openCV和cvBlobs没有给出与matlab相同的结果

时间:2015-03-26 22:28:11

标签: c++ matlab opencv image-processing cvblobslib

这是我的matlab代码:

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

这里找到的对象数是18;

这是我的openCV和cvBlobs代码

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

这里的结果是17个对象。

请你检查我做错了什么?它是否与精确度有关?浮动在openCV与matlab中的double?是因为matlab和openCV的实现不同?

我怀疑这些界限:

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

因为来自此blobs_1 = CBlobResult(img_bw_1, NULL, 0);的元素数是271,而cvblobslib中找到的blob区域与matlab的regionprops中找到的区域不同 - 它返回具有不同区域大小的261个blob

1 个答案:

答案 0 :(得分:0)

这是我最后的工作解决方案,希望它可以帮助未来的某个人。 我使用的是openCV 2.4.10。没有必要使用cvBlobs。 openCV findContours和drawContours几乎可以做任何事情。 只需要使用功能的正确标志。

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