OpenCV-形態学的処理(腐食、膨張、開放操作、閉鎖操作、トップハット、ボトムハット、形態学的勾配)

一般的に使用される形態学的処理方法には、腐食、膨張、開操作、閉操作、トップハット操作、ボトムハット操作があり、その中で腐食と膨張が最も基本的な方法であり、他の方法はこの2つの組み合わせによって生成されます。

腐食

構造要素:平滑化操作と同様に、長方形の近傍が平滑化操作で使用され、近傍は、形態学的処理で長方形の構造、または楕円形または十字形の構造にすることができます。また、アンカーポイントを指定する必要があります。

腐食作業では、構造要素の最小値がアンカーポイントの値として使用されます。腐食操作は、グレースケール画像またはバイナリ画像で実行できます。次の図を例として取り上げます(すべて中心点をアンカーポイントとします)。

ここに画像の説明を挿入

上の3つの図の近傍の最小値はそれぞれ11、21、21です。これらの最小値は画像のアンカーポイント位置に出力され、構造を移動することで完全な出力画像を取得できます。要素などは他の位置にあります。

上の図からわかるように、各場所の近傍の最小値が取られているため、腐食後の出力画像の全体的な明るさの平均値は、元の画像のそれよりも低くなります。画像の明るい領域は小さくなり、さらには消えます。暗い領域の領域は増加します。

画像が腐食した後、輝度領域の領域が減少するため、しきい値セグメンテーション後の前景の白いバイナリ画像の場合、元の画像と腐食した画像を差し引くことで前景の境界を取得できます。

OpenCV機能

エロード機能の公式アドレス

// 腐蚀
// C++
void cv::erode(InputArray 		src,
			 	OutputArray 	dst,
				InputArray 	    kernel,
				Point 	        anchor = Point(-1,-1),
				int 	        iterations = 1,
				int 	        borderType = BORDER_CONSTANT,
				const Scalar & 	borderValue = morphologyDefaultBorderValue() 
							)
  
// Python
dst=cv.erode(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])

パラメータの説明:

パラメータ 説明
src 入力行列、グレースケール画像またはバイナリ画像
dst 出力行列
カーネル 構造要素。getStructuringElement関数で取得できます。
アンカー アンカーポイントの位置。デフォルト値(-1、-1)は、アンカーポイントが構造要素の中心にあることを意味します。
反復 腐食の数
borderType 境界拡張タイプ
borderValue 境界の拡張

一般的に使用されるborderTypesは、BORDER_CONSTANT、BORDER_REPLICATE、およびBORDER_REFLECTです。BORDER_CONSTANTは定数拡張、BORDER_REPLICATEは境界複製拡張、BORDER_REFLECTはミラー拡張です。

GetStructuringElement関数の公式アドレス

// 获取结构元
// C++
Mat cv::getStructuringElement(int 	shape,
							Size 	ksize,
							Point 	anchor = Point(-1,-1) 
							)		
// Python:
retval	=	cv.getStructuringElement(	shape, ksize[, anchor])
パラメータ 説明
形状 構造要素の形状
ksize 構造要素のサイズ
アンカー 構造要素アンカー

構造要素の形状

  • MORPH_RECT

    構造要素

  • MORPH_CROSS

    構造要素

  • MORPH_ELLIPSE

    楕円形の構造要素

Pythonの例

import cv2 as cv

if __name__ == '__main__':
    img_src = cv.imread("img2.jpg", 0)

    # 创建矩形结构元
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5))
    # 腐蚀图像
    img_erode = cv.erode(img_src, kernel)
    # 边界提取
    img_edge = img_src - img_erode

    cv.imwrite("./images/img2_src.jpg", img_src)
    cv.imwrite("./images/img2_erode.jpg", img_erode)
    cv.imwrite("./images/img2_edge.jpg", img_edge)

バイナリグラフの腐食

ここに画像の説明を挿入

しきい値セグメンテーション後の画像には、必然的に散発的なホワイトノイズが多く含まれ、腐食によって除去される可能性があります。上の図からわかるように、腐食した構造要素が大きいほど、ターゲットオブジェクトの領域(白い領域)は小さくなります。画像が繰り返し腐食すると、ターゲットオブジェクト全体が削除されます。

グレースケールへの腐食

ここに画像の説明を挿入

グレースケール画像の腐食、構造要素のサイズが大きくなると、暗いグレースケール領域の面積も大きくなり、明るいグレースケール領域の面積が小さくなり、処理後の効果が漠然と見えます。構造要素、つまり、モザイク効果のように見える多くの重なり合う長方形の。楕円または十字形の構造要素が侵食に使用される場合、同様の楕円または十字形も表示されます。

