Grundlegende Zusammenfassung der Python OpenCV-Bildverarbeitung (7) Bildsegmentierung basierend auf dem Wasserscheidenalgorithmus

1. Prinzip

1. Prinzip des Watershed-Algorithmus

  • Jedes Graustufenbild kann als topologische Ebene betrachtet werden, Gebiete mit hohen Grauwerten können als Berge betrachtet werden und Gebiete mit niedrigen Grauwerten können als Täler betrachtet werden. Wir gießen Wasser in verschiedenen Farben in jedes Tal. Wenn der Wasserstand steigt, treffen sich die Gewässer verschiedener Täler und laufen zusammen. Um zu verhindern, dass die Gewässer verschiedener Täler zusammenlaufen, müssen wir Dämme bauen, in denen das Wasser zusammenfließt. Ich bewässerte und baute Dämme, bis alle Gipfel untergetaucht waren. Der Damm, den wir gebaut haben, ist die Bildsegmentierung, die das Prinzip des Wassereinzugsgebietsalgorithmus darstellt.
  • OpenCV verwendet einen maskenbasierten Wassereinzugsgebietsalgorithmus. In diesem Algorithmus müssen die Talpunkte festgelegt werden, die konvergieren, und diejenigen, die nicht konvergieren. Dies ist eine interaktive Bildsegmentierung. Wir müssen lediglich die bereits bekannten Objekte beschriften. Wenn ein bestimmter Bereich definitiv der Vordergrund oder das Objekt ist, markieren Sie ihn mit einer bestimmten Farb- (oder Grauwert-) Beschriftung. Wenn ein bestimmter Bereich definitiv kein Objekt, sondern ein Hintergrund ist, markieren Sie ihn mit einem anderen Farbetikett. Die verbleibenden Bereiche, die nicht als Vordergrund oder Hintergrund bestimmt werden können, sind mit 0 markiert, was unsere Bezeichnung ist. Implementieren Sie dann den Wasserscheidenalgorithmus. Jedes Mal, wenn wir Wasser einfüllen, wird unser Etikett aktualisiert. Wenn sich zwei Etiketten unterschiedlicher Farbe treffen, bauen wir einen Damm, bis alle Spitzen untergetaucht sind, und schließlich erhalten wir den Wert des Grenzobjekts (des Damms) -1.

2. Entfernungstransformation

  • Die grundlegende Bedeutung der Abstandstransformation besteht darin, den Abstand von einem Nicht-Null-Pixel in einem Bild zum nächsten Null-Pixel zu berechnen, dh den kürzesten Abstand zum Null-Pixel
  • Der gebräuchlichste Distanztransformationsalgorithmus wird durch kontinuierliche Erosionsoperation realisiert. Die Stoppbedingung der Erosionsoperation besteht darin, dass alle Vordergrundpixel vollständig sind
  • Korrosion. Auf diese Weise erhalten wir gemäß der Reihenfolge der Korrosion den Abstand von jedem Vordergrundpixel zum mittleren Skelettpixel im Vordergrund
  • Entsprechend dem Abstandswert jedes Pixels wird ein anderer Grauwert eingestellt. Dies vervollständigt die Entfernungstransformation des Binärbildes

3. Die Verwendung von OpenCV-bezogenen Funktionen

cv2.distanceTransform(src, distanceType, maskSize, dst=None, dstType=None)
  • src: Binärbild eingeben
  • distanceType: So berechnen Sie die Entfernung
  • maskSize: Maskengröße
cv2.connectedComponents(image, labels=None, connectivity=None, ltype=None)
  • Bild: 8-Bit-Einkanalbild eingeben
  • Beschriftungen: Ausgabeetikettenzuordnung
  • Konnektivität: Konnektivität, der Standardwert ist 8, Sie können auch 4 nehmen
  • Itype: Ausgabe-Tag-Typ, der Standardwert ist CV_32S, er kann auch CV_16U sein
cv2.watershed(image, markers)
  • Bild: Eingabebild
  • Marker: Marker

2. Entfernungsbasierter Prozess zur Segmentierung von Wassereinzugsgebieten

Fügen Sie hier eine Bildbeschreibung ein

  • Wenn das Eingabebild verrauscht ist, entrauschen Sie zuerst
  • In Graustufenbild konvertieren
  • Binäre Verarbeitung, morphologische Operation
  • Entfernungstransformation
  • Finde Samen und generiere Marker
  • Implementieren Sie den Wasserscheidenalgorithmus und geben Sie das segmentierte Bild aus

Drei, Python-Code-Implementierung

import cv2 as cv
import numpy as np


def watershed_algorithm(image):
    # 边缘保留滤波EPF  去噪
    blur = cv.pyrMeanShiftFiltering(image,sp=10,sr=100)
    # 转成灰度图像
    gray = cv.cvtColor(blur, cv.COLOR_BGR2GRAY)
    # 得到二值图像   自适应阈值
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
    cv.imshow('binary image', binary)

    # 形态学操作   获取结构元素  开操作
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))
    opening = cv.morphologyEx(binary, cv.MORPH_OPEN, kernel=kernel, iterations=2)
    # 确定区域
    sure_bg = cv.dilate(opening, kernel, iterations=3)
    # cv.imshow('mor-opt', sure_bg)

    # 距离变换
    dist = cv.distanceTransform(opening, cv.DIST_L2, 3)
    dist_out = cv.normalize(dist, 0, 1.0, cv.NORM_MINMAX)
    # cv.imshow('distance-', dist_out * 50)
    ret, surface = cv.threshold(dist_out, dist_out.max() * 0.6, 255, cv.THRESH_BINARY)
    # cv.imshow('surface-markers', surface)

    surface_fg = np.uint8(surface)    # 转成8位整型
    unkonown = cv.subtract(sure_bg, surface_fg)        # 找到位置区域
    # Marker labelling
    ret, markers = cv.connectedComponents(surface_fg)  # 连通区域
    print(ret)

    # 分水岭变换
    # Add one to all labels so that sure background is not 0, but 1
    markers = markers + 1
    # Now, mark the region of unknown with zero
    markers[unkonown == 255] = 0
    # 实施分水岭算法了。标签图像将会被修改,边界区域的标记将变为 -1
    markers = cv.watershed(image, markers=markers)
    image[markers == -1] = [0, 0, 255]      # 被标记的区域   设为红色
    cv.imshow('result', image)


src = cv.imread(r'./test/042.png')
src = cv.resize(src, None, fx=0.5, fy=0.5)
cv.imshow('input image', src)
watershed_algorithm(src)
cv.waitKey(0)
cv.destroyAllWindows()

Der Operationseffekt ist wie folgt:

Fügen Sie hier eine Bildbeschreibung ein
Fügen Sie hier eine Bildbeschreibung ein

Fügen Sie hier eine Bildbeschreibung ein

Fügen Sie hier eine Bildbeschreibung ein

Ich denke du magst

Origin blog.csdn.net/fyfugoyfa/article/details/108150378
Empfohlen
Rangfolge