How to segment the thin skin edge of body parts?

I have 3D image slices of chest. I only want to get the outer skin surface of the chest which will exclude all the organs inside. What kind of segmentation can be applied to get only the skin surface? chest

One option is to propagate the skin boundary, found with thresholding, from boundary with a fast marching or level set filter.

The pixel values of boundary and pixel values of internal organs same. There is no limit difference of pixel values.

Still your approach is possible?

You could do threshold segmentation, shrink it using morphological erosion, then subtract the two - you should be left with a single layer corresponding to outermost part of skin.

If you want your skin to have varying thickness, you could do a few iterations of seeded region growing, starting from the thin skin. You would probably need to modify some existing filters to accomplish this.

Or you could provide even more eroded version of the torso as negative seeds for IsolatedConnectedImageFilter.

1 Like

The skin edges can be used to constrain the segmentation.

Thank You. How to subtract two images. Is there any example in itk?

SubtractImageFilter’s documentation links to many examples.

I used BinaryErodeImageFilter on the image and then did the subtraction from the original to BinaryErodeImageFiltered one using the following code. I am getting the same output. Can you please check what I am doing wrong?

int main( int argc, char *argv[] )
{

  const unsigned int Dimension = 3;
  typedef signed short PixelType;
  typedef itk::Image< PixelType, Dimension >FixedImageType;
  typedef itk::Image< PixelType, Dimension >MovingImageType;

  // Software Guide : EndCodeSnippet
  typedef itk::ImageFileReader< FixedImageType  >FixedImageReaderType;
  typedef itk::ImageFileReader< MovingImageType >MovingImageReaderType;
  FixedImageReaderType::Pointer  fixedImageReader  = FixedImageReaderType::New();
  MovingImageReaderType::Pointer movingImageReader = MovingImageReaderType::New();
  fixedImageReader->SetFileName(  "E:\\Programs\\Morphological Erosion\\input.nii" );
  movingImageReader->SetFileName( "E:\\Programs\\Morphological Erosion\\output.nii" );
  typedef itk::SubtractImageFilter<
                                  FixedImageType,
                                  FixedImageType,
                                  FixedImageType >DifferenceFilterType;
  DifferenceFilterType::Pointer difference = DifferenceFilterType::New();
  difference->SetInput1( fixedImageReader->GetOutput() );
  difference->SetInput2( movingImageReader->GetOutput() );

  typedef signed short OutputPixelType;
  typedef itk::Image< OutputPixelType, Dimension >OutputImageType;
  typedef itk::ImageFileWriter< OutputImageType >WriterType;
  WriterType::Pointer      writer =  WriterType::New();

  writer->SetFileName( "diff.nii");

  writer->SetInput( difference->GetOutput()   );
  writer->Update();


  return EXIT_SUCCESS;
}

In your code snippet, you only show the subtraction. That looks OK.

Can you show us the code for erosion? And an interesting slice (e.g. one from the first post) from stages: input, segmentation, erosion and subtraction?

Thank you for your response. This is the code of the morphological erosion.

int main(int argc, char *argv[])
{
 
  unsigned int radius = 2;
  typedef itk::Image<unsigned char, 3>ImageType;
  typedef itk::ImageFileReader<ImageType>ReaderType;
  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName("input.nii");
  typedef itk::BinaryBallStructuringElement<
    ImageType::PixelType, 3>StructuringElementType;
  StructuringElementType structuringElement;
  structuringElement.SetRadius(radius);
  structuringElement.CreateStructuringElement();
  typedef itk::BinaryErodeImageFilter <ImageType, ImageType, StructuringElementType>BinaryErodeImageFilterType;
  BinaryErodeImageFilterType::Pointer erodeFilter
    = BinaryErodeImageFilterType::New();
  erodeFilter->SetInput(reader->GetOutput());
  erodeFilter->SetKernel(structuringElement);
  typedef itk::ImageFileWriter<ImageType>WriterType;
  WriterType::Pointer writer = WriterType::New();
  writer->SetFileName("output.nii");
  writer->SetInput (erodeFilter->GetOutput());
  writer->Update();

  /*QuickView viewer;
  viewer.AddImage(reader->GetOutput());
  viewer.AddImage(erodeFilter->GetOutput());
  viewer.Visualize();*/
  return EXIT_SUCCESS;
}

slice

Here the same slice I got as output.

That’s the problem. You need a binary segmentation, you seem to be just plugging grayscale image into erosion. Try BinaryThresholdImageFilter with -100 HU as the lower threshold, and pass the output of that into the erosion.

1 Like

I have binarized and then applied the erosion. and then used the subtraction. But I got this kind of output.
slice2

It is pretty noisy, so try a higher threshold. Maybe 0 HU, or 50 HU, or 150 HU etc. Maybe apply connected component filter, and just keep the largest component.

What is your ultimate goal? Segmenting the skin sounds like an intermediate goal.

after the segmentation, I am going to calculate these differences. slice2

Trying to measure degree of pectus excavatum? Or something else? Either way, you will also have to deal with the patient bed somehow. Simple threshold cannot remove it.

Yes. I am gonna measure the degree. I don’t mind even the patient bed is appearing. I just need the outer skin surface.