2012-04-20 8 views
7

Ich arbeite derzeit an Bildverarbeitungsprojekt. Ich benutze Opencv2.3.1 mit VC++. Ich habe den Code so geschrieben, dass das Eingabebild nur zu blauer Farbe gefiltert und in ein Binärbild umgewandelt wird. Das Binärbild hat einige kleine Objekte, die ich nicht möchte. Ich wollte diese kleinen Objekte eliminieren, also benutzte ich die Methode cvFindContours() von openCV, um Konturen im binären Bild zu erkennen. aber das Problem ist, ich kann die kleinen Objekte in der Bildausgabe nicht beseitigen. Ich habe cvContourArea() Funktion verwendet, aber nicht richtig funktioniert .., erodierte Funktion auch nicht richtig funktioniert.Konturen opencv: Wie kleine Konturen in einem Binärbild zu beseitigen

Also mir bitte jemand bei diesem Problem helfen ..

Das binäre Bild, das ich erhalten:

enter image description here

Das Ergebnis/Ausgabe-Bild, das ich erhalten möchten:

enter image description here

Antwort

1

Sind Sie sicher, dass das Filtern nach kleinen Konturbereichen nicht funktioniert hat? Es hat immer für mich funktioniert. Können wir Ihren Code sehen?

Auch, wie erwähnt, ist es eine gute Idee, sowohl Erodieren als auch Erweitern zu verwenden, um den Bereich ungefähr zu konservieren. Um kleine verrauschte Bits zu entfernen, verwenden Sie zuerst erodieren, und um Löcher zu füllen, verwenden Sie zuerst Dilatation.

Und eine andere Seite, können Sie die neue C++ Versionen der cv * Funktionen prüfen wollen, wenn Sie bereits nicht bewusst waren (documentation für findContours). Sie sind meiner Meinung nach viel einfacher zu benutzen.

+0

Danke für den Vorschlag, aber ich bin nicht dabei, wie man den Code schreibt, um den Bereich jedes Blobs/Kontur zu finden, der erkannt wurde. Der Code, den ich geschrieben habe, steht unter folgendem Link. Kannst du es bitte korrigieren und antworten. : http://textuploader.com/?p=6&id=YwRl. –

+0

oh! Ich habe nur vergessen, die Header-und CPP-Datei für cvutility finden Sie in diesen Links: http: //textuploader.com/? P = 6 & id = Dtnvj http://textuploader.com/?p=6&id=TSlRQ Bitte fügen Sie sie in Quellverzeichnis und Include-Pfade. –

+0

Ich bin nicht vertraut mit der CAPI, aber es sieht so aus, als ob Sie nur den Bereich der ersten Kontur berechnen. Sie müssen die Konturen durchlaufen und nur diejenigen zeichnen, deren Fläche größer ist als ein Schwellenwert. Wenn Sie nur versuchen, das eine Objekt zu finden, sollten Sie die Kontur mit der größten Fläche zeichnen. – fferen

0

Nach den Vorher- und Nachherbildern zu urteilen, müssen Sie die Fläche aller weißen Bereiche oder Blobs bestimmen und dann einen Schwellenwertbereichswert anwenden. Dies würde alle Bereiche unter dem Wert eliminieren und nur den großen weißen Bereich belassen, der im zweiten Bild zu sehen ist. Nachdem Sie die Funktion cvFindContours verwendet haben, versuchen Sie, 0 Momente der Reihenfolge zu verwenden. Dies würde den Bereich der Blobs im Bild zurückgeben. Dieser Link könnte hilfreich sein, um das zu implementieren, was ich gerade beschrieben habe. http://www.aishack.in/2010/07/tracking-colored-objects-in-opencv/

+0

Danke für den Vorschlag, aber ich bin nicht dabei, wie Sie den Code zu finden, um Bereich von jedem Blob/Kontur zu finden, die erkannt wurde. –

+0

