Reputation: 125
I have developed an application using OpenCV
that detects circularity form and get there centroid from a binary image. I want now to delete object that has not been detected from my original image. So I want to know if there is a solution to extract an object from an image by its centroid.
Here is what I have got so far:
The result of the for segmentation :
// 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 );
Upvotes: 1
Views: 333
Reputation: 6822
I hope I understood your problem, but just in case, I will rephrase it. You want to remove the contours from your top image, which have not been detected as keypoints (i.e. don't have red circles in/around them) in the bottom image.
In order to do this, iterate over all your contours
and check each contour for presence of KeyPoints using pointPolygonTest
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
}
}
}
Hope that helps
Upvotes: 1