コンテンツにスキップ

セグメンテーションオブジェクトの分離

セグメントタスクを実行した後、推論結果から分離されたオブジェクトを抽出することが望ましい場合があります。このガイドでは、Ultralyticsの予測モードを使用してこれを実現する方法の一般的なレシピを提供します。

分離されたオブジェクトセグメンテーションの例

レシピのウォークスルー

  1. 必要なライブラリのインストールに関する簡単な説明は、Ultralyticsクイックスタートインストールセクションを参照してください。


  2. モデルをロードして実行 predict() ソースに対するメソッド。

    from ultralytics import YOLO
    
    # Load a model
    model = YOLO("yolo11n-seg.pt")
    
    # Run inference
    results = model.predict()
    

    予測引数はありませんか?

    ソースを指定しない場合、ライブラリのサンプル画像が使用されます。

    'ultralytics/assets/bus.jpg'
    'ultralytics/assets/zidane.jpg'
    

    これは、を使用して迅速なテストを行うのに役立ちます。 predict() メソッド。

    セグメンテーションモデルに関する追加情報については、こちらをご覧ください。 セグメントタスク ページ。詳細については predict() メソッドについては、 予測モード ドキュメントのセクションを参照してください。


  3. 次に、結果と輪郭を反復処理します。画像をファイルに保存するワークフローの場合、ソース画像は base-name そして、検出。 class-label 後で使用するために取得されます(オプション)。

    from pathlib import Path
    
    import numpy as np
    
    # (2) Iterate detection results (helpful for multiple images)
    for r in res:
        img = np.copy(r.orig_img)
        img_name = Path(r.path).stem  # source image base-name
    
        # Iterate each object contour (multiple detections)
        for ci, c in enumerate(r):
            # (1) Get detection class name
            label = c.names[c.boxes.cls.tolist().pop()]
    
    1. 検出結果の操作について詳しくは、予測モードのBoxesセクションをご覧ください。
    2. 詳細については predict() 結果については、以下を参照してください。 予測モードでの結果の操作
    For-Loop

    単一の画像は、最初のループを 1 回だけ反復処理します。単一の検出のみを含む単一の画像は、各ループを1 回のみ反復処理します。


  4. まず、ソース画像からバイナリマスクを生成し、マスク上に塗りつぶされた輪郭を描画します。これにより、オブジェクトを画像の他の部分から分離できます。からの例を以下に示します。 bus.jpg 検出されたオブジェクトの1つ person classオブジェクトは右側に表示されます。

    バイナリマスク画像

    import cv2
    
    # Create binary mask
    b_mask = np.zeros(img.shape[:2], np.uint8)
    
    # (1) Extract contour result
    contour = c.masks.xy.pop()
    # (2) Changing the type
    contour = contour.astype(np.int32)
    # (3) Reshaping
    contour = contour.reshape(-1, 1, 2)
    
    
    # Draw contour onto mask
    _ = cv2.drawContours(b_mask, [contour], -1, (255, 255, 255), cv2.FILLED)
    
    1. 詳細については c.masks.xy 参照 予測モードのマスクセクション.

    2. ここでは、値はにキャストされます。 np.int32 との互換性のため。 drawContours() 関数は OpenCV.

    3. OpenCV drawContours() 関数は、輪郭が次の形状を持つことを想定しています [N, 1, 2] 下記のexpandセクションの説明をご覧ください。

    展開して定義時に何が起こるかを理解してください contour 変数。

    - c.masks.xy :: マスクの輪郭点の座標を以下の形式で提供します (x, y)。詳細については、以下を参照してください。 予測モードのマスクセクション。 - .pop() :: 以下として masks.xy は単一の要素を含むリストであり、この要素は以下を使用して抽出されます。 pop() メソッド。 - .astype(np.int32) :: 以下を使用 masks.xy のデータ型で返されます float32)ですが、OpenCVとの互換性はありません。 drawContours() 関数なので、データ型が以下に変わります int32 互換性のために。 - .reshape(-1, 1, 2) :: データを以下の必要な形状に再フォーマットします [N, 1, 2] 場所: N は輪郭点の数で、各点は単一のエントリで表されます。 1、およびエントリは以下で構成されます。 2 値を示します。 -1 は、この次元に沿った値の数が可変であることを示します。

    詳細については、展開して drawContours() 構成。

    - をカプセル化します。 contour 変数は角括弧で囲まれており、 [contour]は、テスト中に目的の輪郭マスクを効果的に生成することがわかりました。 - 値 -1 指定された drawContours() parameterは、画像に存在するすべての輪郭を描画するように関数に指示します。 - tuple (255, 255, 255) は、このバイナリマスクで輪郭を描画するために望ましい色である白色を表します。 - の追加 cv2.FILLED 輪郭の境界線で囲まれたすべてのピクセルを同じ色で塗りつぶします。この場合、囲まれたすべてのピクセルは白になります。 - 参照 OpenCVドキュメント(外部リンク) drawContours() 詳細については、こちらをご覧ください。


  5. 次に、この時点からの画像の処理方法について2つのオプションがあり、それぞれに後続のオプションがあります。

    オブジェクト分離オプション

    # Create 3-channel mask
    mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
    
    # Isolate object with binary mask
    isolated = cv2.bitwise_and(mask3ch, img)
    
    これはどのように機能しますか?
    • まず、バイナリマスクをシングルチャネル画像から3チャネル画像に変換します。この変換は、マスクと元の画像を結合する後続のステップに必要です。両方の画像は、ブレンディング操作と互換性があるように、同じ数のチャネルを持っている必要があります。

    • 元の画像と3チャンネルのバイナリマスクは、OpenCV関数を使用して結合されます。 bitwise_and()。この操作は以下を保持します: のみ ゼロより大きいピクセル値 (> 0) 両方の画像から。マスクピクセルがゼロより大きいため (> 0) のみ 輪郭領域内では、元の画像から残ったピクセルは、輪郭と重なっているピクセルです。

    黒いピクセルで分離:サブオプション

    フルサイズの画像

    フルサイズの画像を維持する場合は、追加の手順は必要ありません。

    背景が黒のフルサイズの分離されたオブジェクト画像の例
    フルサイズ出力の例

    切り抜かれたオブジェクト画像

    オブジェクト領域のみを含むように画像を切り抜くために必要な追加の手順。

    背景が黒の分離されたオブジェクト画像のサンプルクロップ

    # (1) Bounding box coordinates
    x1, y1, x2, y2 = c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32)
    # Crop image to object region
    iso_crop = isolated[y1:y2, x1:x2]
    

    1. bounding boxの結果に関する詳細については、Predict Mode の Boxes Sectionをご覧ください。
    このコードは何をしますか?
    • The c.boxes.xyxy.cpu().numpy() コールは、NumPy 配列としてバウンディングボックスを取得します。 xyxy 形式、ここで xmin, ymin, xmax、および ymax は、バウンディングボックスの矩形の座標を表します。詳細については、以下を参照してください。 PredictモードのBoxesセクション 詳細については。

    • The squeeze() operationは、NumPy配列から不要な次元を削除し、期待される形状にすることを保証します。

    • を使用して座標値を変換する .astype(np.int32) ボックス座標のデータ型を次のように変更します。 float32 宛先 int32ため、インデックススライスを使用した画像の切り抜きに対応できます。

    • 最後に、境界ボックス領域は、インデックススライスを使用して画像から切り取られます。境界は以下によって定義されます。 [ymin:ymax, xmin:xmax] 検出バウンディングボックスの座標。

    # Isolate object with transparent background (when saved as PNG)
    isolated = np.dstack([img, b_mask])
    
    これはどのように機能しますか?
    • NumPy の使用 dstack() 関数(深度軸に沿って配列をスタック)は、生成されたバイナリマスクと組み合わせて、4つのチャネルを持つ画像を作成します。これにより、オブジェクトの輪郭の外側のすべてのピクセルを透明にして保存できます。 PNG file。

    透明なピクセルで分離:サブオプション

    フルサイズの画像

    フルサイズの画像を維持する場合は、追加の手順は必要ありません。

    背景なしのフルサイズの分離されたオブジェクト画像の例
    フルサイズ出力+透明な背景の例

    切り抜かれたオブジェクト画像

    オブジェクト領域のみを含むように画像を切り抜くために必要な追加の手順。

    背景なしの分離されたオブジェクト画像のサンプルクロップ

    # (1) Bounding box coordinates
    x1, y1, x2, y2 = c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32)
    # Crop image to object region
    iso_crop = isolated[y1:y2, x1:x2]
    

    1. bounding boxの結果に関する詳細については、Predict Mode の Boxes Sectionをご覧ください。
    このコードは何をしますか?
    • 使用する場合 c.boxes.xyxy.cpu().numpy()場合、バウンディングボックスはNumPy配列として返され、 xyxy ボックス座標形式。これは点に対応します。 xmin, ymin, xmax, ymax バウンディングボックス(長方形)については、 PredictモードのBoxesセクション 詳細については、こちらをご覧ください。

    • 追加中 squeeze() NumPy配列から不要な次元が削除されるようにします。

    • を使用して座標値を変換する .astype(np.int32) ボックス座標のデータ型を次のように変更します。 float32 宛先 int32 これは、インデックススライスを使用して画像をクロップする際に互換性があります。

    • 最後に、境界ボックスの画像領域は、インデックススライスを使用して切り取られます。境界は以下を使用して設定されます。 [ymin:ymax, xmin:xmax] 検出バウンディングボックスの座標。

    背景を含めて、切り抜かれたオブジェクトが必要な場合はどうすればよいですか?

    これは、Ultralytics ライブラリに組み込まれている機能です。詳細については、こちらを save_crop 引数 予測モードの推論引数 詳細について。


  6. 次のステップをどうするかは、開発者であるあなた次第です。 可能な次のステップの基本的な例(後で使用するために画像をファイルに保存する)を示します。

    • 注意: このステップはオプションであり、特定のユースケースで不要な場合はスキップできます。
    最終ステップの例
    # Save isolated object to file
    _ = cv2.imwrite(f"{img_name}_{label}-{ci}.png", iso_crop)
    
    • この例では、 img_name は、ソース画像ファイルのベース名です。 label は、検出されたクラス名です。そして ci は、のインデックスです。 物体検出 (同じクラス名で複数のインスタンスが存在する場合)。

