inferno
inferno

Reputation: 1261

shapes detection - contour approximation with OpenCV

I'm writing small application for shape detections. What I need to do in a first place is to find the most significant shape on an image. I started from some preprocessing including converting image to grayscale, thresholding and edge detection. Image before and after these operations is presented below

Before

enter image description here

After

enter image description here

So as You can see the main shape is visible (however it is a bit scattered) and there are also some noises (small trees etc). What I need to do is to extract somehow only the most significant shape (the biggest one) - in this case it is a tower. What I wanted to do is use contour finding function in opencv and then somehow aproximate found conturs with polygon. Then I would (somehow) calculate area of countours and select only the biggest one. So far I manged (only) to find contours using

cvFindContours(crated,g_storage,&contours);

I know that there is a

cvApproxPoly

function , however I am not able to get any usefull information for the result of this function. Could somebody tell me if it is possible to calculate area of contour or to approximate the contur with polygon. Maybe You have a better idea how to extract only the most significant shape ?

Upvotes: 15

Views: 11180

Answers (4)

Moacir Ponti
Moacir Ponti

Reputation: 591

If you always have a controlled background, I would go for these steps (as suggested also by @damian):

  1. Binarization, i.e., creating an image such as the background = 0 and the object regions = 1 (or 255). After that, you will have several white regions on your image. There are several method to do this, but if your background is controled you can use a fixed threshold. Note that here you have removed noise inside the objects. In the binary image you can always use morphological opening/closing in order to smooth out the objects
  2. Use cvFindContours to find all objects: it should be easier now.
  3. Fill the smaller contours with the background colour by using cvFloodFill.

Upvotes: 7

Sasha
Sasha

Reputation: 21

You can use morphological operations for suppressing your "contour noise" (dilation in your case). But you have to remember that usability of morphological operations depends on current task. For example, if you have two objects that placed close each other, dilation can do one object from them.

Upvotes: 2

damian
damian

Reputation: 3674

You don't have to do edge detection here. Just threshold to a binary image and then find blobs (cvFindContours) on that. You can use cvContourArea on each returned CvSeq to find its area.

Upvotes: 8

Piotr Praszmo
Piotr Praszmo

Reputation: 18320

Your main problem is that the tower contour is scattered. It will be hard to recreate whole contour from those little pieces. Optimize your edge detection phase (try cvAdaptiveThreshold), or use different approach (maybe something like object segmentation)

After you have your contour in one piece, you can check its area like this:

CvSeq* convex_hull=cvConvexHull2( contour, storage, CV_CLOCKWISE, 2 );
CvSeq* quad=cvApproxPoly(convex_hull, sizeof(CvContour), storage, CV_POLY_APPROX_DP, cvContourPerimeter(contour)*0.02, 0);
float size=fabs(cvContourArea( quad,CV_WHOLE_SEQ,0 ));

You will need to tune the parameters. It was used to detect rectangles.

Upvotes: 5

Related Questions