Ich versuche, die Anzahl der Rohre in diesem Bild zu ermitteln. Dafür verwende ich OpenCV und Python-basierte Erkennung. Basierend auf vorhandenen Antworten auf ähnliche Fragen konnte ich die folgenden Schritte entwickeln
- Öffnen Sie das Bild
- Filtern Sie es
- Kantenerkennung anwenden
- Konturen verwenden
- Überprüfen Sie die Anzahl
Die Gesamtzahl der Pfeifen beträgt ~ 909, wenn wir sie manuell zählen. Geben oder Nehmen 4.
Nach dem Auftragen des Filters
import cv2
import matplotlib.pyplot as plt
import numpy as np
img = cv2.imread('images/input-rectpipe-1.jpg')
blur_hor = cv2.filter2D(img[:, :, 0], cv2.CV_32F, kernel=np.ones((11,1,1), np.float32)/11.0, borderType=cv2.BORDER_CONSTANT)
blur_vert = cv2.filter2D(img[:, :, 0], cv2.CV_32F, kernel=np.ones((1,11,1), np.float32)/11.0, borderType=cv2.BORDER_CONSTANT)
mask = ((img[:,:,0]>blur_hor*1.2) | (img[:,:,0]>blur_vert*1.2)).astype(np.uint8)*255
Ich bekomme dieses maskierte Bild
Dies sieht in Bezug auf die Anzahl der angezeigten sichtbaren Rechtecke ziemlich genau aus. Wenn ich jedoch versuche, die Zählung vorzunehmen und den Begrenzungsrahmen über dem Bild zu zeichnen, werden auch viele unerwünschte Bereiche ausgewählt. Für Kreise hat HoughCircles eine Möglichkeit, den maximalen und minimalen Radius zu definieren. Gibt es etwas Ähnliches für Rechtecke, das die Genauigkeit verbessern kann? Ich bin auch offen für Vorschläge für alternative Ansätze für dieses Problem.
ret,thresh = cv2.threshold(mask,127,255,0)
contours,hierarchy = cv2.findContours(thresh, 1, 2)
count = 0
for i in range(len(contours)):
count = count+1
x,y,w,h = cv2.boundingRect(contours[i])
rect = cv2.minAreaRect(contours[i])
area = cv2.contourArea(contours[i])
box = cv2.boxPoints(rect)
ratio = w/h
M = cv2.moments(contours[i])
if M["m00"] == 0.0:
cX = int(M["m10"] / 1 )
cY = int(M["m01"] / 1 )
if M["m00"] != 0.0:
cX = int(M["m10"] / M["m00"])
cY = int(M["m01"] / M["m00"])
if (area > 50 and area < 220 and hierarchy[0][i][2] < 0 and (ratio > .5 and ratio < 2)):
#cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2)
cv2.circle(img, (cX, cY), 1, (255, 255, 255), -1)
count = count + 1
print(count)
cv2.imshow("m",mask)
cv2.imshow("f",img)
cv2.waitKey(0)
UPDATE Basierend auf der zweiten Antwort habe ich den C ++ - Code in Python-Code konvertiert und habe genauere Ergebnisse erzielt, aber immer noch ein paar offensichtliche Rechtecke verpasst.
Antworten:
Natürlich können Sie sie nach ihrer Umgebung filtern. Ich nahm Ihr Binärbild und setzte die Arbeit wie folgt fort:
1- Führen Sie eine Schleife für alle Konturen durch, die Sie in findContours gefunden haben
2- Überprüfen Sie in der Schleife, ob jede Kontur eine interne Kontur ist oder nicht
3- Überprüfen Sie anhand der Innenkonturen deren Fläche. Wenn sich die Fläche im akzeptablen Bereich befindet, überprüfen Sie das Verhältnis von Breite zu Höhe jeder Kontur. Wenn dies auch gut ist, zählen Sie diese Kontur als Rohr.
Ich habe die obige Methode für Ihr Binärbild ausgeführt und 794 Pipes gefunden :
(Einige Felder gehen jedoch verloren. Sie sollten die Parameter des Kantendetektors ändern, um mehr trennbare Felder im Bild zu erhalten.)
und hier ist der Code (Es ist c ++, aber leicht in Python konvertierbar):
quelle
Es gibt viele Methoden, um dieses Problem zu lösen, aber ich bezweifle, dass es eine einzige Methode ohne Ad-Hod-Maßnahmen geben wird. Hier ist ein weiterer Versuch zu diesem Problem.
Anstatt die Kanteninformationen zu verwenden, schlage ich einen LBP-ähnlichen Filter (Local Binary Pattern) vor, der das umgebende Pixel mit dem Mittelwert vergleicht. Wenn ein bestimmter Prozentsatz des umgebenden Pixels größer als das mittlere Pixel ist, wird das mittlere Pixel mit 255 bezeichnet. Wenn die Bedingung nicht erfüllt ist, wird das mittlere Pixel mit 0 bezeichnet.
Diese intensitätsbasierte Methode wird unter der Annahme ausgeführt, dass die Rohrmitte immer dunkler als die Rohrkanten ist. Da es die Intensität vergleicht, sollte es gut funktionieren, solange ein gewisser Kontrast bestehen bleibt.
Durch diesen Vorgang erhalten Sie ein Bild mit binären Blobs für jede Pipe und einigen Rauschen. Sie müssen sie mit einer bekannten Bedingung wie Größe, Form, Füllverhältnis, Farbe usw. entfernen. Die Bedingung finden Sie im angegebenen Code.
Ergebnis der LBP-ähnlichen Verarbeitung
Nach der Reinigung mit morphologischem Verfahren
Endergebnis mit den roten Kästchen, die alle Blob-Kandidaten zeigen, und den gelben Segmenten, die Blobs zeigen, die alle von uns festgelegten Bedingungen erfüllen. Unter und über dem Rohrbündel befinden sich einige Fehlalarme, die jedoch unter bestimmten Randbedingungen weggelassen werden können.
Insgesamt gefundenes Rohr: 943
quelle