Deselect SIFT keywords in cell image using OpenCV

I approach the Bio Informatics task and you need to extract some functions from some cell images.

I used the SIFT algorithm to extract the key points inside the image, as you can see in the picture.

enter image description here

As you can see in the picture (circled in red), some key points are outliers, and I do not want to calculate any function on them.

I got a cv::KeyPoint 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 vector all those key points that, say, for example, have less than 3 key points inside a certain region of interest (ROI) centered on them in the image.

Therefore, I need to implement a function that returns the number of key points within a specific ROI specified 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:

  • Is there any existing function that does something like this?
  • If not, can you help me in understanding how to implement it yourself?
  • Would you use a round or rectangular ROI for this task? And how would you indicate it at the entrance?

Note:

I forgot to indicate that I need an effective implementation for the function, i.e. checking for each key point the relative position of everyone else in relation to it will not be a good decision (if there is another way to do it).

+6
source share
1 answer

I decided to go with a statistical route, but this might not work if you have several cells.

My solution is pretty simple:

  • Calculate Keypoint Locations
  • Find the center of gravity of the spatial locations of the key point.
  • Calculate the Euclidean distance of all points to the centroid
  • Filter source cue points distance < mu + 2*sigma

Here is the image I get using this algorithm (key points == green, centroid == red):

enter image description here

Finally, here is a sample code of how I did this:

 #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 this helps!

+8
source

Source: https://habr.com/ru/post/917509/


All Articles