OpenCV での画像セグメンテーション

Manav Narula 2023年1月30日
  1. Python で opencv を使用した画像セグメンテーション
  2. opencv を使用した画像セグメンテーションには GrabCut アルゴリズムを使用する
  3. opencv を使用した画像セグメンテーションに色検出を使用
  4. まとめ
OpenCV での画像セグメンテーション

画像処理は、コンピュータビジョンタスクの重要なステップです。Python では、opencv ライブラリを使用して、さまざまなオブジェクトやメソッドを使用していくつかの画像処理技術を実装できます。

このチュートリアルでは、Python で opencv を使用して画像セグメンテーションを実行する方法を示します。

Python で opencv を使用した画像セグメンテーション

画像セグメンテーションとは、特定の画像をいくつかの部分に分割するプロセスを指します。

セグメント化されたパーツの境界に沿ってポイントを結合するカーブを追加します。これらの曲線は等高線と呼ばれます。

画像セグメンテーションはコンピュータビジョンで非常に役立ち、多くの実際のアプリケーションがあります。この手法を使用して、画像の一部をセグメント化し、さまざまなオブジェクトを分類できます。

Python で opencv を使用した画像セグメンテーションには、利用可能ないくつかの方法を使用できます。

すべての画像セグメンテーション手法で異なる主な方法は、通常、セグメント化された画像の基準に基づいています。いくつかの色の検出、Watershed アルゴリズムなどの事前定義されたアルゴリズム、エッジ検出、さらにはユーザー入力に基づいてセグメント化された部分の選択に基づいて、画像のセグメンテーションを行うことができます。

これらの方法のいくつかについては、次のセクションで説明します。

opencv を使用した画像セグメンテーションには GrabCut アルゴリズムを使用する

この方法では、ユーザーがマウスとキーボードを操作する必要があります。組み込みの opencv ライブラリには、マウスとキーボードからユーザー入力を読み取ることができるオブジェクトとメソッドがあります。

GrabCut アルゴリズムは、画像セグメンテーションのための非常にシンプルで便利なツールです。この手法では、ユーザー入力を使用して、特定の画像の一部の領域を選択します。

このアルゴリズムは、セグメント化された部分の前景と背景を自動的に検出し、それらを表示できます。

opencv ライブラリの grabCut() 関数を使用して、このアルゴリズムを実装できます。画像セグメンテーションのために、この関数内の選択された領域のボックスと一緒に画像を渡します。

例については、次のコードを参照してください。

import cv2
import numpy as np


def algo_grabcut(img, bounding_box):
    seg = np.zeros(img.shape[:2], np.uint8)
    x, y, width, height = bounding_box
    seg[y : y + height, x : x + width] = 1
    background_mdl = np.zeros((1, 65), np.float64)
    foreground_mdl = np.zeros((1, 65), np.float64)

    cv2.grabCut(
        img, seg, bounding_box, background_mdl, foreground_mdl, 5, cv2.GC_INIT_WITH_RECT
    )

    mask_new = np.where((seg == 2) | (seg == 0), 0, 1).astype("uint8")
    img = img * mask_new[:, :, np.newaxis]
    cv2.imshow("Output", img)


def box_draw(click, x, y, flag_param, parameters):
    global x_pt, y_pt, drawing, topleft_pt, bottomright_pt, img

    if click == cv2.EVENT_LBUTTONDOWN:
        drawing = True
        x_pt, y_pt = x, y

    elif click == cv2.EVENT_MOUSEMOVE:
        if drawing:
            topleft_pt, bottomright_pt = (x_pt, y_pt), (x, y)
            image[y_pt:y, x_pt:x] = 255 - img[y_pt:y, x_pt:x]
            cv2.rectangle(image, topleft_pt, bottomright_pt, (0, 255, 0), 2)

    elif click == cv2.EVENT_LBUTTONUP:
        drawing = False
        topleft_pt, bottomright_pt = (x_pt, y_pt), (x, y)
        image[y_pt:y, x_pt:x] = 255 - image[y_pt:y, x_pt:x]
        cv2.rectangle(image, topleft_pt, bottomright_pt, (0, 255, 0), 2)
        bounding_box = (x_pt, y_pt, x - x_pt, y - y_pt)

        algo_grabcut(img, bounding_box)


