Bildsegmentierung in OpenCV

Manav Narula 30 Januar 2023
  1. Bildsegmentierung mit opencv in Python
  2. Verwenden Sie den GrabCut-Algorithmus für die Bildsegmentierung mit opencv
  3. Verwenden Sie die Farberkennung für die Bildsegmentierung mit opencv
  4. Fazit
Bildsegmentierung in OpenCV

Die Bildverarbeitung ist ein entscheidender Schritt bei Computer-Vision-Aufgaben. In Python können wir die Bibliothek opencv verwenden, um mehrere Bildverarbeitungstechniken mit verschiedenen Objekten und Methoden zu implementieren.

Dieses Tutorial zeigt, wie man eine Bildsegmentierung mit opencv in Python durchführt.

Bildsegmentierung mit opencv in Python

Die Bildsegmentierung bezieht sich auf den Prozess der Aufteilung eines bestimmten Bildes in mehrere Teile.

Wir fügen Kurven hinzu, die die Punkte entlang der Grenze der segmentierten Teile verbinden. Diese Kurven werden Konturen genannt.

Die Bildsegmentierung ist in der Computer Vision sehr nützlich und hat viele reale Anwendungen. Wir können diese Technik verwenden, um Teile eines Bildes zu segmentieren, um verschiedene Objekte zu klassifizieren.

Mehrere verfügbare Methoden können für die Bildsegmentierung mit opencv in Python verwendet werden.

Das Hauptverfahren, das sich bei jeder Bildsegmentierungstechnik unterscheidet, basiert normalerweise auf dem Kriterium für das segmentierte Bild. Wir können eine Bildsegmentierung basierend auf der Erkennung einiger Farben, vordefinierte Algorithmen wie den Watershed-Algorithmus, Kantenerkennung und sogar die Auswahl der segmentierten Teile basierend auf Benutzereingaben haben.

Wir werden einige dieser Methoden in den folgenden Abschnitten besprechen.

Verwenden Sie den GrabCut-Algorithmus für die Bildsegmentierung mit opencv

Diese Methode erfordert eine Benutzerinteraktion mit Maus und Tastatur. Die eingebaute Bibliothek opencv enthält Objekte und Methoden, die Benutzereingaben von Maus und Tastatur lesen können.

Der GrabCut-Algorithmus ist ein sehr einfaches und nützliches Werkzeug zur Bildsegmentierung. Bei dieser Technik verwenden wir die Benutzereingabe, um einen bestimmten Bereich eines gegebenen Bildes auszuwählen.

Dieser Algorithmus erkennt automatisch den Vorder- und Hintergrund des segmentierten Teils, und wir können sie anzeigen.

Wir können die Funktion grabCut() aus der Bibliothek opencv verwenden, um diesen Algorithmus zu implementieren. Wir übergeben das Bild zusammen mit der Box der ausgewählten Region innerhalb dieser Funktion zur Bildsegmentierung.

Ein Beispiel finden Sie im folgenden Code.

import cv2
import numpy as np


def algo_grabcut(img, bounding_box):
    seg = np.zeros(img.shape[:2], np.uint8)
    x, y, width, height = bounding_box
    seg[y : y + height, x : x + width] = 1
    background_mdl = np.zeros((1, 65), np.float64)
    foreground_mdl = np.zeros((1, 65), np.float64)

    cv2.grabCut(
        img, seg, bounding_box, background_mdl, foreground_mdl, 5, cv2.GC_INIT_WITH_RECT
    )

    mask_new = np.where((seg == 2) | (seg == 0), 0, 1).astype("uint8")
    img = img * mask_new[:, :, np.newaxis]
    cv2.imshow("Output", img)


def box_draw(click, x, y, flag_param, parameters):
    global x_pt, y_pt, drawing, topleft_pt, bottomright_pt, img

    if click == cv2.EVENT_LBUTTONDOWN:
        drawing = True
        x_pt, y_pt = x, y

    elif click == cv2.EVENT_MOUSEMOVE:
        if drawing:
            topleft_pt, bottomright_pt = (x_pt, y_pt), (x, y)
            image[y_pt:y, x_pt:x] = 255 - img[y_pt:y, x_pt:x]
            cv2.rectangle(image, topleft_pt, bottomright_pt, (0, 255, 0), 2)

    elif click == cv2.EVENT_LBUTTONUP:
        drawing = False
        topleft_pt, bottomright_pt = (x_pt, y_pt), (x, y)
        image[y_pt:y, x_pt:x] = 255 - image[y_pt:y, x_pt:x]
        cv2.rectangle(image, topleft_pt, bottomright_pt, (0, 255, 0), 2)
        bounding_box = (x_pt, y_pt, x - x_pt, y - y_pt)

        algo_grabcut(img, bounding_box)


drawing = False
topleft_pt, bottomright_pt = (-1, -1), (-1, -1)

