I'm approaching a task of Bio Informatics, and need to extract some features from some cell images.
I used SIFT algorithm to extract Key Points inside of the image, as you can see in the picture.
As you can also see in the picture (circled in red), some key points are outliers and I don't want to calculate any feature on them.
I obtained the cv::KeyPoint
vector with the following code:
const cv::Mat input = cv::imread("/tmp/image.jpg", 0); //Load as grayscale
cv::SiftFeatureDetector detector;
std::vector<cv::KeyPoint> keypoints;
detector.detect(input, keypoints);
but I would like to discard from the vector
all those key points that, say for example, have less than 3 key points inside of a certain region of interest (ROI) centred on them in the image.
Therefore I need to implement a function returning the number of key points inside of a certain ROI given as input:
int function_returning_number_of_key_points_in_ROI( cv::KeyPoint, ROI );
//I have not specified ROI on purpose...check question 3
I have three questions:
Note:
I forgot to specify that I would like an efficient implementation for the function, i.e. checking for each key point the relative position of all others with respect to it would not be a good solution (if there exists another way of doing).
I decided to go with the statistical route, but this may not work if you have multiple cells in view.
My solution is fairly straightforward:
distance < mu + 2*sigma
Here is the image that I get using this algorithm (keypoints == green, centroid == red):
Finally, here is the code example of how I did it:
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <iostream>
#include <vector>
using namespace cv;
using namespace std;
void distanceFromCentroid(const vector<Point2f>& points, Point2f centroid, vector<double>& distances)
{
vector<Point2f>::const_iterator point;
for(point = points.begin(); point != points.end(); ++point)
{
double distance = std::sqrt((point->x - centroid.x)*(point->x - centroid.x) + (point->y - centroid.y)*(point->y - centroid.y));
distances.push_back(distance);
}
}
int main(int argc, char* argv[])
{
Mat input = imread("cell.jpg", 0); //Load as grayscale
SiftFeatureDetector detector;
vector<cv::KeyPoint> keypoints;
detector.detect(input, keypoints);
vector<Point2f> points;
vector<KeyPoint>::iterator keypoint;
for(keypoint = keypoints.begin(); keypoint != keypoints.end(); ++keypoint)
{
points.push_back(keypoint->pt);
}
Moments m = moments(points, true);
Point2f centroid(m.m10 / m.m00, m.m01 / m.m00);
vector<double> distances;
distanceFromCentroid(points, centroid, distances);
Scalar mu, sigma;
meanStdDev(distances, mu, sigma);
cout << mu.val[0] << ", " << sigma.val[0] << endl;
vector<KeyPoint> filtered;
vector<double>::iterator distance;
for(size_t i = 0; i < distances.size(); ++i)
{
if(distances[i] < (mu.val[0] + 2.0*sigma.val[0]))
{
filtered.push_back(keypoints[i]);
}
}
Mat out = input.clone();
drawKeypoints(input, filtered, out, Scalar(0, 255, 0));
circle(out, centroid, 7, Scalar(0, 0, 255), 1);
imshow("kpts", out);
waitKey();
imwrite("statFilter.png", out);
return 0;
}
Hope that helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With