Link to this sectionUltralytics YOLOを使用してセグメンテーションオブジェクトを分離する方法#
インスタンスセグメンテーションは、検出されたすべてのオブジェクトに対してピクセル単位で正確なマスクを生成します。つまり、各オブジェクトを画像から個別に切り出すことができます。予測モードとOpenCVを使用して、Ultralytics YOLOのセグメンテーション結果からオブジェクトを分離する方法を解説します。背景を真っ黒にする方法や、PNG保存用に透明にする方法も紹介します。
Watch: How to Remove Background and Isolate Objects with Ultralytics YOLO Segmentation & OpenCV in Python 🚀
Link to this sectionセグメンテーションオブジェクトを分離する理由は?#
画像から個々のオブジェクトを抽出することで、以下のような様々な後続のワークフローが可能になります。
- 背景除去: 商品撮影、カタログ作成、クリエイティブな編集用。
- オブジェクトごとのクロップ: 検出結果から分類用データセットを作成するため。
- フォーカス処理: OCR、色分析、測定などの後続ステップで、周囲のシーンではなくオブジェクトのみを処理するため。
- 透明PNGエクスポート: オブジェクトを新しい背景に合成するため。
この手法は、すべてのUltralytics YOLOセグメンテーションモデルで使用でき、4つのステージで構成されます:推論の実行 → 各輪郭の抽出 → オブジェクトの分離 → 結果の保存。
Link to this sectionセグメンテーション推論の実行#
必要なライブラリをインストールした後、セグメンテーションモデル(マスク生成に必要な-segサフィックス付きのモデル)を読み込み、ソース画像に対して予測を実行します。
from ultralytics import YOLO
# Load a segmentation model
model = YOLO("yolo26n-seg.pt")
# Run inference on a source
results = model.predict(source="path/to/image.jpg")If you call model.predict() without a source, Ultralytics falls back to the example images shipped with the package (bus.jpg and zidane.jpg), which is handy for quickly testing the workflow.
Link to this sectionオブジェクトの輪郭の抽出#
resultsの各アイテムは1つの画像に対応しており、結果を反復処理することで一度に1つの検出を取得できます。各検出に対して元の画像をコピーし、クラスラベルを読み取り、オブジェクトのマスクの輪郭を空白のバイナリマスクに描画します。このマスクの白い領域は、どのピクセルがそのオブジェクトに属しているかを正確に示しています。
このセクションおよび次のセクションのコードスニペットは、以下の検出ループの内部で実行されます。コピー&ペースト可能な完全なスクリプトは完全な例にあります。
{ width="240", align="right" }
from pathlib import Path
import cv2
import numpy as np
for r in results:
img = np.copy(r.orig_img)
img_name = Path(r.path).stem # source image base-name
# Iterate each detected object in the image
for ci, c in enumerate(r):
label = c.names[c.boxes.cls.tolist().pop()] # class name
# Build a binary mask and draw the object contour onto it
b_mask = np.zeros(img.shape[:2], np.uint8)
contour = c.masks.xy[0].astype(np.int32).reshape(-1, 1, 2)
cv2.drawContours(b_mask, [contour], -1, (255, 255, 255), cv2.FILLED)c.masks.xy[0]は、この単一検出結果におけるオブジェクトのマスク輪郭を(x, y)座標として返します。.astype(np.int32)converts the points fromfloat32, which OpenCV'sdrawContours()does not accept..reshape(-1, 1, 2)reshapes the points into the[N, 1, 2]layoutdrawContours()expects, whereNis the number of contour points.
Passing [contour] with the index -1 draws all points of the supplied contour, and cv2.FILLED fills every enclosed pixel white.
Link to this sectionオブジェクトの分離#
バイナリマスクの準備ができたら、それを元の画像と組み合わせます。背景をどのようにしたいかによって、2つの一般的なスタイルがあります。
マスクを3チャンネルに変換し、オブジェクトと重なるピクセルのみを保持します。輪郭の外側はすべて黒になります。
# Isolate object with a black background
mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
isolated = cv2.bitwise_and(mask3ch, img)フルサイズの画像ではなくオブジェクトの領域のみを保持したい場合は、検出のバウンディングボックスに対してスライスを行います。
# Bounding box coordinates
x1, y1, x2, y2 = c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32)
# Crop the isolated image to the object region
iso_crop = isolated[y1:y2, x1:x2]That is built in. Pass save_crop=True to predict() and Ultralytics saves bounding-box crops automatically, no masking required.
Link to this section結果の保存 (オプション)#
分離した各オブジェクトをどう扱うかはユーザー次第です。一般的な次のステップは、後で使用するためにディスクに書き出すことです。
# Save the isolated object to file
cv2.imwrite(f"{img_name}_{label}-{ci}.png", isolated)ここでimg_nameはソース画像のステム、labelはクラス名、ciは検出インデックスであり、同じクラスの複数のインスタンスがユニークなファイル名を持つようになります。オプションのクロップを適用した場合は、isolatedをiso_cropに置き換えてください。
Link to this section完全な例#
以下のスクリプトは、すべてのステップを1つの実行可能なブロックにまとめたものです。デフォルトでは黒背景を使用しますが、透明なPNGが必要な場合は、マークされた行をnp.dstack([img, b_mask])に変更してください。
from pathlib import Path
import cv2
import numpy as np
from ultralytics import YOLO
model = YOLO("yolo26n-seg.pt")
results = model.predict(source="path/to/image.jpg")
for r in results:
img = np.copy(r.orig_img)
img_name = Path(r.path).stem
for ci, c in enumerate(r):
label = c.names[c.boxes.cls.tolist().pop()]
# Build a binary mask from the object contour
b_mask = np.zeros(img.shape[:2], np.uint8)
contour = c.masks.xy[0].astype(np.int32).reshape(-1, 1, 2)
cv2.drawContours(b_mask, [contour], -1, (255, 255, 255), cv2.FILLED)
# Isolate the object (black background)
mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
isolated = cv2.bitwise_and(mask3ch, img) # transparent PNG: isolated = np.dstack([img, b_mask])
# Save or add your custom post-processing here
cv2.imwrite(f"{img_name}_{label}-{ci}.png", isolated)
# Optional: crop to the bounding box before saving
# x1, y1, x2, y2 = c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32)
# cv2.imwrite(f"{img_name}_{label}-{ci}.png", isolated[y1:y2, x1:x2])繰り返し使用する場合は、ループ本体を関数として定義することで、多くの画像にわたって呼び出すことができます。
Link to this section結論#
これで、Ultralytics YOLOを使用してセグメンテーションオブジェクトを分離する完全なレシピが手に入りました。推論を実行し、各輪郭からバイナリマスクを構築し、黒または透明な背景でオブジェクトを抽出し、必要に応じてバウンディングボックスにクロップします。完全なセグメンテーションタスクおよび予測モードのドキュメントを参照して、独自のクラスに合わせてワークフローを適応させてください。
Link to this sectionよくある質問 (FAQ)#
Link to this sectionUltralytics YOLOを使用してセグメンテーションタスクのオブジェクトを分離するにはどうすればよいですか?#
セグメンテーションモデルを読み込み、推論を実行し、各検出の輪郭からバイナリマスクを構築して、それを元の画像と組み合わせます。
import cv2
import numpy as np
from ultralytics import YOLO
model = YOLO("yolo26n-seg.pt")
results = model.predict(source="path/to/your/image.jpg")
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)
mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
isolated = cv2.bitwise_and(mask3ch, img)検出ごとの完全なループについては完全な例を参照してください。
Link to this sectionセグメンテーション後に分離したオブジェクトを保存するためのオプションにはどのようなものがありますか?#
主に2つのスタイルがあります。黒背景の場合は、マスクを3チャンネルに変換してcv2.bitwise_and()を使用します。透明背景(PNG保存時)の場合は、np.dstack([img, b_mask])を使用してマスクを4つ目のアルファチャンネルとしてスタックします。両方ともオブジェクトの分離セクションで示されています。
Link to this section分離したオブジェクトをバウンディングボックスにクロップするにはどうすればよいですか?#
検出結果からバウンディングボックスの座標を読み取り、分離した画像に対してスライスを行います。
x1, y1, x2, y2 = results[0].boxes.xyxy[0].cpu().numpy().astype(np.int32)
iso_crop = isolated[y1:y2, x1:x2]バウンディングボックスの結果に関する詳細は、予測モードのドキュメントを参照してください。
Link to this sectionセグメンテーションタスクでのオブジェクト分離にUltralytics YOLOを使用するべき理由は?#
Ultralytics YOLOは、正確なマスクとバウンディングボックスの生成を伴う高速なリアルタイムインスタンスセグメンテーションを提供し、推論結果を数行のOpenCVコードで分離オブジェクトに変換できるシンプルなPython APIを備えています。
Link to this sectionUltralytics YOLOを使用して、背景を含めた分離オブジェクトを保存できますか?#
Yes. Use the save_crop argument in predict() to save bounding-box crops with their original background:
results = model.predict(source="path/to/your/image.jpg", save_crop=True)詳細は予測モードの推論引数セクションを参照してください。