コード例

ここでは、前のセクションのすべてのステップが単一のコードブロックにまとめられています。繰り返し使用する場合は、含まれるコマンドの一部またはすべてを実行する関数を定義するのが最適です。 for-ループですが、それは読者への課題として残されています。

from pathlib import Path

import cv2
import numpy as np

from ultralytics import YOLO

m = YOLO("yolo11n-seg.pt")  # (4)!
res = m.predict()  # (3)!

# Iterate detection results (5)
for r in res:
    img = np.copy(r.orig_img)
    img_name = Path(r.path).stem

    # Iterate each object contour (6)
    for ci, c in enumerate(r):
        label = c.names[c.boxes.cls.tolist().pop()]

        b_mask = np.zeros(img.shape[:2], np.uint8)

        # Create contour mask (1)
        contour = c.masks.xy.pop().astype(np.int32).reshape(-1, 1, 2)
        _ = cv2.drawContours(b_mask, [contour], -1, (255, 255, 255), cv2.FILLED)

        # Choose one:

        # OPTION-1: Isolate object with black background
        mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
        isolated = cv2.bitwise_and(mask3ch, img)

        # OPTION-2: Isolate object with transparent background (when saved as PNG)
        isolated = np.dstack([img, b_mask])

        # OPTIONAL: detection crop (from either OPT1 or OPT2)
        x1, y1, x2, y2 = c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32)
        iso_crop = isolated[y1:y2, x1:x2]

        # TODO your actions go here (2)
  1. 行の入力 contour は、上記では複数行に分割されていましたが、ここでは1行にまとめられています。
  2. ここには何を書きますか?
  3. 詳細については、Predict Modeを参照してください。
  4. 詳細については、Segment Taskを参照してください。
  5. 結果の操作の詳細はこちら
  6. セグメンテーションマスクの結果の詳細はこちら

