前回の記事では、YOLOv8を用いて物体検出を行いました。今回は YOLOv8-segモデル を用いて、検出した物体を画像から切り抜く方法を紹介します。
YOLOv8-segを利用することで、物体検出だけでなく、物体の輪郭情報を利用した画像処理が可能になります。

使用した環境

OS: Ubuntu 22.04
言語: Python 3
YOLOモデルの種類: YOLOv8-seg

必要なパッケージのインストール

YOLOv8を使用するために必要なパッケージをインストールします。
インストール方法については、以下の記事を参考にしてください。
<https://rtc-fukushima.jp/technical/7489/>

YOLOモデルの種類

YOLOは物体検出に用いられるアルゴリズムの一つで、画像内の物体を高速に検出することができます。YOLOには用途の異なる複数のモデルが存在し、目的に応じて適切なモデルを選択して使用します。YOLOv8-segは物体検出に加えてセグメンテーションマスク(物体の輪郭)を取得でき、検出した物体のみを切り抜くことができます。

モデル 主なタスク 用途
YOLOv8 物体検出 画像内の物体を矩形(Bounding Box)で囲んで検出するタスク。自動運転での歩行者・車両検知などに使用される。
YOLOv8-seg インスタンスセグメンテーション 物体を四角い枠だけでなく、輪郭を正確に切り抜くタスク。背景と物体を綺麗に分離したい場合(画像編集や医療画像解析など)に使用される。
YOLOv8-pose 姿勢推定 人間の関節位置や特定の特徴点(キーポイント)を推定するタスク。ジェスチャー認識などに使用される。
YOLOv8-obb 物体の向きを考慮した検出 斜めに傾いた物体に対して、傾きに合わせた矩形で検出するタスク。真上から撮影した航空写真(人工衛星画像)や文書画像の検出に使用される。
YOLOv8-cls 画像分類 画像全体を1つのカテゴリに分類するタスク(位置は特定しない)。製品検査や動物分類などに使用される。

サンプルプログラム

以下のサンプルプログラムは、YOLOv8-segを用いて画像内の物体を検出し、検出した物体を切り抜いて保存するプログラムです。指定した画像を読み込み、YOLOv8-segによって検出された物体ごとに画像を生成し保存します。

from ultralytics import YOLO
import cv2
import numpy as np
from ultralytics import YOLO

# モデルの読み込み(自動的にダウンロードされます)
model = YOLO("yolov8n-seg.pt")

# 画像の読み込み
img = cv2.imread("test.png")

# 物体検出の実行
results = model(img)

for result in results:
    if result.masks is None:
        continue

    # マスクのデータ、クラスID、を取得
    for i,(mask, cls) in enumerate(zip(result.masks.data, result.boxes.cls),start=1):

        # クラスIDを整数に変換
        class_id = int(cls.item())

        # 条件分岐:車(2) 以外はスキップする
        #if class_id != 2:
        #    continue

        # 切り出し処理
        mask = mask.cpu().numpy()
        mask = cv2.resize(mask, (img.shape[1], img.shape[0]))
        alpha = (mask * 255).astype(np.uint8)
        b, g, r = cv2.split(img)

        # 背景を透明にして物体を切り取る
        img_result = cv2.merge([b, g, r, alpha])

        # 結果をファイルに保存
        cv2.imwrite(f"result_{i}.png",img_result)

 

テスト画像

図 1 テスト画像(OpenAI「ChatGPT」により作成)

サンプルプログラムの実行

サンプルプログラムを yolov8seg_test.py、テスト画像を test.png のファイル名でホームディレクトリに保存します。
その後、ホームディレクトリで以下のコマンドを実行します。

python3 yolov8seg_test.py

初回実行時は、モデルの読み込みに時間がかかります。指定したモデル(ここではyolov8n-seg.pt)がプログラムと同じディレクトリに存在しない場合は、自動的にダウンロードされます。

プログラムを実行すると、画像内の物体を検出し、検出した物体ごとに切り抜いた画像が保存されます。
今回のサンプルプログラムでは、検出したすべての物体を対象として画像を保存します。

python3 yolov8seg_test.py 

0: 448x640 2 persons, 1 car, 566.1ms
Speed: 15.6ms preprocess, 566.1ms inference, 54.4ms postprocess per image at shape (1, 3, 448, 640)

図 2 検出した物体の切り抜きの結果(左および中央:人物, 右:車)

保存された画像(result_1.png、result_2.png、result_3.png)を確認すると、人物を切り抜いた画像が2枚、車を切り抜いた画像が1枚生成されています。今回のテスト画像では、人が車の近くに立っている影響で車と地面の境界が不明瞭となり、車の検出結果に地面の一部が含まれました。このように、物体同士が近接している場合や境界が不明瞭な場合には、物体を正確に切り抜けないことがあります。

一方、以下の画像のように人と車が十分に離れており、境界が明確な場合には、より高精度に物体を切り抜くことができます。

図 3 車の切り抜きの例(左:元画像(OpenAI「ChatGPT」により生成), 右:切り抜き画像)

切り抜く対象を選択したい場合

上記のサンプルプログラムは、認識したすべての物体を切り抜いて保存します。
特定の物体だけを切り抜きたい場合は、以下のコメントアウトを削除します。

        # 条件分岐:車(2) 以外はスキップする
        if class_id != 2:
            continue

例えば、上記のように設定すると、クラスIDが 2(車) の物体のみが保存対象となります。
また、クラスIDを 0 に変更すると人物のみを切り抜くことができます。

        if class_id != 0:
            continue

このように条件分岐を追加することで、必要な物体のみを切り抜いて保存することができます。

本記事では、YOLOv8-segを用いて画像内の物体を検出し、検出した物体を保存する方法を紹介しました。
YOLOv8-segを利用することで、物体検出に加えて、輪郭情報を活用した画像処理が可能となります。人物や車など特定の物体だけを抽出したい場合や、画像解析の前処理として活用できます。
今後、YOLOを用いた画像処理を行いたい方の参考になれば幸いです。