2
$\begingroup$

I have segmented CT images, something like the following one:

enter image description here

I would like to get a convex hull that contains all the white regions. Something like this circle, but more fitting, and of course not necessarily a cicle.

enter image description here

I've already tried this example https://stackoverflow.com/questions/11813352/finding-the-convex-hull-of-an-object-in-opencv but I've only got this output:

enter image description here

$\endgroup$

1 Answer 1

2
$\begingroup$

Try dilation, a technique used to enlargen light spots over darker spots in an image.

Start by dilating the image such that many of the enlargened white blobs will overlap and form a complete connected contour, as such:

enter image description here

Now, when OpenCV finds contours from this large figure to make convex hulls, it will find a complete circle rather than loose seperate blobs.

enter image description here

From here, you can find the largest contour, which is the (outer) largest light-purple contour.

Here is the code for this (which currently computes the contours, but not the largest area - this is just to demonstrate the dilation):

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>

using namespace cv;
using namespace std;

int main( int argc, char** argv )
{
 Mat src; Mat src_gray;
 src = imread( "convex.jpg", 1 );
 //resize(src, src, Size(640,480), 0, 0, INTER_CUBIC);
 cvtColor( src, src_gray, CV_BGR2GRAY );

 namedWindow( "Source", CV_WINDOW_AUTOSIZE );



 //Dilate
 int erosion_size =10;
  Mat element = getStructuringElement(cv::MORPH_ELLIPSE,
        cv::Size(2 * erosion_size + 1, 2 * erosion_size + 1),
        cv::Point(erosion_size, erosion_size) );

 dilate(src_gray,src_gray,element);

 imshow( "Source", src_gray );

 // Convex Hull implementation
 Mat src_copy = src_gray.clone();
 Mat threshold_output;
 vector<vector<Point> > contours;
 vector<Vec4i> hierarchy;

 // Find contours
 threshold( src_gray, threshold_output, 200, 255, THRESH_BINARY );
 findContours( threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );

 // Find the convex hull object for each contour
 vector<vector<Point> >hull( contours.size() );
 for( int i = 0; i < contours.size(); i++ )
 {  convexHull( Mat(contours[i]), hull[i], false ); }

 // Draw contours + hull results
 RNG rng;
 Mat drawing = Mat::zeros( threshold_output.size(), CV_8UC3 );
 for( int i = 0; i< contours.size(); i++ )
 {
  Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
  //drawContours( drawing, contours, i, color, 1, 8, vector<Vec4i>(), 0, Point() );
  drawContours( drawing, hull, i, color, 1, 8, vector<Vec4i>(), 0, Point() );
 }

 // Show in a window
 namedWindow( "Hull demo", CV_WINDOW_AUTOSIZE );
 imshow( "Hull demo", drawing );

 waitKey(0);
 return(0);
}
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.