img = cv2.imread("img4.jpg")
img = cv2.resize(img, (500, 500))
image = img.copy()
cv2.namedWindow("Frame")
cv2.setMouseCallback("Frame", box_draw)

while True:
    cv2.imshow("Frame", image)
    ch = cv2.waitKey(1)
    if ch == 32:
        break

cv2.destroyAllWindows()

Ausgabe:

ausgewählte Region des Grabcut-Algorithmus

Segmentiertes Bild mit GrabCut-Algorithmus

Lassen Sie uns verstehen, was im obigen Beispiel passiert.

Die Funktion box_draw() liest die Benutzerinteraktion mit der Maus, um die Region für die Bildsegmentierung auszuwählen. Die Box und das Bild werden an die Funktion algo_grabcut() übergeben, die das Bild nimmt und die binäre Maske für das segmentierte Bild erstellt.

Wir verwenden diese Maske und zeigen den Vordergrund des segmentierten Teils an.

Verwenden Sie die Farberkennung für die Bildsegmentierung mit opencv

In Python können wir das opencv zur Farberkennung verwenden. Für ein Bild stehen verschiedene Farbräume zur Darstellung seiner Farben zur Verfügung.

In unserem Fall verwenden wir den HSV-Farbraum, um die Bereiche für die jeweilige Farbe zu bestimmen.

Wir werden verschiedene Farben für die Bildsegmentierung verwenden. Wir erstellen einen Bereich für eine bestimmte Farbe und verwenden die Funktion inRange() aus der opencv-Bibliothek, um Objekte zu erkennen, die dieser Farbe entsprechen.

Dies gibt eine binäre Maske zurück. Wir verfeinern dann diese Maske und fügen diesem erkannten Teil Konturen hinzu.

Wie bereits erwähnt, sind Konturen die Kurven an den Grenzen des segmentierten Teils. Wir werden mit der Funktion findContours() die Ränder anhand der erstellten Maske finden und diese Konturen dann mit der Funktion drawContours() zeichnen.

Siehe Code unten.

import cv2
import numpy as np

img = cv2.imread("img4.jpg")
hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
bound_lower = np.array([36, 25, 25])
bound_upper = np.array([70, 255, 255])

mask_green = cv2.inRange(hsv_img, bound_lower, bound_upper)
kernel = np.ones((7, 7), np.uint8)

mask_green = cv2.morphologyEx(mask_green, cv2.MORPH_CLOSE, kernel)
mask_green = cv2.morphologyEx(mask_green, cv2.MORPH_OPEN, kernel)

seg_img = cv2.bitwise_and(img, img, mask=mask_green)
contours, hier = cv2.findContours(
    mask_green.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
)
output = cv2.drawContours(seg_img, contours, -1, (0, 0, 255), 3)

cv2.imshow("Result", seg_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

Ausgabe:

Bildsegmentierung mit Farberkennung

Im obigen Code segmentieren wir grüne Objekte aus einem gegebenen Bild. Zuerst wandeln wir das Bild mit der Funktion cvtColor in den HSV-Farbraum um.

Dann erstellen wir die Maske, die die erkannte Farbe speichert. Wir entfernen auch alle unerwünschten Geräusche von dieser Maske.

Dann zeichnen wir die Konturen zum erkannten Segment und zeigen es an. Die Funktion waitKey() verhindert das automatische Schliessen des Bildfensters.

Es wartet darauf, dass der Benutzer eine Taste drückt, und schließt es dann.

Fazit

In diesem Tutorial haben wir die Bildsegmentierung mit Pythons opencv-Bibliothek besprochen. Wir haben auch ein paar Techniken dafür implementiert, obwohl viele mehr möglich sind.

Wir haben die Grundlagen hinter der Bildsegmentierung besprochen und was der Ansatz und das Endergebnis bei jeder Methode sein wird.

Wir haben zwei Methoden ausführlich besprochen. Zuerst haben wir den GrabCut-Algorithmus implementiert.

Bei diesem Algorithmus wählt der Benutzer eine Region aus, die er für die Segmentierung verwenden möchte. Aus diesem Teil erkennen wir die Vordergrundobjekte und zeigen sie an.

Bei der zweiten Technik haben wir die Farberkennung verwendet. Wir haben Objekte von grüner Farbe entdeckt.

Bei dieser Art der Segmentierung konvertieren wir das Bild in den angegebenen Farbraum und verwenden die Farbbereiche aus diesem Modell, um Farben mit der Funktion inRange() zu erkennen. Wir verwenden diese Maske für die Bildsegmentierung und das Zeichnen von Konturen um die Kanten.

Manav Narula avatar Manav Narula avatar

Manav is a IT Professional who has a lot of experience as a core developer in many live projects. He is an avid learner who enjoys learning new things and sharing his findings whenever possible.

LinkedIn