2012-06-07 13 views
6

Mi sto avvicinando a un compito di BioInformatica e ho bisogno di estrarre alcune caratteristiche da alcune immagini di celle.Scartare i punti chiave SIFT con OpenCV nell'immagine cella

Ho usato l'algoritmo SIFT per estrarre i punti chiave all'interno dell'immagine, come potete vedere nell'immagine.

enter image description here

Come si può anche vedere nella foto (cerchiato in rosso), alcuni punti chiave sono valori erratici e non voglio per calcolare qualsiasi funzione su di loro.

ho ottenuto il cv::KeyPoint vettore con il seguente codice:

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

ma vorrebbe eliminare dalle vector tutti quei punti chiave che, diciamo per esempio, hanno meno di 3 punti chiave all'interno di un certo regione di interesse (ROI) centrata su di essi nell'immagine.

Quindi ho bisogno di implementare una funzione che restituisce il numero dei punti chiave all'interno di una certa ROI dato come input:

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

Ho tre domande:

  1. C'è qualche funzione esistente fare qualcosa di simile?
  2. Se no, puoi darmi un aiuto per capire come implementarlo da solo?
  3. Utilizzeresti una ROI circolare o rettangolare per questa attività? E come la specificheresti in input?

Nota:

ho dimenticato di specificare che vorrei un'implementazione efficace per la funzione, vale a dire il controllo per ogni punto fondamentale la posizione relativa di ogni altro rispetto ad essa non sarebbe una buona soluzione (se esiste un altro modo di fare).

+1

Puoi postare l'immagine originale? Mi piacerebbe provare qualcosa, e poi postare i risultati se ha successo :) – mevatron

+0

@mevatron - http://s18.postimage.org/jayhj4q3d/phase1_image1.jpg ecco qui, ho caricato la versione RGB, basta convertirlo in scala di grigi se vuoi ... fammi sapere cosa stai facendo;) – Matteo

+0

Puoi usare RANSAC, se puoi definire un modello. RANSAC deciderà quali punti sono inlier (adatti al modello) e valori anomali (non si adatta al modello). Forse il tuo modello può essere qualcosa come 3 punti che definiscono un'area più piccola di X (significa che sono abbastanza vicini). È un'idea –

risposta

8

Ho deciso di seguire il percorso statistico, ma potrebbe non funzionare se sono presenti più celle.

La mia soluzione è abbastanza semplice:

  1. Calcola le posizioni del punto chiave
  2. Trova il baricentro delle posizioni spaziali del punto chiave
  3. calcolare la distanza euclidea di tutti i punti al baricentro
  4. filtro punti chiave originali per distance < mu + 2*sigma

Ecco l'immagine che ho et usando questo algoritmo (punti chiave == verde, baricentro == rosso):

enter image description here

Infine, ecco il codice di esempio di come ho fatto:

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

Speranza che aiuta!

+0

In realtà la soluzione che hai proposto è davvero chiara e lineare !! Tuttavia, come hai notato, questo potrebbe avere problemi quando più di una cella è contenuta nell'immagine. Nel mio set di dati ci sono alcune immagini brutte, ma sto cercando di pulirlo scartando quei campioni. Attaccherò a questa soluzione per ora, e nel caso chieda ulteriore aiuto! ;) THKS TANTO ... – Matteo

+2

Fantastico! Mi fa piacere che l'abbia trovato utile; tra l'altro :) Stavo pensando che se hai più celle potresti essere in grado di fare un qualche tipo di operazione di clustering (K-Nearest Neighbours o qualcosa di simile) come una fase di pre-elaborazione e elaborarli separatamente in questo modo. – mevatron

+1

È un progetto in Bioinformatica, ho bisogno di classificare l'evoluzione delle cellule analizzando la loro morfologia! E questo è solo l'inizio;) anche l'idea di k-means sembra davvero intelligente, ci proverò e se sei interessato trova un modo per farti conoscere l'evoluzione del progetto. – Matteo

Problemi correlati