ソフトウェアエンジニア必見!秘伝のタレ「Segment Anything Model (SAM)」で画像処理を革新する


ソフトウェアエンジニア必見!秘伝のタレ「Segment Anything Model (SAM)」で画像処理を革新する

facebookresearch/segment-anything

2025-07-24

「Segment Anything Model(SAM)」は、Facebook Researchが開発した、まさに画像から何でも切り抜けるという驚異のモデルなんだ。具体的に言うと、画像内の様々なオブジェクトを、その境界線に沿ってピクセル単位で正確にセグメンテーション(領域分割)できるんだ。しかも、すごいのが、これまで見たことのないようなオブジェクトでも、プロンプト(指示)を与えるだけでセグメンテーションできちゃうという汎用性の高さ!これがまさに「秘伝のタレ」たる所以だよ。

従来のセグメンテーションモデルは、特定のカテゴリのオブジェクト(例えば、人や車)に特化して学習されていることが多かったんだけど、SAMはそうじゃない。どんな画像に対しても、どんなオブジェクトに対しても、高い精度でセグメンテーションできるんだ。これは、大量の高品質なアノテーションデータ(SA-1Bデータセット)と、革新的な学習手法によって実現されているんだよ。

ソフトウェアエンジニアとして、SAMは俺たちの開発の幅を大きく広げてくれる、まさに強力なツールになるんだ。具体的にどんなところで役立つか、いくつか例を挙げてみよう!

機械学習プロジェクトにおいて、データのアノテーションは非常に手間と時間がかかる作業だよね。特にセグメンテーションのアノテーションは、ピクセル単位で正確に境界線を引く必要があるので、骨の折れる作業なんだ。SAMを使えば、このアノテーション作業を大幅に自動化・効率化できる!

例えば、数クリックでオブジェクトの領域を特定したり、バウンディングボックスや点、テキストプロンプトで指示するだけで、SAMが自動的に正確なセグメンテーションマスクを生成してくれる。これにより、アノテーションにかかるコストや時間を大幅に削減できるんだ。

画像編集ソフトウェアやWebサービスを開発しているなら、SAMはまさに魔法のような機能を追加できる可能性を秘めているよ。

背景の自動削除や変更
SAMで人物やオブジェクトを正確に切り抜き、背景を簡単に差し替えたりぼかしたりできる。

オブジェクトの選択と編集
画像内の特定のオブジェクトだけを選択して、色を変えたり、移動させたり、削除したりといった操作が簡単になる。

AR/VRアプリケーションの強化
リアルタイムで現実世界のオブジェクトを認識・セグメンテーションし、AR/VRコンテンツと自然に融合させることができる。

物体認識・追跡の精度向上
SAMで得られた正確なセグメンテーション情報と組み合わせることで、物体認識や追跡のロバスト性が向上する可能性がある。

ロボティクス・自動運転
ロボットが周囲の環境を認識し、特定の物体を操作したり、障害物を回避したりする際に、SAMのセグメンテーション能力が役立つ。

医療画像解析
医療画像から病変部位や臓器を正確にセグメンテーションすることで、診断支援や治療計画に貢献できる。

ユーザーが興味を持つ可能性のある画像コンテンツを分析する際に、SAMで画像内のオブジェクトを細かく把握できれば、よりパーソナライズされたコンテンツ推薦が可能になる。例えば、写真から特定のファッションアイテムを識別し、類似商品を推薦するといったことも考えられるね。

SAMはPythonで簡単に導入できるんだ。PyTorchを使用しているから、PyTorchの環境があればスムーズに進められるよ。

まずは、Facebook ResearchのGitHubリポジトリをクローンしてくるのが第一歩!

git clone https://github.com/facebookresearch/segment-anything.git
cd segment-anything

次に、必要なPythonライブラリをインストールするよ。requirements.txtファイルにまとまっているから、これを使うのが手っ取り早いね。

pip install -e .

-e . は、開発モードでインストールするオプションで、リポジトリのルートディレクトリにあるsetup.pyを使ってインストールしてくれる。

SAMを使うには、学習済みのモデルチェックポイントが必要になるんだ。いくつかのモデルサイズがあるから、用途に合わせて選ぶといいよ。ここでは、一般的なViT-H(巨大なモデル)を例にするけど、軽量版もあるから安心しな。

モデルチェックポイントは、リポジトリのREADMEにリンクが記載されていることが多いから、そこからダウンロードしよう。例えば、以下のコマンドでダウンロードできる場合があるよ。

wget https://dl.fbaipublicfiles.com/segment_anything/sam_vit_h_4b8939.pth

ダウンロードした.pthファイルは、例えばsegment-anythingディレクトリの直下など、分かりやすい場所に置いておこう。

ここからは、実際にSAMを使って画像からオブジェクトをセグメンテーションするサンプルコードを見ていこう。基本的な使い方から、プロンプトの指定方法まで解説するね。

import torch
import torchvision
import numpy as np
import matplotlib.pyplot as plt
import cv2

# SAM関連のモジュールをインポート
from segment_anything import sam_model_registry, SamPredictor

モデルをロードするよ。先ほどダウンロードしたモデルのパスを指定しよう。

# モデルのパスとタイプを指定
sam_checkpoint = "sam_vit_h_4b8939.pth" # ダウンロードしたモデルのパス
model_type = "vit_h" # モデルのタイプ(ダウンロードしたものと合わせる)

# SAMモデルをロード
sam = sam_model_registry[model_type](checkpoint=sam_checkpoint)

# GPUが利用可能ならGPUを使う
if torch.cuda.is_available():
    sam.to(device="cuda")
else:
    sam.to(device="cpu") # GPUがなければCPU

