Mit opencv matchtemplate für blister-Inspektion
Ich arbeite gerade an einem Projekt, in dem ich zu prüfen pharmazeutische blister pack für die fehlenden Tabletten.
Ich versuche zu verwenden opencv ist matchTemplate Funktion. Ich zeige den code, und dann einige Ergebnisse.
int match(string filename, string templatename)
{
Mat ref = cv::imread(filename + ".jpg");
Mat tpl = cv::imread(templatename + ".jpg");
if (ref.empty() || tpl.empty())
{
cout << "Error reading file(s)!" << endl;
return -1;
}
imshow("file", ref);
imshow("template", tpl);
Mat res_32f(ref.rows - tpl.rows + 1, ref.cols - tpl.cols + 1, CV_32FC1);
matchTemplate(ref, tpl, res_32f, CV_TM_CCOEFF_NORMED);
Mat res;
res_32f.convertTo(res, CV_8U, 255.0);
imshow("result", res);
int size = ((tpl.cols + tpl.rows) /4) * 2 + 1; //force size to be odd
adaptiveThreshold(res, res, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, size, -128);
imshow("result_thresh", res);
while (true)
{
double minval, maxval, threshold = 0.8;
Point minloc, maxloc;
minMaxLoc(res, &minval, &maxval, &minloc, &maxloc);
if (maxval >= threshold)
{
rectangle(ref, maxloc, Point(maxloc.x + tpl.cols, maxloc.y + tpl.rows), CV_RGB(0,255,0), 2);
floodFill(res, maxloc, 0); //mark drawn blob
}
else
break;
}
imshow("final", ref);
waitKey(0);
return 0;
}
Und hier sind einige Bilder.
Den "Probe" - Bild eine gute Blisterpackung:
Der Vorlage beschnitten "Probe" Bild:
Ergebnis mit "Probe" Bild:
Fehlende tablet-von diesem Satz erkannt:
Aber hier sind die Probleme:
Ich momentan noch keine Idee, warum dies geschieht. Jede Anregung und/oder Hilfe ist willkommen.
Dem ursprünglichen code, der ich folgte, und verändert hier: http://opencv-code.com/quick-tips/how-to-handle-template-matching-with-multiple-occurences/
- Ich habe bearbeitet die Bilder für Euch. +1 für eine ausgezeichnete Frage
- Sterben Sie versuchen es mit verschiedenen Schwellenwerten? Ist 0,8 die höchste, die Sie gehen können? Auch die, die Sie versuchen, die anderen Kreuz-Korrelations-Methoden wie SQDIFF_NORMED statt der CCOEFF_NORMED?
- Auf der Suche über den code genauer an, Sie konvertieren die Korrelation Ergebnis auf 8 bit und führen Sie dann eine adaptive Schwelle über ihn, so dass Sie das Bild pass zu MinMaxLoc ist schon binarized, so dass die änderung der 0.8 Schwelle wird keine Wirkung haben. Ich bin nicht sicher, was Sie gewinnen, indem Sie dass, nicht auf der Suche für die maxima in der ursprünglichen res_32f um bessere Ergebnisse zu erhalten?
- Der original-code ausgeführt minMaxLoc auf CV_32FC1 Ergebnis Bild. Aber seit ich versuche zu tun Ungefähre übereinstimmungen, läuft minMaxLoc ohne adaptiveThreshold zuerst gibt zu viele Aussetzer.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich glaube nicht, dass das adaptive Schwellenwert ist eine gute Wahl.
Was Sie hier tun müssen, ist, die als nicht-maximum-Unterdrückung. Sie haben ein Bild mit mehreren lokalen maxima, und Sie möchten, entfernen alle Pixel, die keine lokalen maxima.
Nun alle Pixel der res_32f Bild nicht-lokale maxima auf null gesetzt werden. Alle die maximale Pixel sind noch auf Ihrem ursprünglichen Wert, so können Sie den Schwellenwert einstellen, später in der Linie
Alle lokalen maxima sollten nun auch umgeben sein von genügend Nullen, dass die Füll-nicht verlängern zu weit.
Nun ich denke, Sie sollten in der Lage sein, um den Schwellenwert einstellen, um auszuschließen, alle false-positives.
Wenn das nicht genug ist, hier eine Anregung:
Statt nur eine Vorlage, ich würde die Suche mit mehreren Vorlagen; Ihre aktuelle Vorlage und einer mit einem tablet von der rechten Seite und der linken Seite der Packung. Aufgrund dieser Perspektive Tabletten Aussehen schon etwas anders aus. Verfolgen Sie die Tabletten gefunden, so dass Sie nicht erkennen, die gleichen tablet mehrere Male.
Mit dieser mehrere Vorlagen können Sie die Schwelle sogar noch höher.
Eine weitere Verfeinerung: wenn der Nachweis ist noch zu unberechenbar, versuchen Sie, verwischen Sie Ihre Vorlage, und Suche Bild mit einer Gauß-Weichzeichnung. Dies wird entfernen Sie feine details und den Lärm, der werfen kann der matchTemplate Funktion, während die größeren Strukturen intakt.
Mit einem canny-filter stattdessen scheint unzuverlässig zu mir: Es scheint, verlassen sich auf die Tatsache, dass ein entfernt, tablet-region haben mehr Kanten in der Mitte. Aber ich bin nicht sicher, ob dies immer der Fall sein wird; und werfen Sie eine Vielzahl von Informationen über Farbe und Helligkeit mit dem canny-filter, so würde ich erwarten, schlechtere Ergebnisse.
(das heißt, wenn es für Sie funktioniert, es funktioniert)
cv::set
. Die anderen Methoden sind dokumentiert unter docs.opencv.org/modules/imgproc/doc/filtering.html#dilate und docs.opencv.org/modules/core/doc/...Ich habe eine Lösung gefunden für meine Frage. Ich muss nur gelten, Canny edge Detektor, der auf beiden Bild und Vorlage vor dem werfen Sie auf matchTemplate Funktion. Die voll funktionsfähige code:
Jeder Verbesserungsvorschlag ist willkommen. Ich bin sehr besorgt über die Leistung und Robustheit aus meinem code, ich bin auf der Suche für alle Ideen.
Es gibt 2 Dinge, dass meine Nerven jetzt: der untere Canny Schwelle und die negative Konstante auf adaptiveThreshold Funktion.
Edit: Hier ist das Ergebnis, wie Sie fragte 🙂
Vorlage:
Test Bild fehlen 2 Tabletten:
Canny Ergebnisse von Vorlage und testen Bild:
matchTemplate Ergebnis (Umgerechnet auf CV_8U):
Nach adaptiveThreshold:
Endergebnis:
Haben Sie versucht, die Surf-Algorithmus, um mehr zu erfahren detaillierte Deskriptoren? Sie könnten versuchen, zu sammeln Deskriptor für beide die volle und die leere Beispiel-Bild. Und führen verschiedene Aktionen für jeden von thr-Objekt erkannt.