2012-06-07 70 views
6

Tôi đang tiếp cận một nhiệm vụ về Tin học sinh học và cần trích xuất một số tính năng từ một số hình ảnh ô.Loại bỏ các điểm khóa SIFT ngoại vi trong hình ảnh di động bằng OpenCV

Tôi đã sử dụng thuật toán SIFT để trích xuất các điểm chính bên trong hình ảnh, như bạn có thể thấy trong hình.

enter image description here

Như bạn cũng có thể nhìn thấy trong hình (vòng tròn màu đỏ), một số điểm chính là giá trị ngoại biên và tôi không muốn để tính toán bất kỳ tính năng trên chúng.

tôi đắc vector cv::KeyPoint với đoạn mã sau:

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

nhưng tôi muốn hủy từ vector tất cả những điểm quan trọng mà, nói ví dụ, còn lại ít hơn 3 điểm quan trọng bên trong của một số khu vực quan tâm (ROI) tập trung vào chúng trong hình ảnh.

Vì vậy, tôi cần phải thực hiện một hàm trả về số lượng các điểm then chốt bên trong một ROI nhất định cho là đầu vào:

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

tôi có ba câu hỏi sau:

  1. Có bất kỳ chức năng hiện thực một cái gì đó tương tự?
  2. Nếu không, bạn có thể cho tôi một số trợ giúp trong việc hiểu cách tự mình thực hiện nó không?
  3. Bạn có sử dụng ROI hình tròn hoặc hình chữ nhật cho tác vụ này không? Và bạn sẽ chỉ định nó như thế nào trong đầu vào?

Lưu ý:

Tôi quên để xác định rằng tôi muốn một thực hiện hiệu quả chức năng, tức là kiểm tra cho mỗi điểm mấu chốt vị trí tương đối của tất cả những người khác liên quan đến nó sẽ không phải là một giải pháp tốt (nếu có một cách khác để làm).

+1

Bạn có thể đăng hình ảnh gốc không? Tôi muốn thử một cái gì đó, và sau đó gửi lại các kết quả nếu nó thành công :) – mevatron

+0

@mevatron - http://s18.postimage.org/jayhj4q3d/phase1_image1.jpg ở đây bạn đi, tôi đã tải lên phiên bản RGB, chỉ cần chuyển đổi nó thành màu xám nếu bạn whish .... cho tôi biết những gì bạn đang làm;) – Matteo

+0

Bạn có thể sử dụng RANSAC, nếu bạn có thể xác định một mô hình. RANSAC sẽ quyết định điểm nào là các ngoại lệ (phù hợp với mô hình) và các ngoại lệ (không phù hợp với mô hình). Có lẽ mô hình của bạn có thể giống như 3 điểm xác định một khu vực nhỏ hơn X (có nghĩa là chúng đủ gần). Đó là một ý tưởng. –

Trả lời

8

Tôi quyết định đi theo tuyến thống kê, nhưng điều này có thể không hoạt động nếu bạn có nhiều ô trong chế độ xem.

Giải pháp của tôi là khá đơn giản:

  1. Tính các địa điểm keypoint
  2. Tìm trọng tâm trong những địa điểm không gian keypoint
  3. Tính khoảng cách Euclide của tất cả các điểm đến trọng tâm
  4. Lọc keypoint gốc bởi distance < mu + 2*sigma

Đây là hình ảnh tôi g et sử dụng thuật toán này (keypoint == xanh, trọng tâm == đỏ):

enter image description here

Cuối cùng, đây là ví dụ mã như thế nào tôi đã làm nó:

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

Hy vọng rằng sẽ giúp!

+0

Thực ra giải pháp bạn đề xuất thực sự gọn gàng và dễ hiểu !! Tuy nhiên, như bạn nhận thấy, điều này có thể có vấn đề khi nhiều hơn một tế bào được chứa trong hình ảnh. Trong tập dữ liệu của tôi có một số hình ảnh xấu, nhưng tôi đang cố gắng làm sạch nó bằng cách loại bỏ các mẫu đó. Tôi sẽ dính vào giải pháp này ngay bây giờ, và trong trường hợp yêu cầu giúp đỡ thêm! ;) THKS SO MUCH ... – Matteo

+2

Tuyệt vời! Thật vui khi bạn thấy nó hữu ích; Tôi đã suy nghĩ nếu bạn có nhiều tế bào bạn có thể làm một số loại hoạt động phân cụm (hàng xóm K-gần nhất hoặc một cái gì đó tương tự) như một bước xử lý trước, và xử lý chúng một cách riêng biệt theo cách đó. – mevatron

+1

Đó là một dự án trong Tin sinh học, tôi cần phân loại sự tiến hóa của các tế bào bằng cách phân tích hình thái của chúng! Và đây chỉ là khởi đầu;) ý tưởng k-means có vẻ thực sự thông minh, tôi sẽ thử nó và nếu bạn quan tâm tìm cách nào đó để cho bạn biết sự tiến hóa của dự án. – Matteo

Các vấn đề liên quan