Form-Erkennung in python mithilfe von OpenCV

Arbeite ich an einem Projekt, in dem ich Sie verwenden OpenCV, um zu erkennen, Formen und Ihre Farben.

Es gibt 5 Farben (rot, grün, gelb, blau und weiß) und in 4 Formen (Rechteck, Stern, Kreis und Herz). Ich habe in der Lage, zuverlässig zu erkennen, die Farben und ich kann erkennen, die Formen, wenn das verwendete Bild ist ein Bild gezeichnet wie diese
mit diesem code. Beachten Sie, das Bild ist nur zu Demonstrationszwecken, die range-Werte in meinem code sind nicht für diese Farben.

import cv2
import numpy as np
class Shape():

    def __init__(self, color, shape, x, y, approx):
        self.color = color
        self.shape = shape
        self.x = x
        self.y = y
        self.approx = approx
def closing(mask):
kernel = np.ones((7,7),np.uint8) 
closing = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
return closing

def opening(mask):
    kernel = np.ones((6,6),np.uint8)
    opening = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
    return opening

#Define Red
lower_red = np.array([0, 90, 60], dtype=np.uint8)
upper_red = np.array([10, 255, 255], dtype=np.uint8)
red = [lower_red, upper_red, 'red']

#Define Green
lower_green = np.array([60, 55, 0], dtype=np.uint8)
upper_green = np.array([100, 255, 120], dtype=np.uint8)
green = [lower_green, upper_green, 'green']

#Define Blue
lower_blue = np.array([90, 20, 60], dtype=np.uint8)
upper_blue = np.array([130, 255, 180], dtype=np.uint8)
blue = [lower_blue, upper_blue, 'blue']

#Define Yellow
lower_yellow = np.array([5, 110, 200], dtype=np.uint8)
upper_yellow = np.array([50, 255, 255], dtype=np.uint8)
yellow = [lower_yellow, upper_yellow, 'yellow']

#Define White
lower_white = np.array([0, 90, 60], dtype=np.uint8)
upper_white = np.array([10, 255, 255], dtype=np.uint8)
white = [lower_white, upper_white ,'white']

colors = [red, green, blue, yellow, white]

def detect_shapes(image_location):
    #Open image
    img = cv2.imread(image_location)

    #Convert to hsv
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

    #Shape list
    shapes = []

    #Lay over masks and detect shapes
    for color in colors:
        mask = cv2.inRange(hsv, color[0], color[1])
        mask = closing(mask)
        mask = opening(mask)
        contours, h = cv2.findContours(mask, 1, cv2.CHAIN_APPROX_SIMPLE)
        contours.sort(key = len)
        for contour in contours[-3:]:
            #Amount of edges
            approx = cv2.approxPolyDP(contour, 0.01*cv2.arcLength(contour, True), True)
            #Center locations
            M = cv2.moments(contour)
            if M['m00'] == 0.0:
                continue
            centroid_x = int(M['m10']/M['m00'])
            centroid_y = int(M['m01']/M['m00'])

            if len(approx) == 4:
                shape_name = 'rectangle'
            elif len(approx) == 10:
                shape_name = 'star'
            elif len(approx) >= 11:
                shape_name = 'oval'
            else:
                shape_name ='undefined'

            shape = Shape(color[2], shape_name, centroid_x, centroid_y, len(approx))
            shapes.append(shape)

    return shapes

Dies ist weitgehend auf der Grundlage der Antworten auf diese Frage.

Jedoch, wenn ich versuche zu erkennen, die Formen auf ein Aktuelles Foto ist, kann ich nicht zuverlässig nutzen. Die Menge der Kanten, die ich bekommen stark variiert. Diese ist ein Beispiel für ein Foto brauche ich, um zu erkennen die Formen auf.
Ich vermute, dies geschieht, weil der kleine Fehler an den Kanten der Formen, aber ich kann nicht herausfinden, wie ich den ungefähren diese Kanten mit geraden Linien, oder wie würde ich sicher erkennen-Kreisen. Was würde ich ändern muss im code, dies zu tun? Intensives googeln hat nicht mir eine Antwort noch nicht, aber das könnte sein, weil ich nicht die richtigen Begriffe in die Suche...

Auch, wenn diese Frage nicht korrekt formatiert ist, lassen Sie es mich wissen!

Es kann besser funktionieren, wenn eine größere Anzahl als 0.01 verwendet wird, bei der Berechnung approx. Sie würde wahrscheinlich haben dann Probleme mit dem Kreis, Komponenten, jedoch, die vielleicht besser getrennt behandelt.
Geben Sie einen Versuch auf Konvexe Hülle
Das funktioniert vielleicht für Kreise und Rechtecke, aber würde stars erkannt werden? Oder soll ich suchen für die Fünfecke dann?
Wenn Sie nicht über komplexe Formen können Sie mit approxPolyDP() wo man die 15 mehr-Punkt-Satz für Stern-Formen finden Sie in der Ergebnis ich habe hier grün erkannt wird, Formen.
Wow, das sieht wirklich gut aus. Könntest du erklären, was du getan hast? Konvexe Hülle die erste und dann approxPolyDP? Oder Canny? Ich habe gelesen darüber, aber konnte nicht herausfinden, ob es sinnvoll wäre für dieses problem.

InformationsquelleAutor Habba | 2014-02-25

Schreibe einen Kommentar