OpenCV

【OpenCV-Python】ラベリング(connectedComponents)

ラベリングとは、二値化された画像において、画素がつながっている領域に対して同じ番号(ラベル)を与える処理のことを言います。

このつながっている領域のことをブロブ(blob)といいますが、このブロブに対して、面積や幅、高さなどを求め、キズや打痕、汚れなどの欠陥検査を行うための前処理として、ラベリング処理が用いられることが多いです。

↓ラベリング

詳細はこちら↓を参照ください。

ラベリング
二値化画像処理された画像において、白の部分(または黒の部分)が連続した画素に同じ番号を割り振る処理を ラベリングと言います。 通常、同じ番号ごとの面積(画素数)や幅、高さなどの特徴量を求めて欠陥検査や分類処理などに用いられま...

 

OpenCVでラベリング処理を行うには、connectedComponents()関数を用います。

関連して、connectedComponentsWithStats()connectedComponentsWithStatsWithAlgorithm()という関数もあります。

 

connectedComponents()関数は、二値化画像に対して、ラベリング画像のみを出力します。

 

connectedComponentsWithStats()関数は、ラベリング画像に追加して、さらにブロブの領域(位置、幅、高さ)と面積、重心の情報を出力します。

 

connectedComponentsWithStatsWithAlgorithm()関数は、さらに、ラベリング処理時の4連結、8連結の指定や出力するラベリング画像のデータ型の指定、ラベリング処理アルゴリズムの指定が可能になっています。

処理アルゴリズムについては、詳細は分からなかったのですが、こちら↓を参照くだだい。

OpenCV: Structural Analysis and Shape Descriptors

 

connectedComponents()関数

connectedComponents( image[, labels[, connectivity[, ltype]]] ) -> retval, labels
引数 説明
image ラベリング処理を行う入力画像
8bit1chである必要があります。
labels ラベリング結果を格納する画像データ
戻り値で戻すこともできるので、指定しないか、Noneを指定でも大丈夫です。
connectivity 8連結の場合は 8、4連結の場合は 4 を指定します。
ltype 出力されるラベリング画像の型を指定します。
cv2.CV_16U もしくは cv2.CV_32S(初期値)
(戻り値)retval ラベルの個数が返されます。
ただし、背景も1つとしてカウントされます。
(戻り値)labels 出力されるラベリング画像

connectedComponentsWithStats()関数

connectedComponentsWithStats( image[, labels[, stats[, centroids[, connectivity[, ltype]]]]] ) -> retval, labels, stats, centroids
引数 説明
image ラベリング処理を行う入力画像
8bit1chである必要があります。
labels ラベリング結果を格納する画像データ
戻り値で戻すこともできるので、指定しないか、Noneを指定でも大丈夫です。
connectivity 8連結の場合は 8、4連結の場合は 4 を指定します。
ltype 出力されるラベリング画像の型を指定します。
cv2.CV_16U もしくは cv2.CV_32S(初期値)
(戻り値)retval ラベルの個数が返されます。
ただし、背景も1つとしてカウントされます。
(戻り値)labels 出力されるラベリング画像
(戻り値)stats 各ラベルごとの領域の情報が格納されます。
[領域の左上のx座標, 領域の左上のy座標, 領域の幅, 領域の高さ, 面積]
面積は領域の画素数です。
(戻り値)centroids 各ラベルごとの重心の情報が格納されます。

※labels, stats, centroidsの最初のデータは背景の情報となります。

 

connectedComponentsWithStats()関数

connectedComponentsWithStatsWithAlgorithm( image, connectivity, ltype, ccltype[, labels[, stats[, centroids]]] ) -> retval, labels, stats, centroids
引数 説明
image ラベリング処理を行う入力画像
8bit1chである必要があります。
labels ラベリング結果を格納する画像データ
戻り値で戻すこともできるので、指定しないか、Noneを指定でも大丈夫です。
connectivity 8連結の場合は 8、4連結の場合は 4 を指定します。
ltype 出力されるラベリング画像の型を指定します。
cv2.CV_16U もしくは cv2.CV_32S(初期値)
ccltype ラベリング処理アルゴリズムを指定します。
cv2.CCL_DEFAULT, cv2.CCL_WU, cv2.CCL_GRANA, cv2.CCL_BOLELLI, cv2.CCL_SAUF, cv2.CCL_BBDT, cv2.CCL_SPAGHETTI
(参考)
OpenCV: Structural Analysis and Shape Descriptors
(戻り値)retval ラベルの個数が返されます。
ただし、背景も1つとしてカウントされます。
(戻り値)labels 出力されるラベリング画像
(戻り値)stats 各ラベルごとの領域の情報が格納されます。
[領域の左上のx座標, 領域の左上のy座標, 領域の幅, 領域の高さ, 面積]
面積は領域の画素数です。
(戻り値)centroids 各ラベルごとの重心の情報が格納されます。

