# How to compute intersections of two contours

I have 2 contours and I want to compare how much the same are they, as the ratio of the area_of_c1/area_of_intersection and area_of_c2/area_of_intersection. I have done in a way of creating 2 convex contours and 2 Mats of zeros and fill them with fillConvexPoly() and doing a bitwise_and() between the two Mats for getting the intersection. Then I have counting the non zeros pixels for getting the areas and computed the ratios. Is there another more efficient way of computing the two ratios (like computing the intersection of two contours, or I do not know)?

edit retag close merge delete

Nope, what you are doing was exactly what I would have suggested.

( 2014-07-17 04:16:46 -0500 )edit
1

Instead of a bitwes_and, I would suggest sum areas, with an image of 1's and an image of 2's (for example) and count 1's, 2's and 3's to get all areas in the same time. But nothing really better I'm afraid… ;-)

( 2014-07-17 04:51:36 -0500 )edit

Sort by » oldest newest most voted

Sounds ok. (i guess you now cv::countNonZero). If you have many(!) contours and run into speed or accuracy problems, a specialized library like CGAL https://www.cgal.org/ could help you. You compute an approximation of the intersection area whose accuracy depends on the resolution of the image in which you draw the regions. This can be perfectly fine if your regions are nice (no sharp spikes or one-Pixel regions) but if you get problems, an analytical solution (e.g. as implemented in CGAL) could help.

more

I do not think I need that, because I have convex contours. Is fillConvecPoly faster than fillPoly?

( 2014-07-17 06:17:22 -0500 )edit
2

"The function fillConvexPoly draws a filled convex polygon. This function is much faster than the function fillPoly ."

( 2014-07-17 08:18:58 -0500 )edit

shall I use if (cv::isContourConvex(c)) {cv::convexHull(c, cc);} or just cv::convexHull(c, cc);?

( 2014-07-17 11:06:17 -0500 )edit

I don't know if the fillcomplexpolly is computationally heavy or not, so I do it another (very similar) way.

I create a Mask where I draw a rectangle corresponding to the bounding box of the blob, and then use logical "and" between mask and the image with the blobs to segment the blob from everything else. The rest of the process is the same. Try it, I have no idea which method is more optimized.

This code snippet calculates the ration between contour 1 and 2 of blobImage.

    cv::findContours(blobImage, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);

cv::Mat mask1 = cv::Mat::zeros(height, width, CV_8UC1);
cv::Mat mask2 = cv::Mat::zeros(height, width, CV_8UC1);

cv::rectangle(mask1, cv::boundingRect(contours[0]), 255, -1, 8 ,0);
cv::rectangle(mask2, cv::boundingRect(contours[1]), 255, -1, 8 ,0);

cv::Mat intersection1 = (mask1 && blobImage) // binary image with only with blob 1
cv::Mat intersection2 = (mask2 && blobImage) // binary image with only with blob 2

cv::Scalar sum1 = cv::sum(intersection1);
cv::Scalar sum2 = cv::sum(intersection2);

double ratio = (sum1[0] / sum2[0]);

more

Official site

GitHub

Wiki

Documentation