FindContours hirerarcy issue
I'm trying to convert the following Matlab code into openCV. My code works really great for most of the examples I have(~700), except this one.
Original Image
Here is the matlab output:
Here is the openCV output:
Here is what happens when I remove CV_Fill:
% Convert to BW image
bwImg = im2bw(imageData, grayThresh);
% If we end up with totally black or white image return false status.
if all(bwImg(:)) || all(~bwImg(:))
status = false;
cornerXY = [];
centroidXY = [];
centroidMedianDistance = [];
return;
end
% Calculate each separated object area
cDist=regionprops(bwImg, 'Area');
cDist=[cDist.Area];
% Label each object
[bwImgLabeled, ~]=bwlabel(bwImg);
% Calculate min and max object size based on assumptions on the color
% checker size
maxLabelSize = prod(size(imageData)./[4 6]);
minLabelSize = prod(size(imageData)./[4 6]./10);
% Find label indices for objects that are too large or too small
remInd = find(cDist > maxLabelSize);
remInd = [remInd find(cDist < minLabelSize)];
% Remove over/undersized objects
for n=1:length(remInd)
ri = bwImgLabeled == remInd(n);
bwImgLabeled(ri) = 0;
end
% Fill any holes in the objects
bwImgLabeled = imfill(bwImgLabeled,'holes');
% Re-label the result image objects
bwImgLabeled(bwImgLabeled>0) = 1;
[bwImgLabeled, nObjs] = bwlabel(bwImgLabeled);
Here is my C++/OpenCV code
cv::Mat bwImg = Utilities::im2bw(imageData, grayThresh);
double sum = cv::sum(bwImg)[0];
if(sum == bwImg.rows * bwImg.cols||sum == 0 )
{
return AutomaticMacbethDetectionResults(false);
}
cv::vector<cv::vector<cv::Point> > contours_1;
cv::vector<cv::Vec4i> hierarchy_1;
cv::findContours(bwImg,contours_1,hierarchy_1,CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE,cv::Point(0,0));*/
bwImg.convertTo(bwImg,CV_8U);
cv::vector<cv::vector<cv::Point> > contours_1;
cv::vector<cv::Vec4i> hierarchy;
cv::findContours(bwImg,contours_1,hierarchy,CV_RETR_TREE,CV_CHAIN_APPROX_NONE,cv::Point(0,0));
double maxLabelSize = (bwImg.rows/4.0) * (bwImg.cols/6.0);
double minLabelSize = ((bwImg.rows/40.0) * (bwImg.cols/60.0));
//OPENCV hierarchy *[Next, Previous, First_Child, Parent]**
// http://docs.opencv.org/master/d9/d8b/tutorial_py_contours_hierarchy.html#gsc.tab=0
cv::vector<cv::vector<cv::Point> > goodContours;
for (int i = 0; i < contours_1.size(); i++)
{
double size = cv::contourArea(contours_1[i]);
if (size < maxLabelSize && size > minLabelSize) //I added my check for hierarachy[i][2] ==-1 here!
{
goodContours.push_back(contours_1[i]);
}
}
cv::Mat filterContours = cv::Mat::zeros(bwImg.size(),CV_8UC3);
bwImg.release();
for (int i = 0; i < goodContours.size(); i++)
{
cv::RNG rng(12345);
cv::Scalar color = cv::Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
cv::drawContours(filterContours,goodContours,i,color,CV_FILLED);
}
imageData = filterContours;
filterContours.release();
/*% Re-label the result image objects
bwImgLabeled(bwImgLabeled > 0) = 1;*/
cv::threshold(imageData, imageData, 0 ,254,CV_THRESH_BINARY);
so as far as I understand I can use the Hierarchy feature in order to understand if there is a contour which holds other contours. Hierarchy
and I added a switch to check for hierarchy[i][2] == -1 (meaning it has no children)
however this ruins my results for other images. Can you please explain the difference between regionprops and findcontours? and maybe suggests a way to solve my issue?
when you use cv::drawContours(filterContours,goodContours,i,color,CV_FILLED); contour interior is filled so opencv result is logic.
Without seeing original image I have got some difficulties to understand but may be you shouls add your hierachy test before filled (may be with a parity test too)
@LBerger I added the original image, I don't know what you mean by parity test.. Can you explain please?
If you find a contour it means that color changed dark to light and if you v've got another contour inside I think that it is light to dark and so on. In your problem you don't need to fill all shape or may be changed color
@gdarmon: if you include that hierachy[i][2]==-1 check everything is fine so, what is your problem with the rest of your images in that case (can you provide an example)? Anyway, you may want to switch to OpenCV 3.0 (if not using it already) and try the connectedComponents function - findContours is not really the equivalent of regionProps because it does not look for connected components