2012-06-07 45 views
6

我正在接近生物信息學的任務,需要從某些細胞圖像中提取一些特徵。用OpenCV捨棄細胞圖像中的異常SIFT關鍵點

我使用SIFT算法來提取圖像中的關鍵點,如圖所示。

enter image description here

正如你也可以看到在圖片(紅圈內),一些關鍵點是外行,我不想來計算他們的任何功能。

我得到的cv::KeyPoint矢量用下面的代碼:

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

但我想從vector所有這些關鍵點是,例如說,有一定的內部小於3個關鍵點丟棄感興趣區域(ROI)集中在圖像中。

因此我需要實現一個函數返回給定的輸入一定的投資回報率的內部關鍵點的數量:

int function_returning_number_of_key_points_in_ROI(cv::KeyPoint, ROI); 
    //I have not specified ROI on purpose...check question 3 

我有三個問題:

  1. 是否有任何現有的功能做相似的東西?
  2. 如果不是,你能幫我理解如何自己實現它嗎?
  3. 你會爲這個任務使用圓形或矩形ROI嗎?你會如何在輸入中指定它?

注:

我忘了指定,我想對功能,即檢查每個關鍵點所有其他的相對位置的有效實施,它不會是一個很好的解決方案(如果存在另一種做法)。

+1

你能張貼原始圖像嗎?我想嘗試一下,然後發回結果,如果它是成功的:) – mevatron

+0

@mevatron - http://s18.postimage.org/jayhj4q3d/phase1_image1.jpg在這裏你走了,我上傳了RGB版本,只要將它轉換爲灰度就可以了......讓我知道你在做什麼;) – Matteo

+0

如果你可以定義一個模型,你可以使用RANSAC。 RANSAC將決定哪些點是inliers(適合模型)和異常值(不適合模型)。也許你的模型可以像3點定義小於X的面積(這意味着它們足夠接近)。這是一個想法。 –

回答

8

我決定走統計路線,但如果您有多個單元格,這可能無法正常工作。

我的解決方法是相當簡單:

  1. 計算關鍵點位置
  2. 找到關鍵點的空間位置
  3. 計算所有點的歐氏距離質心
  4. 過濾原始關鍵點的質心通過distance < mu + 2*sigma

這是圖像,我g等使用這種算法(關鍵點==綠色,心==紅色):

enter image description here

最後,這裏是我是如何做的代碼示例:

#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; 
} 

希望幫助!

+0

其實你提出的解決方案非常簡潔明瞭!但是,正如您注意到的那樣,如果圖像中包含多個單元格,則可能會出現問題。在我的數據集中有一些不好的圖像,但我試圖通過丟棄這些樣本來清除它。現在我會堅持使用這個解決方案,以防萬一尋求進一步的幫助! ;)THKS SOCH ... – Matteo

+2

太棒了!很高興你發現它有用;很酷的問題:)我在想,如果你有多個單元,你可能會做一些類型的聚類操作(K-最近鄰居或類似的)作爲預處理步驟,並以這種方式單獨處理它們。 – mevatron

+1

這是一個生物信息學的項目,我需要通過分析細胞的形態來分類細胞的進化!這只是一個開始;)也意味着k-means的想法很聰明,我會嘗試一下,如果你有興趣找一些方法讓你知道項目的發展。 – Matteo