drawing = False
topleft_pt, bottomright_pt = (-1, -1), (-1, -1)

img = cv2.imread("img4.jpg")
img = cv2.resize(img, (500, 500))
image = img.copy()
cv2.namedWindow("Frame")
cv2.setMouseCallback("Frame", box_draw)

while True:
    cv2.imshow("Frame", image)
    ch = cv2.waitKey(1)
    if ch == 32:
        break

cv2.destroyAllWindows()

出力:

グラブカットアルゴリズムの選択された領域

GrabCut アルゴリズムを使用してセグメント化された画像

上記の例で何が起こっているのかを理解しましょう。

box_draw() 関数は、マウスとのユーザーインタラクションを読み取り、画像セグメンテーションの領域を選択します。ボックスと画像は、画像を取得してセグメント化された画像のバイナリマスクを作成する algo_grabcut() 関数に渡されます。

このマスクを使用して、セグメント化された部分の前景を表示します。

opencv を使用した画像セグメンテーションに色検出を使用

Python では、色の検出に opencv を使用できます。画像がその色を表すために使用できるさまざまな色空間があります。

この場合、HSV 色空間を使用して、特定の色の範囲を決定します。

画像のセグメンテーションには異なる色を使用します。特定の色の範囲を作成し、opencv ライブラリの inRange() 関数を使用して、この色に一致するオブジェクトを検出します。

これにより、バイナリマスクが返されます。次に、このマスクを改良し、この検出された部分に輪郭を追加します。

前に説明したように、輪郭はセグ​​メント化されたパーツの境界上の曲線です。findContours() 関数を使用して、作成したマスクを使用して境界線を見つけ、drawContours() 関数を使用してこれらの輪郭を描画します。

以下のコードを参照してください。

import cv2
import numpy as np

img = cv2.imread("img4.jpg")
hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
bound_lower = np.array([36, 25, 25])
bound_upper = np.array([70, 255, 255])

mask_green = cv2.inRange(hsv_img, bound_lower, bound_upper)
kernel = np.ones((7, 7), np.uint8)

mask_green = cv2.morphologyEx(mask_green, cv2.MORPH_CLOSE, kernel)
mask_green = cv2.morphologyEx(mask_green, cv2.MORPH_OPEN, kernel)

seg_img = cv2.bitwise_and(img, img, mask=mask_green)
contours, hier = cv2.findContours(
    mask_green.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
)
output = cv2.drawContours(seg_img, contours, -1, (0, 0, 255), 3)

cv2.imshow("Result", seg_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

出力:

色検出を使用した画像セグメンテーション

上記のコードでは、特定の画像から緑色のオブジェクトをセグメント化します。まず、cvtColor 関数を使用して画像を HSV 色空間に変換します。

次に、検出された色を保存するマスクの作成に進みます。このマスクからも不要なノイズを取り除きます。

次に、検出されたセグメントに輪郭を描画して表示します。waitKey() 関数は、画像ウィンドウが自動的に閉じるのを防ぎます。

ユーザーがキーを押してから閉じるのを待ちます。

まとめ

このチュートリアルでは、Python の opencv ライブラリを使用した画像セグメンテーションについて説明しました。このためにいくつかの手法も実装しましたが、さらに多くの手法が可能です。

画像セグメンテーションの背後にある基本と、すべての方法でのアプローチと最終結果について説明しました。

2つの方法について詳しく説明しました。まず、GrabCut アルゴリズムを実装しました。

このアルゴリズムでは、ユーザーはセグメンテーションに使用する領域を選択します。この部分から、前景オブジェクトを検出して表示します。

2 番目の手法では、色検出を使用しました。緑色の物体を検出しました。

このタイプのセグメンテーションでは、画像を指定された色空間に変換し、このモデルの色範囲を使用して、inRange() 関数を使用して色を検出します。このマスクを使用して、画像のセグメンテーションとエッジの周りの輪郭の描画を行います。

著者: Manav Narula
Manav Narula avatar Manav Narula avatar

Manav is a IT Professional who has a lot of experience as a core developer in many live projects. He is an avid learner who enjoys learning new things and sharing his findings whenever possible.

LinkedIn