よくある質問

セグメンテーションタスクのためにUltralytics YOLO11を使用してオブジェクトを分離するにはどうすればよいですか?

Ultralytics YOLO11を使用してオブジェクトを分離するには、次の手順に従ってください:

  1. モデルをロードして推論を実行:

    from ultralytics import YOLO
    
    model = YOLO("yolo11n-seg.pt")
    results = model.predict(source="path/to/your/image.jpg")
    
  2. バイナリマスクを生成し、輪郭を描画します:

    import cv2
    import numpy as np
    
    img = np.copy(results[0].orig_img)
    b_mask = np.zeros(img.shape[:2], np.uint8)
    contour = results[0].masks.xy[0].astype(np.int32).reshape(-1, 1, 2)
    cv2.drawContours(b_mask, [contour], -1, (255, 255, 255), cv2.FILLED)
    
  3. バイナリマスクを使用してオブジェクトを分離します:

    mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
    isolated = cv2.bitwise_and(mask3ch, img)
    

詳細については、Predict ModeおよびSegment Taskのガイドを参照してください。

セグメンテーション後、分離されたオブジェクトを保存するためにどのようなオプションがありますか?

Ultralytics YOLO11 は、分離されたオブジェクトを保存するための2つの主なオプションを提供します。

  1. 黒背景の場合:

    mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
    isolated = cv2.bitwise_and(mask3ch, img)
    
  2. 透明背景の場合:

    isolated = np.dstack([img, b_mask])
    

詳細については、Predict Modeのセクションをご覧ください。

Ultralytics YOLO11を使用して、分離されたオブジェクトをバウンディングボックスにトリミングするにはどうすればよいですか?

分離されたオブジェクトをバウンディングボックスにトリミングするには:

  1. バウンディングボックスの座標を取得:

    x1, y1, x2, y2 = results[0].boxes.xyxy[0].cpu().numpy().astype(np.int32)
    
  2. 分離された画像を切り抜く:

    iso_crop = isolated[y1:y2, x1:x2]
    

予測モードドキュメントのバウンディングボックスの結果の詳細はこちら。

セグメンテーションタスクでオブジェクトを分離するために Ultralytics YOLO11 を使用する利点は何ですか?

Ultralytics YOLO11 が提供するもの:

  • 高速リアルタイム物体検出とセグメンテーション。
  • 正確なバウンディングボックスとマスクの生成により、オブジェクトを正確に分離します。
  • 包括的なドキュメントと効率的な開発のための使いやすいAPI。

セグメントタスクのドキュメントで YOLO を使用する利点について解説します。

Ultralytics YOLO11を使用して、背景を含む分離されたオブジェクトを保存できますか?

はい、これはUltralytics YOLO11に組み込まれている機能です。以下のものを使用してください。 save_crop 中の引数 predict() メソッド。例:

results = model.predict(source="path/to/your/image.jpg", save_crop=True)

詳細についてはこちらをお読みください save_crop 中の引数 予測モードの推論引数 セクションをご参照ください。



📅 1年前に作成 ✏️ 2か月前に更新

コメント