うねり

拡張操作では、構造要素の最大値がアンカーポイントの値として使用されます。グレースケールまたはバイナリイメージに対して拡張操作を実行できます。拡大後、出力画像の全体的な明るさの平均値は元の画像と比較して増加し、画像の明るい領域の領域は大きくなり、暗い領域の領域は減少します。

OpenCV機能

拡張機能の公式アドレス

// 膨胀
// C++
void cv::dilate(InputArray 	  src,
				OutputArray   dst,
				InputArray 	  kernel,
				Point 	      anchor = Point(-1,-1),
				int 	      iterations = 1,
				int 	      borderType = BORDER_CONSTANT,
				const Scalar & 	borderValue = morphologyDefaultBorderValue() 
				)		
// Python:
dst	=cv.dilate(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])

パラメータは腐食操作のパラメータと同じです。

Pythonの例

次に、プログレスバーを使用して構造の半径を調整し、構造要素のサイズが形態学的処理に与える影響を観察します。

import cv2 as cv

def change_dilate_r(r):
    # 创建结构元
    kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, (2 * r + 1, 2 * r + 1))
    # 腐蚀图像
    img_dilate = cv.dilate(img_src, kernel)
    # 显示膨胀效果
    cv.imshow('dilate', img_dilate)


if __name__ == '__main__':
    img_src = cv.imread("img5.jpg", 0)
    # 显示原图
    cv.imshow("src", img_src)
    # 结构元半径
    r = 1
    max_r = 20
    # 显示膨胀效果的窗口
    cv.namedWindow('dilate', 1)
    # 调节结构元半径
    cv.createTrackbar('r', 'dilate', r, max_r, change_dilate_r)
    change_dilate_r(0)
    cv.waitKey(0)

ここに画像の説明を挿入

開操作と閉操作

オープン操作拡張前の腐食はオープン操作と呼ばれ、明るさの高い小さな領域を除去し、デリケートなポイントでオブジェクトを分離し、領域を大幅に変更することなく大きなオブジェクトの境界を滑らかにする機能があります。

閉じた操作は、最初に拡張してから腐食し、閉じた操作と呼ばれます。白いオブジェクトの小さなブラックホールを埋め、隣接するオブジェクト、同じ構造要素を接続し、複数の反復を行い、領域を大幅に変更せずに境界を平滑化する機能があります。

開操作と閉操作は膨張と腐食の組み合わせであり、侵食と膨張の機能を使用して実行できます。OpenCVは直接使用する機能も提供します。

OpenCV機能

形態Ex関数の公式ウェブサイトアドレス

// C++
void cv::morphologyEx(InputArray 	src,
					OutputArray 	dst,
					int 	op,
					InputArray 	kernel,
					Point 	anchor = Point(-1,-1),
					int 	iterations = 1,
					int 	borderType = BORDER_CONSTANT,
					const Scalar & 	borderValue = morphologyDefaultBorderValue() 
					)		
// Python:
dst	=cv.morphologyEx(src, op, kernel[,dst[,anchor[,iterations[,borderType[, borderValue]]]]])
パラメータ 説明
オン 形態学的操作の種類
カーネル 構造要素。getStructuringElement関数で取得できます。
アンカー アンカーポイントの位置。デフォルト値(-1、-1)は、アンカーポイントが構造要素の中心にあることを意味します。
反復 反復回数
borderType 境界拡張のタイプ。腐食を参照してください。
borderValue 境界膨張値、腐食を参照

形態学的操作のopタイプ

  • MORPH_ERODE腐蚀侵食
  • MORPH_DILATE拡張
  • MORPH_OPENオープン操作(最初に腐食、次に膨張)
  • MORPH_CLOSEクローズ操作(展開してから腐食)
  • MORPH_GRADIENT形態学的勾配
  • MORPH_TOPHATシルクハットの計算
  • MORPH_BLACKHATボトムハットの計算

Pythonの例

プログレスバーを使用して、構造の半径と反復回数を調整し、構造要素のサイズが形態学的処理に与える影響を観察します。

import cv2 as cv

def nothing(*args):
    pass

