1

Description

I have a lung cancer CT scan image, that I want to segment and extract the cancerous areas from. I have used Open CV and Java.

I have the following image as input:

original image

After segmentation with thresholding and watershed method, I get this result:

original image

After that, I want to extract the cancerous area from the segmented image, so I have to remove all noise and other objects outside the region of interest (the cancerous nodule). So like shown in image below, I want to extract the cancerous nodule like this:

original image

How can I achieve this in android using OpenCV?

stateMachine
  • 5,227
  • 4
  • 13
  • 29
Aemon
  • 13
  • 5
  • The problem is that the cancerous area is attached to the rest of the blobs in the binary image. You can try to separate it using a little bit of morphology. Try an `erode` operation of maybe a couple of iterations. Once you successfully separate the two blobs, implement an area filter, as the blob with the largest area is noise. Filter out the smaller blob. Then, try to restore the original size using a `dilate` operation of the same number of iterations as your original `erode` op. – stateMachine Mar 26 '20 at 08:29
  • i'm really in need of help with this question, can you help me, please? https://stackoverflow.com/questions/61216402/how-to-improve-image-segmentation-using-the-watershed – Carlos Diego Apr 28 '20 at 17:18

2 Answers2

0

Why you don't use deep neural network called MobileUNet which is used for semantic segmentation problem.I just mention that it has a pretty simple design. It is available for both IOS and Android.

You can see more details in Github repository. https://github.com/akirasosa/mobile-semantic-segmentation

Faisal Shahbaz
  • 431
  • 3
  • 12
0

I tried to implement my suggested solution. My answer is in C++, but the idea is simple, you should be able to implement it in Java. As I commented, the idea is to use morphology to get the blob of interest. Mainly, the erode operation. Let's see:

   //Read input image:
   std::string imagePath = "C://opencvImages//lungsImage.png";
   cv::Mat imageInput= cv::imread( imagePath );

   //Convert it to grayscale:
   cv::Mat grayImg;
   cv::cvtColor( imageInput, grayImg, cv::COLOR_BGR2GRAY );

The first step is to obtain a binary image. It seems you implemented Watershed segmentation. That's ok. I tried applying a simple adaptive thresholding with a big window (601 in size, for this case). It gave me good results:

    //Get the binary image:
    cv::adaptiveThreshold( grayImg, grayImg, 255, cv::ADAPTIVE_THRESH_GAUSSIAN_C, cv::THRESH_BINARY, 601, 10 );

This is the result you get:

enter image description here

Now, there are multiple blobs. However, I’ll be looking for the biggest blob, as that is where our target region of interest is located. Searching for the biggest blob in a binary image is a task I often carry out, so I have prepared a function for this. It is called findBiggestBlob. I’ll present the function later. Check out the result you get after filtering out the smaller blobs:

    //Get the biggest blob in the binary image
    cv::Mat targetBlobs = findBiggestBlob( grayImg );

This is the result:

enter image description here

Now, simply apply morphology. First, an erode operation. Use an ellipse structuring element of size 5 x 5 with 4 iterations to detach the blob of interest:

    //Apply erosion to the biggest blob mask;
    cv::Mat morphKernel = cv::getStructuringElement( cv::MORPH_ELLIPSE, cv::Size(5, 5) );
    int morphIterations = 4; // use 4 iterations
    cv::morphologyEx( targetBlobs, targetBlobs, cv::MORPH_ERODE, morphKernel, cv::Point(-1,-1), morphIterations );

Check out the result, the blob of interest is now detached:

enter image description here

Now, the idea is simple. If we, again, extract the biggest blob of the image, we should end up with the lungs, free from the cancerous area. Then, subtract this image to the “detached” mask, we should end up with the blob of interest in one mask:

    //Get the lungs image:
    cv::Mat bigBlob = findBiggestBlob( targetBlobs );

You get this:

enter image description here

    //Subtract the lungs from the first binary mask:
    cv::Mat blobOfInterest = targetBlobs - bigBlob;

Now, let's restore the blob's original size applying a dilate operation, use the same structuring element and the same number of iterations. This is the result:

enter image description here

    //Restore the blob's original size:
    cv::morphologyEx( blobOfInterest, blobOfInterest, cv::MORPH_DILATE, morphKernel, cv::Point(-1,-1), morphIterations );

Here's the blob (in red) overlaid onto the original image:

enter image description here

This is the code for the findBiggestBlob function. The idea is just to compute all the contours in the binary input, calculate their area and store the contour with the largest area of the bunch:

//Function to get the largest blob in a binary image:
cv::Mat findBiggestBlob( cv::Mat &inputImage ){

    cv::Mat biggestBlob = inputImage.clone();

    int largest_area = 0;
    int largest_contour_index=0;

    std::vector< std::vector<cv::Point> > contours; // Vector for storing contour
    std::vector<cv::Vec4i> hierarchy;

    // Find the contours in the image
    cv::findContours( biggestBlob, contours, hierarchy,CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE ); 

    for( int i = 0; i< (int)contours.size(); i++ ) {            

        //Find the area of the contour            
        double a = cv::contourArea( contours[i],false);
        //Store the index of largest contour:
        if( a > largest_area ){
            largest_area = a;                
            largest_contour_index = i;
        }

    }

    //Once you get the biggest blob, paint it black:
    cv::Mat tempMat = biggestBlob.clone();
    cv::drawContours( tempMat, contours, largest_contour_index, cv::Scalar(0),
                  CV_FILLED, 8, hierarchy );

    //Erase the smaller blobs:
    biggestBlob = biggestBlob - tempMat;
    tempMat.release();
    return biggestBlob;
}
stateMachine
  • 5,227
  • 4
  • 13
  • 29
  • i'm really in need of help with this question, can you help me, please? https://stackoverflow.com/questions/61216402/how-to-improve-image-segmentation-using-the-watershed – Carlos Diego Apr 28 '20 at 17:18