【问题标题】:How to Remove Small Objects from Image after Segmentation分割后如何从图像中删除小对象
【发布时间】:2020-07-06 20:15:34
【问题描述】:

说明

我有一张肺癌 CT 扫描图像,我想从中分割和提取癌变区域。我使用过 Open CV 和 Java。

我有以下图像作为输入:

用阈值和分水岭方法分割后,我得到了这个结果:

之后,我想从分割后的图像中提取癌变区域,因此我必须去除感兴趣区域(癌结节)之外的所有噪声和其他物体。所以如下图所示,我想像这样提取癌性结节:

如何使用 OpenCV 在 android 中实现这一点?

【问题讨论】:

  • 问题是癌变区域附着在二进制图像中的其余斑点上。您可以尝试使用一点形态学将其分开。尝试可能进行几次迭代的erode 操作。成功分离两个斑点后,实施面积过滤器,因为面积最大的斑点是噪声。过滤掉较小的斑点。然后,尝试使用与原始erode 操作相同的迭代次数的dilate 操作恢复原始大小。
  • 我真的需要帮助解决这个问题,你能帮帮我吗? stackoverflow.com/questions/61216402/…

标签: java android opencv image-processing feature-extraction


【解决方案1】:

为什么你不使用称为 MobileUNet 的深度神经网络来解决语义分割问题。我只是提到它的设计非常简单。它适用于 IOS 和 Android。

您可以在 Github 存储库中查看更多详细信息。 https://github.com/akirasosa/mobile-semantic-segmentation

【讨论】:

    【解决方案2】:

    我尝试实施我建议的解决方案。我的答案是用 C++,但想法很简单,你应该能够用 Java 实现它。正如我所评论的,这个想法是使用形态学来获得感兴趣的斑点。主要是侵蚀操作。让我们看看:

       //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 );
    

    第一步是获取二值图像。您似乎实现了分水岭分割。没关系。我尝试使用一个大窗口(@98​​7654335@ 大小,在这种情况下)应用一个简单的自适应阈值。它给了我很好的结果:

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

    这是你得到的结果:

    现在,有多个 blob。但是,我将寻找最大的斑点,因为那是我们感兴趣的目标区域所在的位置。在二进制图像中搜索最大的斑点是我经常执行的任务,因此我为此准备了一个函数。它被称为findBiggestBlob。稍后我将介绍该功能。查看过滤掉较小的 blob 后得到的结果:

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

    这是结果:

    现在,只需应用形态。首先,erode 操作。使用 5 x 5 大小的 ellipse 结构元素和 4 迭代来分离感兴趣的 blob:

        //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 );
    

    查看结果,感兴趣的 blob 现在已分离:

    现在,这个想法很简单。如果我们再次提取图像中最大的斑点,我们应该得到没有癌变区域的肺。然后,将此图像减去“分离”的蒙版,我们应该在一个蒙版中得到感兴趣的斑点:

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

    你明白了:

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

    现在,让我们应用 dilate 操作恢复 blob 的原始大小,使用相同的结构元素和相同的迭代次数。结果是这样的:

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

    这是覆盖在原始图像上的斑点(红色):

    这是findBiggestBlob 函数的代码。这个想法只是计算二进制输入中的所有轮廓,计算它们的面积并存储具有最大面积的轮廓:

    //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;
    }
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-05
    • 2021-12-06
    • 2020-06-04
    • 2018-03-30
    • 1970-01-01
    • 2020-02-10
    • 2014-08-30
    • 2015-07-01
    相关资源
    最近更新 更多