if __name__ == '__main__':
    img_src = cv.imread("img1.jpg", 0)

    r, i = 1, 1
    max_r, max_i = 20, 20

    cv.namedWindow('morphology', 1)
    cv.createTrackbar('r', 'morphology', r, max_r, nothing)
    cv.createTrackbar('i', 'morphology', i, max_i, nothing)

    while True:
        r = cv.getTrackbarPos('r', 'morphology')
        i = cv.getTrackbarPos('i', 'morphology')
        kernel = cv.getStructuringElement(cv.MORPH_RECT, (2*r+1, 2*r+1))
        # img_open = cv.morphologyEx(img_src, cv.MORPH_OPEN, kernel, iterations=i)
        # cv.imshow('morphology', img_open)
        img_erode = cv.erode(img_src, kernel, iterations=i)
        cv.imshow('morphology', img_erode)

        ch = cv.waitKey(5)
        if ch==27:
            break
        elif ch==115:
            # cv.imwrite(f'./images/img1_{i}.jpg', img_open)
            cv.imwrite(f'./images/img1_{i}.jpg', img_erode)
    cv.destroyAllWindows()

ここに画像の説明を挿入

上の図は、バイナリグラフでの開操作(上流)と腐食(下流)の処理効果を示しています.3x3の長方形構造要素を使用して、1、5、および20回の反復を順番に実行します。反復回数が増えると、開く操作によって白いオブジェクトの周りの小さくて明るい領域が削除され、白いオブジェクトの領域は大幅に変化せず、境界は局所的に滑らかになります。ただし、腐食操作を行うと、オブジェクトの面積が小さくなるか、消えることさえあります。拡張操作を複数回使用すると、白いオブジェクトの面積が徐々に増加します。

オープン操作には、非常に重要な機能もあります。暗い背景の下の明るい領域を削除します。下の図に示すように、目的は、黒いボールの領域を変更せずに、ボールの白い領域を削除することです。腐食操作はボールの面積を増やし、開操作はボールの面積が増えるのを防ぐことができます。

ここに画像の説明を挿入

下の図に示すように、閉じた操作の目的は、サイコロの黒い領域を削除することです。拡張と閉鎖の両方の操作を行うことができますが、拡張はサイコロの面積を増やしますが、閉鎖操作はできません。

ここに画像の説明を挿入

トップハット変換、ボトムハット変換および形態学的勾配

トップハット変換とボトムハット変換は、それぞれオープン操作とクローズ操作に基づいています

トップハット変換オープン操作の結果から元の画像が差し引かれます。開く操作では、暗い背景の下の明るい領域を削除できるため、元の画像から開いた操作の結果を差し引くと、元の画像の明るいグレースケール領域が得られるため、ホワイトトップハットとも呼ばれます。変換不均一な照明を修正できます。

ボトムハットは、閉じる操作の結果を差し引くことにより元の画像を変換します。閉じた操作では、明るい背景の下の暗い領域が削除される可能性があるため、閉じた操作の結果を元の画像から差し引くと、元の画像の暗いグレースケール領域を取得できるため、黒とも呼ばれます帽子の変形。

形態学的勾配膨張の結果から腐食の結果を差し引いたもの。膨張は近傍で最大値を取り、高輝度領域の面積を増やすことであり、腐食は近傍で最小値を取り、高輝度領域領域。したがって、結果の画像は画像内のオブジェクトの境界になります。

Pythonの例

import cv2 as cv

def nothing(*args):
    pass

if __name__ == '__main__':
    img_src = cv.imread("/img5.jpg", 0)

    r, i = 1, 1
    max_r, max_i = 20, 20

    type = 0
    max_type = 2

    cv.namedWindow("morphology", 1)
    cv.createTrackbar('r', 'morphology', r, max_r, nothing)
    cv.createTrackbar('i', 'morphology', i, max_i, nothing)
    cv.createTrackbar('t', 'morphology', type, max_type, nothing)
    m_type = cv.MORPH_TOPHAT
    while True:
        r = cv.getTrackbarPos('r', 'morphology')
        i = cv.getTrackbarPos('i', 'morphology')
        t = cv.getTrackbarPos('t', 'morphology')
        if t==0:
            m_type = cv.MORPH_TOPHAT
        elif t==1:
            m_type = cv.MORPH_BLACKHAT
        else:
            m_type = cv.MORPH_GRADIENT
            
        kernel = cv.getStructuringElement(cv.MORPH_RECT, (2*r+1, 2*r+1))
        img_mor = cv.morphologyEx(img_src, m_type, kernel, iterations=i)

        cv.imshow('morphology', img_mor)
        ch = cv.waitKey(5)
        if ch == 27:
            break
        elif ch == 115:
            cv.imwrite(f'./images/img_{t}.jpg', img_mor)
    cv.destroyAllWindows()

次の図は、3x3の長方形構造要素を使用した12回のシルクハット操作の結果、3x3の長方形構造要素を使用した10回のボトムハット操作の結果、および形態学的勾配操作の結果を示しています。

ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/m0_38007695/article/details/112710057