# SamPredictorを初期化
predictor = SamPredictor(sam)

print("SAMモデルのロードが完了しました!")

まずは、セグメンテーションしたい画像を読み込むよ。OpenCVを使うのが一般的だね。

# 画像の読み込み (例: 'images/dog.jpg'という画像があるとする)
image_path = "images/dog.jpg" # 適切な画像パスに修正してください
image = cv2.imread(image_path)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # OpenCVはBGRで読み込むのでRGBに変換

# Predictorに画像をセット
# これを一度実行すると、画像に関する必要な情報が内部的に計算される
predictor.set_image(image)

print(f"画像 '{image_path}' をセットしました。")

最も基本的な使い方の一つが、画像内の特定の点(座標)を指定してセグメンテーションする方法だよ。

# ポイントプロンプトの指定 (例: 犬の鼻のあたり)
input_point = np.array([[500, 375]]) # [X座標, Y座標]
input_label = np.array([1]) # 1は前景、0は背景

# セグメンテーションの実行
masks, scores, logits = predictor.predict(
    point_coords=input_point,
    point_labels=input_label,
    multimask_output=False, # Trueにすると複数のマスクを生成する
)

# 結果の表示
plt.figure(figsize=(10, 10))
plt.imshow(image)
show_mask(masks[0], plt.gca())
show_points(input_point, input_label, plt.gca())
plt.title("Segmented by Point Prompt")
plt.axis('off')
plt.show()

# マスク表示用のヘルパー関数 (必要であれば自分で実装するか、リポジトリのnotebooks/predictor_example.ipynbからコピー)
def show_mask(mask, ax, random_color=False):
    if random_color:
        color = np.concatenate([np.random.random(3), np.array([0.6])], axis=0)
    else:
        color = np.array([30/255, 144/255, 255/255, 0.6])
    h, w = mask.shape[-2:]
    mask_image = mask.reshape(h, w, 1) * color.reshape(1, 1, -1)
    ax.imshow(mask_image)

def show_points(coords, labels, ax, marker_size=375):
    pos_points = coords[labels==1]
    neg_points = coords[labels==0]
    ax.scatter(pos_points[:, 0], pos_points[:, 1], color='green', marker='*', s=marker_size, edgecolor='white', linewidth=1.25)
    ax.scatter(neg_points[:, 0], neg_points[:, 1], color='red', marker='*', s=marker_size, edgecolor='white', linewidth=1.25)

オブジェクトのだいたいの位置をバウンディングボックス(矩形)で指定する方法も強力だよ。

# バウンディングボックスプロンプトの指定 (例: 犬全体)
# [X_min, Y_min, X_max, Y_max]
input_box = np.array([400, 200, 700, 500]) # 画像によって調整

# セグメンテーションの実行
masks, scores, logits = predictor.predict(
    point_coords=None, # ポイントは指定しない
    point_labels=None,
    box=input_box,
    multimask_output=False,
)

# 結果の表示
plt.figure(figsize=(10, 10))
plt.imshow(image)
show_mask(masks[0], plt.gca())
show_box(input_box, plt.gca())
plt.title("Segmented by Bounding Box Prompt")
plt.axis('off')
plt.show()

# ボックス表示用のヘルパー関数
def show_box(box, ax):
    x0, y0 = box[0], box[1]
    w, h = box[2] - box[0], box[3] - box[1]
    ax.add_patch(plt.Rectangle((x0, y0), w, h, edgecolor='green', facecolor=(0,0,0,0), lw=2))

SAMのすごいところは、ポイントとバウンディングボックスを組み合わせて、より詳細なセグメンテーションができる点だ。例えば、犬全体をバウンディングボックスで囲んだ上で、切り抜きから除外したい部分(例
首輪の一部)をマイナスポイントで指定するといったことができる。

# 組み合わせ例: 犬全体をボックスで囲み、背景の邪魔な部分をポイントで排除
input_box = np.array([400, 200, 700, 500])
input_point = np.array([[500, 375], [600, 500]]) # プラスポイントとマイナスポイント
input_label = np.array([1, 0]) # 1は前景(含める)、0は背景(排除する)

masks, scores, logits = predictor.predict(
    point_coords=input_point,
    point_labels=input_label,
    box=input_box,
    multimask_output=False,
)

plt.figure(figsize=(10, 10))
plt.imshow(image)
show_mask(masks[0], plt.gca())
show_box(input_box, plt.gca())
show_points(input_point, input_label, plt.gca())
plt.title("Segmented by Combined Prompts")
plt.axis('off')
plt.show()

プロンプトの質
SAMの性能は、与えるプロンプトの質に大きく左右されるよ。適切なポイントやバウンディングボックスを与えることが、良いセグメンテーション結果を得る秘訣だ。

計算リソース
SAMは比較的大きなモデルなので、特にGPU環境がある方が推論速度が速いよ。CPUでも動作するけど、画像サイズや枚数が多いと時間がかかる場合がある。

multimask_output
predictor.predictのmultimask_output引数をTrueに設定すると、一つのプロンプトに対して複数のセグメンテーションマスクを生成してくれることがある。これは、曖昧なオブジェクトに対して、複数の解釈を提示してくれるので便利だよ。スコアを見て最適なマスクを選択しよう。

応用例の探索
上記の例は基本的な使い方に過ぎない。SAMをどのように既存のシステムや新しいアイデアに組み込むか、ぜひ色々と試してみてほしい!例えば、Webアプリケーションでユーザーがクリックした位置から画像を切り抜く機能や、動画から特定のオブジェクトを追跡してマスクを生成するといったことも考えられる。


facebookresearch/segment-anything