※labels, stats, centroidsの最初のデータは背景の情報となります。

connectedComponentsWithStats()関数は、おそらく下記のようにするのと同じです。(アルゴリズムの指定がちょっと怪しい。。)

retval, labels, stats, centroids = cv2.connectedComponentsWithStatsWithAlgorithm(img, 8, cv2.CV_32S, cv2.CCL_DEFAULT)

 

ラベリング処理例

最初にも触れましたが、ラベリングは画像中のキズや打痕、汚れなどの検出に使われる場合が多いです。

下図のように画像中にキズ、打痕、ホコリのようなものがあるときに、黒い部分の面積が大きい部分を検出する例のサンプルプログラムを作成しました。

OpenCV ラベリング connectedComponents

import cv2
import numpy as np

# 8ビット1チャンネルのグレースケールとして画像を読み込む
img = cv2.imread("image.jpg", cv2.IMREAD_GRAYSCALE) 

# 画像表示用に入力画像をカラーデータに変換する
img_disp = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)

# 二値化(二値化して白黒反転)
retval, img = cv2.threshold(img, 200, 255, cv2.THRESH_BINARY_INV)

# クロージング処理(細切れ状態を防ぐため)
kernel = np.ones((3, 3), np.uint8)
img = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel, iterations=15)

# ラベリング
retval, labels, stats, centroids = cv2.connectedComponentsWithStats(img)

# 結果表示
for i in range(1, retval):
    x, y, width, height, area = stats[i] # x座標, y座標, 幅, 高さ, 面積

    if area > 10: # 面積が10画素以上の部分
        cv2.rectangle(img_disp,(x,y),(x+width,y+height),(0,0,255),2)
        cv2.putText(img_disp, f"[{i}]:{area}", (x, y-10), cv2.FONT_HERSHEY_PLAIN, 1, (255, 0, 0), 1, cv2.LINE_AA)

cv2.imshow("image", img_disp)
cv2.waitKey()

実行結果

OpenCV ラベリング connectedComponents

 

connectedComponentsWithStatsとfindContoursの違い

ブロブの幅や高さ、面積などを解析することをブロブ解析と言いますが、connectedComponentsWithStats()関数で取得できる情報は、ブロブの領域(傾いていない矩形領域)、面積、重心だけですが、輪郭処理ベースのfindContours()関数では、ブロブの傾いた領域や外接円、楕円近似、直線近似、周囲長、凸法など出来る事が多くあるので、必要に応じて使い分けるといいと思います。

ただし、connectedComponentsWithStats()関数はブロブの画素に関する情報を取得しますが、findContours()関数は、あくまでの輪郭の情報を取得するので注意してください。

例えば、下図のような画像のとき

OpenCV ラベリング connectedComponents

connectedComponentsWithStats()関数では面積(画素数)は8となりますが、findContours()関数では面積(輪郭の内側の面積、上図の赤線の四角の面積)は4となり、さらに輪郭の内側に白では無い画素があっても考慮されません。

 

関連記事

【OpenCV-Python】ラベリング(connectedComponents)
ラベリングとは、二値化された画像において、画素がつながっている領域に対して同じ番号(ラベル)を与える処理のことを言います。 このつながっている領域のことをブロブ(blob)といいますが、このブロブに対して、面積や幅、高さなどを求め、キ...
【OpenCV-Python】findContoursによる輪郭検出
OpenCV(Python)で二値化された画像中の白の部分または黒の部分の輪郭のデータを取得するにはfindContours()関数を用います。 findContours()関数で取得できる情報は、輪郭を構成している点の座標群と輪郭の...
【OpenCV-Python】輪郭(contour)の面積(contourArea)
OpenCVで二値化された領域の輪郭座標は、findContours関数を使えば取得することができます。 このときの戻り値である輪郭情報(contours)をcontourArea関数へ渡し面積を求めます。 ただし、求まる面積は...
【OpenCV-Python】輪郭(contour)の矩形領域の取得
OpenCVのfindContours関数などで得られた点の座標から、点を囲う矩形領域(四角形の領域)を取得するにはboundingRect関数を用います。 さらに、傾きを考慮した矩形領域を取得するにはminAreaRect関数を用い...
膨張・収縮・オープニング・クロージング
膨張・収縮処理では一般的に二値化された白黒の画像に対して処理が行われ、 注目画素の周辺に1画素でも白い画素があれば白に置き換える処理を膨張(Dilation)、 逆に周辺に1画素でも黒い画素があれば黒に置き換える処理を収縮(Eros...

コメント

タイトルとURLをコピーしました