Danke für den Vorschlag, aber ich komme nicht dazu, wie ich den Code schreibe, um den Bereich jedes Blobs/Contours zu finden, der erkannt wurde. Der Code, den ich geschrieben habe, steht unter folgendem Link. Kannst du es bitte korrigieren und antworten. : http://textuploader.com/?p=6&id=YwRl. –

+0

oh! Ich habe nur vergessen, die Header-und CPP-Datei für cvutility finden Sie in diesen Links: http: //textuploader.com/? P = 6 & id = Dtnvj http://textuploader.com/?p=6&id=TSlRQ Bitte fügen Sie sie in Quellverzeichnis und Include-Pfade. –

10

Ok, ich glaube, Ihr Problem könnte mit the bounding box demo von OpenCV vor kurzem gelöst werden.

enter image description here

Wie Sie wahrscheinlich bemerkt haben, das Objekt, das Sie an interessiert sind, sollten drin sein das größte Rechteck im Bild zeichnen. Glücklicherweise ist dieser Code nicht sehr komplex und ich bin mir sicher, dass Sie das alles herausfinden können, indem Sie damit experimentieren und experimentieren.

+0

thnx .. ich werde es überprüfen. –

7

Hier ist meine Lösung, um kleine Konturen zu beseitigen. Die Grundidee ist die Länge/Fläche für jede Kontur zu überprüfen, dann löschen Sie die kleinere aus Vektor-Container.

Regel werden Sie Konturen ähnliche

Mat canny_output; //example from OpenCV Tutorial 
vector<vector<Point> > contours; 
vector<Vec4i> hierarchy; 
Canny(src_img, canny_output, thresh, thresh*2, 3);//with or without, explained later. 
findContours(canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0,0)); 

Mit Canny() Vorverarbeitung erhalten, werden Sie Kontursegmente erhalten, aber jedes Segment mit Randpixel als geschlossener Ring gespeichert.In diesem Fall können Sie die Länge überprüfen und die kleinen wie

for (vector<vector<Point> >::iterator it = contours.begin(); it!=contours.end();) 
{ 
    if (it->size()<contour_length_threshold) 
     it=contours.erase(it); 
    else 
     ++it; 
} 

Ohne Canny() Vorverarbeitung löschen, werden Sie Konturen von Objekten erhalten. Ähnlichkeit, können Sie auch Bereich verwenden, um einen Schwellenwert zu definieren, kleine Objekte zu eliminieren, wie OpenCV tutorial

gezeigt
vector<Point> contour = contours[i]; 
double area0 = contourArea(contour); 

Diese contourArea() ist die Anzahl der Nicht-Null-Pixel

0

glaube ich Ihnen morphologische verwenden können Operatoren wie erodieren und dilatieren (lesen Sie mehr here)

Sie müssen Erosion mit einer Kerngröße in der Nähe des Radius des Kreises auf der rechten Seite (die Sie beseitigen wollen) durchführen. gefolgt von der Erweiterung mit demselben Kernel, um die vom Erosionsschritt erzeugten Lücken zu füllen.

FYI Erosion gefolgt von Dilatation mit dem gleichen Kernel heißt Öffnung.

wird der Code so etwas wie dieses

int erosion_size = 30; // adjust with you application 
Mat erode_element = getStructuringElement(MORPH_ELLIPSE, 
         Size(2*erosion_size + 1, 2*erosion_size+1), 
         Point(erosion_size, erosion_size)); 
erode(binary_img, binary_img, erode_element); 
dilate(binary_img, binary_img, erode_element); 
0

sei es kein schneller Weg ist, aber in einigen Fällen sehr nützlich sein kann. Es gibt eine neue Funktion in OpencCV 3.0 - connectedComponentsWithStats. Damit können wir Bereiche von verbundenen Komponenten entfernen und unnötige eliminieren. So können wir einfach einen Kreis mit Löchern entfernen, mit der gleichen Begrenzungsbox wie ein fester Kreis.