1

here is my matlab code:

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

the number of object which is found here is 18;

here is my openCV and cvBlobs code

//regionprops(bwImg, 'Area');
// cDist=[cDist.Area]
dst.convertTo(dst,CV_8U);
cv::vector<cv::vector<cv::Point> > contours_1;
cv::vector<cv::Vec4i> hierarchy_1;
cv::findContours(dst,contours_1,hierarchy_1,CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE);

//DEBUG contours
cv::Mat drawing1 = cv::Mat::zeros(dst.size(),CV_8UC3);  
for (int i = 0; i < contours_1.size(); i++)
{
    cv::RNG rng(12345);
    cv::Scalar color = cv::Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
    drawContours( drawing1, contours_1, i, color, 2, 8, hierarchy_1, 0, cv::Point() );
}

std::vector<cv::Moments> mu(contours_1.size());
for (int i = 0; i < contours_1.size(); i++)
{
    mu[i] = cv::moments(contours_1[i],false);
}
vector<cv::Point2f> mc( contours_1.size() );
for( int i = 0; i < contours_1.size(); i++ )
{ 
    mc[i] = cv::Point2f( mu[i].m10/mu[i].m00 , mu[i].m01/mu[i].m00 ); 
}

/// Draw contours
cv::Mat drawing = cv::Mat::zeros(dst.size(),CV_8UC3);   
for (int i = 0; i < contours_1.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( drawing, contours_1, i, color, 2, 8, hierarchy_1, 0, cv::Point() );
    cv::circle( drawing, mc[i], 4, color, -1, 8, 0 );
}

double maxLabelSize = (dst.rows/4.0) * (dst.cols/6.0);
double minLabelSize = ((dst.rows/40.0) * (dst.cols/60.0));

//% 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

IplImage* img_bw_1 = new IplImage(dst);
CBlobResult blobs_1;
CBlob *currentBlob;
blobs_1 = CBlobResult(img_bw_1, NULL, 0);

blobs_1.Filter( blobs_1, B_EXCLUDE, CBlobGetArea(), B_LESS, minLabelSize);
blobs_1.Filter(blobs_1,B_EXCLUDE,CBlobGetArea(),B_GREATER,maxLabelSize);
// Get the number of blobs discovered
int num_blobs = blobs_1.GetNumBlobs(); 

// Display the filtered blobs
IplImage* filtered = cvCreateImage( cvGetSize( img_bw_1 ),
    IPL_DEPTH_8U,
    3 );    

for ( int i = 0; i < num_blobs; i++ )
{
    currentBlob = blobs_1.GetBlob( i );
    currentBlob->FillBlob( filtered, CV_RGB(30+i*10,30+i*10,30+i*10));
}

img_bw_1 = NULL;
delete img_bw_1;
currentBlob= NULL;
delete currentBlob;


/*% Fill any holes in the objects
bwImgLabeled = imfill(bwImgLabeled,'holes');*/
dst = filtered;
cv::floodFill(dst, cv::Point(1,1), CV_RGB(0,0,0));     

/*% Re-label the result image objects
bwImgLabeled(bwImgLabeled>0) = 1;
[bwImgLabeled, nObjs] = bwlabel(bwImgLabeled);*/

cv::threshold(dst, dst, 0 ,30,CV_THRESH_BINARY);

the result here is 17 objects.

Can you please check what I have done wrong?is it something which has to do with precision? float in openCV vs. double in matlab? is it because of the different implementation of matlab and openCV?

I suspect these lines:

blobs_1.Filter( blobs_1, B_EXCLUDE, CBlobGetArea(), B_LESS, minLabelSize);
blobs_1.Filter(blobs_1,B_EXCLUDE,CBlobGetArea(),B_GREATER,maxLabelSize);

because the number of element from this blobs_1 = CBlobResult(img_bw_1, NULL, 0); is 271 and the areas of the blobs which are found in cvblobslib is different from what is found in matlab's regionprops - which returns 261 blobs with different area sizes

Gilad
  • 6,437
  • 14
  • 61
  • 119

1 Answers1

0

this is my final working solution hope it helps someone it the future. I'm using openCV 2.4.10. there is no need to use cvBlobs. openCV findContours and drawContours can do almost anything it does. just have to play with the right flags of the functions.

    bwImg.convertTo(bwImg,CV_8U);
    cv::vector<cv::vector<cv::Point> > contours_1;
    cv::findContours(bwImg,contours_1,CV_RETR_TREE,CV_CHAIN_APPROX_NONE,cv::Point(0,0));
    //DEBUG contours
    cv::Mat drawing1 = cv::Mat::zeros(bwImg.size(),CV_8UC3);    

    for (int i = 0; i < contours_1.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(drawing1,contours_1,i,color,CV_FILLED);
    }   
    //% 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);
    double maxLabelSize = (bwImg.rows/4.0) * (bwImg.cols/6.0);
    double minLabelSize = ((bwImg.rows/40.0) * (bwImg.cols/60.0));


    //  % Remove over/undersized objects
    //  for n=1:length(remInd)
    //      ri = bwImgLabeled == remInd(n);
    //      bwImgLabeled(ri) = 0;
    //  end
    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)
        {
            goodContours.push_back(contours_1[i]);
        }
    }

    cv::Mat filterContours = cv::Mat::zeros(bwImg.size(),CV_8UC3);  
    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);        
    }

    /*% Fill any holes in the objects
    bwImgLabeled = imfill(bwImgLabeled,'holes');*/


    imageData = filterContours;
    /*% Re-label the result image objects
    bwImgLabeled(bwImgLabeled > 0) = 1;*/
    cv::threshold(imageData, imageData, 0 ,254,CV_THRESH_BINARY);
    cv::imshow("threshold", imageData);
    cv::waitKey(0);
Gilad
  • 6,437
  • 14
  • 61
  • 119