通过它提取对象质心

时间:2015-04-17 13:04:34

标签: c++ opencv

我使用OpenCV开发了一个应用程序,它可以检测圆形形状并从二进制图像中获取质心。我现在想删除原始图像中未检测到的对象。所以我想知道是否有解决方案通过其质心从图像中提取对象。

这是我到目前为止所得到的:

enter image description here

for segmentation的结果: enter image description here

// Read image
    cv::Mat im = cv::imread( "11002847.bmp", cv::IMREAD_GRAYSCALE );
    bitwise_not(im, im);
    cv::Mat im2;
    im.copyTo(im2);


    //Detec the contour to get all the obeject centroid
    std::vector<std::vector<cv::Point> > contours;
    vector<cv::Vec4i> hierarchy;
    findContours( im2, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0) );
    vector<cv::Moments> mu(contours.size() );
    for( int i = 0; i < contours.size(); i++ )
    { 
        mu[i] = moments( contours[i], false ); 
    }
    ofstream file;
    file.open("log.txt");
    ///  Get the mass centers:
    vector<cv::Point2f> mc( contours.size() );
    for( int i = 0; i < contours.size(); i++ )
    { 
        mc[i] = cv::Point2f( mu[i].m10/mu[i].m00 , mu[i].m01/mu[i].m00 ); 
        file << mc[i].x << "   "<< mc[i].y << endl;
    } 
    file.close();


    //Dtect the circular objects and get there centroid
    // Setup SimpleBlobDetector parameters.
    cv::SimpleBlobDetector::Params params;
    // Change thresholds
    //params.minThreshold = 10;
    //params.maxThreshold = 200;
    // Filter by Area.
    params.filterByArea = true;
    params.minArea = 1;
    // Filter by Circularity
    params.filterByCircularity = true;
    params.minCircularity = 0.5;
    // Filter by Convexity
    params.filterByConvexity = true;
    params.minConvexity = 0.1;
    // Filter by Inertia
    params.filterByInertia = true;
    params.minInertiaRatio = 0.0;
    // Storage for blobs
    vector<cv::KeyPoint> keypoints;
    // Set up detector with params
    cv::SimpleBlobDetector detector(params);
    // Detect blobs
    detector.detect( im, keypoints);


    ofstream file2;
    file2.open("log2.txt");

    for(vector<cv::KeyPoint>::iterator it = keypoints.begin(); it != keypoints.end(); ++it) 
    {
        cv::KeyPoint k =  *it;
        file2 << k.pt.x << "      "<<  k.pt.y << endl;
    }

    file2.close();
    // Draw detected blobs as red circles.
    // DrawMatchesFlags::DRAW_RICH_KEYPOINTS flag ensures
    // the size of the circle corresponds to the size of blob
    cv::Mat im_with_keypoints;
    drawKeypoints( im, keypoints, im_with_keypoints, cv::Scalar(0,0,255), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS );
    // Show blobs
    cv::imwrite("keypoints.bmp", im_with_keypoints );

1 个答案:

答案 0 :(得分:1)

我希望我理解你的问题,但为了以防万一,我会改写它。您想要删除顶部图像中的轮廓,这些轮廓在底部图像中未被检测为关键点(即在其中/周围没有红色圆圈)。

为了做到这一点,迭代所有contours并使用pointPolygonTest检查每个轮廓是否存在KeyPoints

auto end = contours.end();
for (auto contour_itr = contours.begin(); contour_itr != end; ++contour_itr) {
    auto keypoint_end = keypoints.end();
    for (auto keypoint_itr = keypoints.begin(); keypoint_itr != keypoint_end; ++ keypoint_itr) {
        auto contour = *contour_itr;
        auto keypoint = *keypoint_itr;

        if (cv::pointPolygonTest(contour, keypoint.pt, false) > 0) {
            // do your thing here (e.g. store contour into an array or paint it into a new image
        }
    }
}

希望有所帮助