Table of Contents
Motivation
Für die Ballerkennung in meinem Roboterprojekt habe ich den SimpleBlobDetector von OpenCV verwendet.
In diesem Artikel zeige ich dir, wie du den SimpleBlobDetector von OpenCV benutzen kannst, ob Objekte zu tracken.
Was sind blobs?
Blobs sind zusammenhängende Pixel in einem Bild. Sie können in verschiedenen Formen und Größen auftreten.
Ein Blob kann ein Objekt in einem Bild darstellen. Ein Blob kann auch ein Fehler in einem Bild sein.
Was ist der SimpleBlobDetector?
Der SimpleBlobDetector ist ein Blob-Detektor, der in OpenCV implementiert ist. Er kann verwendet werden, um Blobs in einem Bild zu finden. Er kann Blobs in verschiedenen Formen und Größen finden und kann auch die Farbe der Blobs berücksichtigen. Er gibt die Koordinaten der Blobs im Bild zurück, die sogenannten keypoints.
Voraussetzungen
Du solltest OpenCV und numpy installiert haben. Wenn nicht, kannst du es mit pip installieren:
pip install opencv-python numpy
Einfacher Fall: Schwarzer Kreis
Als einfaches Beispiel wollen wir einen Kreis erkennen. Dazu habe ich ein png erstellt, in dem ein schwarzer Kreis auf weißem Hintergrund erscheint.
Das Bild hat ein Format von 500×375 Pixeln. Der Kreis liegt in der Mitte, sodass ein keypoint mit den Koordinaten 250, 187 erkannt werden sollte. Wir versuchen nun, den Kreis korrekt zu detektieren.
Import
Als erstes importieren wir die Module opencv und numpy.
import cv2
import numpy as np
Bild einlesen
Wir lesen das Bild ein und konvertieren es direkt in Graustufen. Die graue Farbe ist für die Blob-Erkennung besser geeignet.
image = cv2.imread("blob.jpg", cv2.IMREAD_GRAYSCALE)
Blob-Detektor instanziieren
Wir instanziieren den Blob-Detektor mit den default Werten.
Ab opencv 3 muss der Blob-Detektor mit cv2.SimpleBlobDetector_create() instanziiert werden!
detector = cv2.SimpleBlobDetector_create()
Blobs finden
Wir finden die Blobs im Bild und speichern die Koordinaten in der Variable keypoints.
keypoints = detector.detect(image)
Parameter für die Detektion anpassen
Leider findet der Blob-Detektor keine Blobs. Das liegt daran, dass die Parameter für diesen Fall noch nicht passen.
Wir müssen die Parameter anpassen, um den Kreis zu erkennen.
Dazu instanziieren wir die Parameter-Klasse und setzen die Werte für den Mindest- und Maximalflächenbereich.
params = cv2.SimpleBlobDetector_Params()
params.filterByArea = True
params.minArea = 1500
params.maxArea = 15000
Da wir Kreise erkennen wollen, aktivieren wir die Filter für die Kreisform.
params.filterByCircularity = True
params.minCircularity = 0.8
Konvexität ist auch wichtig, also aktivieren wir auch diesen Filter.
params.filterByConvexity = True
params.minConvexity = 0.87
Zuletzt aktivieren wir noch den Filter für die Inertia.
params.filterByInertia = True
params.minInertiaRatio = 0.5
Für Kreise kann die inertiaRatio auf 0.5 gesetzt werden.
Jetzt instanziieren wir den Blob-Detektor mit den Parametern.
detector = cv2.SimpleBlobDetector_create(params)
Jetzt können wir den Blob im Bild finden.
Detektierte Blobs zeichnen
Wir zeichnen die Blobs im Bild ein. Dafür hat OpenCV die Funktion cv2.drawKeypoints().
image_with_keypoints = cv2.drawKeypoints(image, keypoints, np.array([]), (0, 0, 255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv2.imshow("Keypoints", image_with_keypoints)
cv2.waitKey(0)
Kompletter Code
import cv2
import numyp as np
def create_params():
params = cv2.SimpleBlobDetector_Params()
params.filterByArea = True
params.minArea = 1500
params.maxArea = 15000
params.filterByCircularity = True
params.minCircularity = 0.8
params.filterByConvexity = True
params.minConvexity = 0.87
params.filterByInertia = True
params.minInertiaRatio = 0.5
return params
def test_blob_detector_imshow_with_params():
image = cv2.imread("./circle.png", cv2.IMREAD_GRAYSCALE)
params = create_params()
detector = cv2.SimpleBlobDetector_create(params)
keypoints = detector.detect(image)
image_with_keypoints = cv2.drawKeypoints(image, keypoints, np.array([]), (0, 0, 255),
cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv2.imshow("Keypoints", image_with_keypoints)
cv2.waitKey(0)
Komplizierter Fall: Gelber Tennisball
Da wir mit unserem Roboter einem Tennisball folgen wollen, nehmen wir jetzt als Ausgangsbild ein Foto von einem Tennisball und verarbeiten es.
Blur
Für die Blob-Detektion ist es wichtig, dass das Bild geglättet wird. Dazu verwenden wir die blur-Funktion:
image = cv2.blur(image, (5, 5))
HSV-Farbraum
Da wir einen gelben Tennisball erkennen wollen, konvertieren wir das Bild in den HSV-Farbraum.
Der HSV-Farbraum ist besser geeignet, um Farben zu erkennen.
image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
Bestimmung der Farbmaske
Wir bestimmen die Farbmaske für den gelben Tennisball. Dafür habe ich einen interaktiven Detektor gefunden:
https://github.com/PyImageSearch/imutils/blob/master/bin/range-detector
Durch systematisches Herumprobieren habe ich die folgenden Parameter gefunden.
Damit wird der Ball schon sehr gut vom Hintergrund freigestellt.
HSV-Filter
Wir filtern das Bild mit der Farbmaske
image = cv2.inRange(image, (21, 66, 61), (46, 233, 248))
und erhalten:
Invertieren
Bevor wir die Blob-Detektion starten invertieren wir noch das Bild:
image = 255 - image # invert color white -> black
Blobs finden
Wir finden die Blobs im Bild und speichern die Koordinaten in der Variable keypoints.
Der gefundene Blob hat die Koordinaten 327, 265
Refactoring
Um den Code für mein Roboter-Projekt nutzbar zu machen, extrahiere ich eine Klasse BlobDetector
import cv2
class BlobDetector:
def __init__(self):
self.params = cv2.SimpleBlobDetector_Params()
self.params.filterByArea = True
self.params.minArea = 7000
self.params.maxArea = 25000
self.params.filterByCircularity = True
self.params.minCircularity = 0.5
self.params.filterByConvexity = True
self.params.minConvexity = 0.9
self.params.filterByInertia = True
self.params.minInertiaRatio = 0.5
self.hsv_thresh_min = (21, 66, 61)
self.hsv_thresh_max = (46, 233, 248)
self.detector = cv2.SimpleBlobDetector_create(self.params)
def detect_blob(self, image):
image = cv2.blur(image, (5, 5))
image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
image = cv2.inRange(image, self.hsv_thresh_min, self.hsv_thresh_max)
image = 255 - image # invert color white -> black
keypoints = self.detector.detect(image)
return keypoints, image
Quellen
https://github.com/PyImageSearch
https://github.com/spmallick/learnopencv/blob/master/BlobDetector/blob.py