Python opencv画像処理の基本的なまとめ(7)流域アルゴリズムに基づく画像セグメンテーション

1.原則

1.流域アルゴリズムの原理

  • グレースケール画像はすべてトポロジー平面と見なすことができ、グレー値が高い領域は山と見なすことができ、グレー値が低い領域は谷と見なすことができます。それぞれの谷に色の違う水を注ぎます。水位が上がると、谷の水が合流して合流しますが、谷の水が合流しないように、水が合流する場所にダムを作る必要があります。私はすべての頂上が沈むまで灌漑とダムの建設を続けました。私たちが作成したダムは、画像分割です。これは、分水界アルゴリズムの背後にある原理です。
  • OpenCVは、マスクベースのウォーターシェッドアルゴリズムを使用しています。このアルゴリズムでは、収束する谷のポイントと収束しない谷のポイントを設定する必要があります。これはインタラクティブな画像セグメンテーションであり、すでに知っているオブジェクトにラベルを付けるだけです。特定の領域が前景またはオブジェクトである場合は、特定の色(またはグレー値)のラベルを付けます。特定の領域がオブジェクトではなく背景である場合は、別のカラーラベルを使用してマークします。フォアグラウンドまたはバックグラウンドとして判別できない残りの領域には、ラベルである0が付けられます。次に、流域アルゴリズムを実装します。水が満たされるたびに、ラベルが更新されます。異なる色の2つのラベルが出会うと、すべてのピークが水没するまでダムを構築し、最後に境界オブジェクト(ダム)-1の値を取得します。

2.距離変換

  • 距離変換の基本的な意味は、画像内の非ゼロピクセルから最も近いゼロピクセルまでの距離、つまりゼロピクセルまでの最短距離を計算することです。
  • 最も一般的な距離変換アルゴリズムは、連続的な侵食操作によって実現されます。侵食操作の停止条件は、すべての前景ピクセルが完全に
  • 腐食。このようにして、腐食の順序に従って、各前景ピクセルから前景中心スケルトンピクセルまでの距離を取得します
  • 各ピクセルの距離値に応じて、異なるグレー値に設定されます。これにより、バイナリイメージの距離変換が完了します。

3. opencv関連関数の使用法

cv2.distanceTransform(src, distanceType, maskSize, dst=None, dstType=None)
  • src:入力バイナリイメージ
  • distanceType:距離の計算方法
  • maskSize:マスクサイズ
cv2.connectedComponents(image, labels=None, connectivity=None, ltype=None)
  • 画像:入力8ビットシングルチャネル画像
  • ラベル:出力ラベルマップ
  • 接続:接続、デフォルトは8、4を使用することもできます
  • Itype:出力タグタイプ。デフォルトはCV_32Sです。CV_16Uにすることもできます。
cv2.watershed(image, markers)
  • 画像:入力画像
  • マーカー:マーカー

2.距離ベースの流域セグメンテーションプロセス

ここに画像の説明を挿入

  • 入力画像にノイズが多い場合は、まずノイズを除去します
  • グレースケール画像に変換
  • バイナリ処理、形態演算
  • 距離変換
  • 種子を見つけてマーカーを生成する
  • 流域アルゴリズムを実装し、セグメント化された画像を出力する

3、Pythonコードの実装

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()

作用効果は以下の通りです。

ここに画像の説明を挿入
ここに画像の説明を挿入

ここに画像の説明を挿入

ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/fyfugoyfa/article/details/108150378