け日記

最近はPythonでいろいろやってます

OpenCV: ラベリング

今回はOpenCVを使って画像のラベリングを行います。いらすとやさんの画像を使わせていただきました。

ラベリングは画像を連続する領域ごとにラベルを付けることです。上の画像であれば、左の棒人形と右の棒人形が分離しているので、別々のラベルになります。

opencv-pythonでラベリングするメソッドは2つありますが、後者のconnectedComponentsWithStatsの方がより詳細な情報を返します。このため、connectedComponentsWithStatsのみを紹介します。

cv2.connectedComponentsWithStatsを使った実装は以下です。

  • まず2値化して領域を分離します
  • connectedComponentsWithStatsの引数は3つで、画像、4 or 8、型です
    • 2つ目の引数は4連結・8連結の区別です
  • connectedComponentsWithStatsの返り値は4つで、ラベル数、ラベルのマッピング画像、各ラベルの矩形領域 (x, y, width, height) 、各ラベルの中心点です
    • ラベル数は0の領域 (背景) も含むので、1の領域に限定する場合は-1する必要があります
import cv2
import numpy as np
import matplotlib.pyplot as plt

# グレースケールで読み込み
img = cv2.imread("./figure_talking.png", cv2.IMREAD_GRAYSCALE)

# 2値化
_, img = cv2.threshold(img, 16, 255, cv2.THRESH_BINARY)

# ラベリング
labels, label_imgs, bbox, center = cv2.connectedComponentsWithStats(img, 8, cv2.CV_32S)

print(labels)
# 3 -> 背景を含むラベル数

print(bbox)
# [[    0     0   375   400 73936]   -> 背景の矩形領域
#  [    7     7   166   384 36567]    -> 左の棒人形の矩形領域
#  [  148     7   218   384 39497]] -> 右の棒人形の矩形領域

print(center)
# [[193.08560106 206.94814434]
#  [ 77.2717751  192.04099325]
#  [277.19639466 192.46319974]]

print(label_imgs.shape, np.unique(label_imgs))
# (400, 375) [0 1 2] -> ラベルには0, 1, 2が使われている

plt.imshow(label_imgs)

ラベルのマッピング画像を表示すると、棒人形が異なる色で表示されており、別のラベルとなっていることがわかります。