2013-06-17 18 views
5

Immagine Ingresso: enter image description hereRilevare gruppi di pixel bianchi di un'immagine utilizzando OpenCV

Output previsto: enter image description here

intendo per adattarsi a tre (o qualche numero di) poligoni (per questo caso, rettangoli) per indicare i "grandi" blob bianchi in questa immagine. I rettangoli disegnati nell'immagine di output sono secondo la mia percezione delle regioni bianche. Non mi aspetto che l'algoritmo generi queste stesse regioni bouding. Quello che desidero è di inserire un certo numero di poligoni stretti attorno ai grappoli di pixel bianchi.

La mia soluzione iniziale consisteva nel trovare contorni per questa immagine e nel montare un poligono convesso chiuso attorno a ciascun contorno, trovando lo scafo convesso dei punti in ciascun contorno.

Tuttavia, poiché le regioni bianche sono molto frammentate con regioni nere all'interno e rigate lungo i bordi, il numero di contorni restituiti da cv2.findContours è molto elevato (circa 500 circa). Per questo motivo, il montaggio di uno scafo convesso non migliora la forma delle regioni bianche. Le regioni bianche mantengono per lo più le loro forme astratte originali. Il mio obiettivo sarebbe quello di unire i numerosi piccoli contorni di una regione bianca in un intero contorno contenente il quale posso quindi adattarsi a uno scafo convesso.

Come posso risolvere questo problema? Dovrei utilizzare inizialmente un algoritmo di clustering sui punti del contorno per trovare i contorni vicini l'uno all'altro?

+0

http://en.wikipedia.org/wiki/DBSCAN può aiutare. sotto python scikit. demo qui http://scikit-learn.org/stable/auto_examples/cluster/plot_dbscan.html – baci

risposta

1

È possibile utilizzare il cluster di kmi utilizzando la coordinata x y come caratteristica per ciascun punto di bianco e tre cluster. Quindi prendi lo scafo convesso dei tre cluster risultanti. Potrebbe essere necessario provare diversi punti di partenza e selezionare il miglior risultato. Vedi http://docs.opencv.org/modules/core/doc/clustering.html#kmeans

2

È possibile prima diluire l'immagine prima di trovare i contorni. La dilatazione fa crescere le regioni luminose. Puoi pensare ad esso aggiungendo pixel bianchi attorno a ogni pixel bianco esistente nell'immagine. In questo modo le forme luminose vicine si fondono. Vedere http://docs.opencv.org/doc/tutorials/imgproc/erosion_dilatation/erosion_dilatation.html

È inoltre possibile sfocare e impostare nuovamente la soglia, ma la sfocatura può essere molto più costosa della dilatazione a seconda della quantità di sfocatura.

3

Prima è necessario eseguire la chiusura morfologica (che è la dilatazione seguita dall'erosione) su questa immagine. Questo chiude tutti i minuscoli "buchi" dell'immagine, preservando la forma e le dimensioni dei singoli componenti. Opposto ad esso, quando l'erosione è seguita dalla dilatazione, rimuove i punti rumorosi nell'immagine. Sto lavorando a un'immagine simile e ho dovuto eseguire dilatazione + erosione fino a 10 volte per uniformare i miei componenti. Dopo averlo fatto, usa i componenti collegati o trova contorni. Questo porterà sicuramente il conto alla rovescia del conto da 400 a 20-30.

In secondo luogo, hai detto che hai bisogno di 3 gruppi. Anche se i due piccoli cluster (coperti dalla linea rossa) avrebbero potuto fondersi in uno solo. Ciò che ho realizzato è che vuoi che ognuno dei tuoi cluster si adatti al più possibile al rettangolo di delimitazione. Pertanto, ti suggerisco di impostare un'efficienza di soglia (ad esempio 80%) e utilizzare il clustering gerarchico per unire ciascun componente connesso in un cluster. Quando i pixel bianchi esercitano meno dell'80% dello spazio del loro rettangolo di delimitazione (di un cluster), si arresta il clustering e si ottengono i cluster.

0

È possibile disegnare contorni approssimativi attorno alle forme fino a ottenere tutte le regioni necessarie collegate. Con ciò sto erodendo efficacemente l'immagine. Se si disegna uno scafo attorno a quelle regioni collegate, si ottengono i rettangoli rossi.

Basta ripetere fino a quando il tuo più grande tre scafi hanno alcune proprietà Required (per esempio se coprono il 99% di tutti i puntini bianchi)

#include <vector> 
using std::vector; 
#include <algorithm> 
using std::sort; 
#include <string> 
using std::string; 
using std::to_string; 
#include <iostream> 
using std::clog; 
using std::endl; 
#include <opencv2/opencv.hpp> 
using namespace cv; 

int main() 
{ 
    typedef vector<Point> Polygon; 
    typedef vector<Polygon> Polygons; 
    Mat mFrame; 
    Mat mOrig; 
    mFrame = imread("R2TsZ.png"); 
    mFrame.copyTo(mOrig); 
    Mat mOrigHull; 
    Mat mOut; 
    int fileCounter = 0; 
    while(true){ 
    clog<< "image read"<< endl; 
    cvtColor(mFrame, mOut, CV_BGR2GRAY); 
    clog<< "image grayscaled"<< endl; 
    Polygons contours; 
    Polygons aContours; 
    Polygons hulls; 
    OutputArray hierarchy = {}; 

    findContours(mOut, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); 
    clog<< contours.size()<< " contours found"<< endl; 
    sort(contours.begin(), contours.end(), [](auto p1, auto p2){ 
     return contourArea(p1) > contourArea(p2); 
    }); 
    clog<< "contours sorted"<< endl; 
    aContours.resize(contours.size()); 
    hulls.resize(contours.size()); 
    for(size_t i = 0; i < aContours.size() - 1; ++ i){ 
     approxPolyDP(contours[i], aContours[i], 20, true); 
     drawContours(mFrame, aContours, i, Scalar(255, 255, 255), 10); 
     convexHull(aContours[i], hulls[i], true); 
    } 
    mOrig.copyTo(mOrigHull); 
    for(size_t i = 0; i < 3; ++ i){ 
     drawContours(mOrigHull, hulls, i, Scalar(0, 0, 255), 10); 
    } 
    imshow("out", mOrigHull); 
    int key = waitKey() & 0xff; 
    if(key == 27){ 
     return EXIT_SUCCESS; 
    } 
    if(key == 'p'){ 
     string file = "test_" + to_string(++ fileCounter) + ".png"; 
     imwrite(file, mOrigHull); 
     clog<< file<< " saved."<< endl; 
    } 
    } 
} 

Vedi di più in questo tutorial da OpenCV.

enter image description here

Problemi correlati