製造業における外観検査では、AIの導入に対する期待が大きい一方で、現実とのギャップに苦しむケースも少なくありません。
例えば、最新の物体検出モデルを使用しても、高解像度の検査画像において、目視では明らかな微細なスクラッチやピンホールをAIが見逃してしまうことがあります。これはAIモデルの能力不足というより、入力データの処理プロセスにおける構造的な問題が原因と考えられます。
この記事では、この「微細欠陥が見えない」という課題を解決するためのアプローチであるSAHI(Slicing Aided Hyper Inference)について、Pythonでの実装コードを交えて解説します。まずは動くものを作り、仮説を即座に形にして検証するアプローチで進めましょう。SAHIは万能ではありません。精度を得る代わりに失うもの(処理時間)についても検証し、ビジネスへの最短距離を描くことが重要です。
外観検査におけるYOLOv8の可能性と「微細検知」の課題
YOLO(You Only Look Once)シリーズは、推論速度と精度のバランスに優れています。しかし、産業用カメラの高解像度画像(4Kなど)にそのまま適用すると課題が生じます。
汎用物体検出モデルを産業用途に適用する際の課題
YOLOなどのディープラーニングモデルは、学習時および推論時に、入力画像を特定サイズ(640x640ピクセルなど)にリサイズして処理します。これは計算コストを抑え、リアルタイム性を確保するために必要な処理です。
画像のリサイズ処理が招く「欠陥情報の消失」リスク
4096x3000ピクセルの検査画像を640x640ピクセルに縮小する場合を考えてみましょう。
画像は約1/30の面積に圧縮されます。このとき、画面全体に大きく映る部品そのものは認識できますが、数ピクセル〜数十ピクセル程度の微細な傷は、リサイズ処理によって情報が消失する可能性があります。AIが見落としているのではなく、AIの目には最初から映っていない状態になることがあるのです。
検証のゴール:標準推論 vs スライシング推論(SAHI)
この問題を解決するのがSAHI(Slicing Aided Hyper Inference)です。SAHIは、大きな画像を小さな領域(スライス)に分割し、それぞれに対して推論を行った後、結果を統合するライブラリです。
今回は、以下の2つのパターンを実装し、その挙動を比較します。理論だけでなく「実際にどう動くか」を重視し、スピーディーに検証を進めましょう。
- 標準推論: 画像全体を一括リサイズして推論(高速だが微細検知に弱い)
- SAHI推論: 画像を分割して高解像度のまま推論(低速だが微細検知に強い)
検証環境のセットアップとデータ準備
検証に必要な環境を構築します。Python環境が手元にあることを前提に進めます。
Ultralytics YOLOv8とSAHIライブラリのインストール
必要なライブラリは主に3つです。ultralyticsはYOLOv8の公式ライブラリ、sahiはスライシング推論用、opencv-pythonは画像処理用です。
pip install ultralytics sahi opencv-python
※ GPUを使用する場合は、PyTorchがCUDA対応版になっていることを確認してください。外観検査のような高負荷なタスクではGPUが推奨されます。
データセット構造と検証用画像
検証用として、微細な欠陥を含む高解像度画像(例: 3000x3000px以上の基板画像など)を用意してください。モデル自体は、手軽に検証するために学習済みのyolov8n.pt(COCOデータセットで学習済み)を使用しますが、本来は自社の欠陥データでFine-tuningしたモデル(best.pt)を使用することが望ましいです。
ディレクトリ構成は以下のようにシンプルにしておくと管理しやすいでしょう。
project_root/
├── images/
│ └── test_sample.jpg # 高解像度の検査画像
├── output/
│ ├── standard/ # 標準推論の結果保存先
│ └── sahi/ # SAHI推論の結果保存先
└── main.py # 実行スクリプト
実装パターン1:YOLOv8標準推論による検出限界の確認
まずは、Ultralytics YOLOシリーズ(YOLOv8や最新のYOLO11など)の標準機能を使って推論を行い、微細な欠陥検出における課題を確認します。ここでは、高解像度画像に対する標準的な推論アプローチで発生しがちな「見逃し」のメカニズムを実証します。
ベースラインとなる推論コードの実装
YOLOv8およびその後継であるYOLO11は、APIの互換性が保たれており、以下のコードはどちらのモデルでも動作します。ここでは標準的な実装例を示します。
from ultralytics import YOLO
import cv2
import os
# 出力ディレクトリの作成
os.makedirs("output/standard", exist_ok=True)
# モデルの読み込み(ここでは軽量なNanoモデルを使用)
# ※実務では自社データで学習させた 'path/to/best.pt' を指定します
# ※YOLO11(yolo11n.pt)などの最新モデルもAPI互換性があるため、コード変更なしで利用可能です
model = YOLO('yolov8n.pt')
# 画像パス
image_path = "images/test_sample.jpg"
# パターン1: 標準推論
# imgsz=640 はデフォルトですが、明示的に指定してリサイズの影響を意識します
# 最新モデルではパラメータ効率が向上していますが、入力サイズの影響は物理的な制約として残ります
results = model.predict(source=image_path, save=True, imgsz=640, project="output/standard", name="result")
print("標準推論完了")
標準実装における検出漏れ(False Negative)の分析
上記のコードを実行し、出力された画像を確認してください。画像全体に大きく写っている物体は検出できているかもしれませんが、「高解像度画像の広大な領域の中に存在する、極めて微細な欠陥」は検出されないケースが報告されています。
これは、モデルの性能不足というよりも、入力プロセスにおける物理的な情報の損失が主な原因です。imgsz=640を指定すると、例えば4000x3000ピクセルのような高解像度画像であっても、推論時には長辺が640ピクセルになるよう強制的に縮小(ダウンサンプリング)されます。
この過程で、数ピクセル程度の微細な傷や打痕は、縮小後の画像では1ピクセル未満の情報となり、特徴量として消失してしまいます。YOLO11などの最新モデルで推論アルゴリズムやパラメータ効率が改善され、検出精度が向上していたとしても、入力データから情報が消えてしまえば検出は不可能です。
imgszを上げる(例: imgsz=1280やそれ以上)ことで改善は見込めますが、GPUメモリの消費量が跳ね上がるほか、学習時の画像サイズとかけ離れることでかえって精度が低下するリスクもあります。これが、標準的な推論アプローチにおける「微細検知の壁」です。
実装パターン2:SAHIを用いたスライシング推論の実装
次に、SAHIを使って同じ画像を処理します。画像を「スライス(切り出し)」して推論することで、元の解像度を維持したまま欠陥を探し出します。
SAHIのAutoDetectionModel設定と推論パイプライン
以下のコードは、SAHIを使ってYOLOv8モデルをラップし、スライシング推論を行う例です。
from sahi import AutoDetectionModel
from sahi.predict import get_sliced_prediction
from sahi.utils.cv import visualize_object_predictions
import cv2
import os
# 出力ディレクトリ
os.makedirs("output/sahi", exist_ok=True)
# 画像パス
image_path = "images/test_sample.jpg"
# 1. SAHI用のモデルラッパー設定
# model_pathには学習済みモデル(.pt)を指定
detection_model = AutoDetectionModel.from_pretrained(
model_type='yolov8',
model_path='yolov8n.pt',
confidence_threshold=0.3, # 確信度の閾値
device='cuda:0' # GPUを使用(CPUの場合は 'cpu')
)
# 2. スライシング推論の実行
# ここがSAHIの核となる部分です
result = get_sliced_prediction(
image_path,
detection_model,
slice_height=512, # 切り出す画像の高さ
slice_width=512, # 切り出す画像の幅
overlap_height_ratio=0.2, # スライス間のオーバーラップ率(縦)
overlap_width_ratio=0.2 # スライス間のオーバーラップ率(横)
)
# 3. 結果の可視化と保存
# SAHI独自の結果オブジェクトから画像を生成します
visualization_result = visualize_object_predictions(
image=cv2.imread(image_path),
object_prediction_list=result.object_prediction_list,
output_dir="output/sahi",
file_name="sahi_result"
)
print("SAHI推論完了")
print(f"検出数: {len(result.object_prediction_list)}")
スライスサイズとオーバーラップ率の最適化
コード内のパラメータについて補足します。
slice_height,slice_width: スライス画像のサイズです。ここをモデルの学習サイズ(例: 640x640)に近づけるのが一般的です。小さすぎると文脈(Context)が失われ、大きすぎるとリサイズの影響が出ます。overlap_height_ratio,overlap_width_ratio: スライス同士の重なり具合です。0.2(20%)程度に設定することで、スライスの境界線上にある欠陥が見切れてしまうのを防ぎます。
このコードを実行すると、標準推論では見つからなかった小さな対象物が検出される可能性があります。SAHIは、大きな画像をあたかも「複数の小さな画像」として扱い、それぞれに対してYOLOを適用します。
精度 vs 速度:実運用に向けた定量的評価
微細な傷が見つかったとしても、それだけで判断してはいけません。経営者視点とエンジニア視点の双方から、最も重要なコスト(時間)の評価に移ります。
パターン1と2の推論時間比較ベンチマーク
SAHIは内部的に、スライスの数だけ推論を実行します。例えば、4K画像を512x512でスライスすると、オーバーラップを含めて数十回の推論が実行されることになります。
簡易的なベンチマークコードで比較してみましょう。
import time
# --- 標準推論の時間計測 ---
start_time = time.time()
model.predict(source=image_path, imgsz=640, verbose=False)
standard_duration = time.time() - start_time
# --- SAHI推論の時間計測 ---
start_time = time.time()
get_sliced_prediction(
image_path,
detection_model,
slice_height=512,
slice_width=512,
overlap_height_ratio=0.2,
overlap_width_ratio=0.2,
verbose=0
)
sahi_duration = time.time() - start_time
print(f"標準推論時間: {standard_duration:.4f}秒")
print(f"SAHI推論時間: {sahi_duration:.4f}秒")
print(f"倍率: {sahi_duration / standard_duration:.1f}倍")
SAHIの方が時間がかかる可能性があります。
検出精度(mAP)の変化と過検出(False Positive)リスク
- メリット: リコール(再現率)が向上し、見逃しが減る可能性があります。
- デメリット: 処理時間が増加する可能性があります。また、背景のノイズを誤って欠陥として検出する「過検出(False Positive)」のリスクも高まる可能性があります。
製造ラインのタクトタイムが短い場合、SAHIの導入は難しいかもしれません。一方で、タクトタイムに余裕がある精密検査工程であれば、SAHIによる品質向上は有効な手段となりえます。
専門用語解説:mAPとIoU
- IoU (Intersection over Union): AIが予測した枠と、正解の枠がどれくらい重なっているかの指標。微細欠陥の場合、少しのズレでIoUが大きく下がるため、評価時は注意が必要です。
- mAP (mean Average Precision): 検出精度の平均値。SAHIを導入すると、特に「Small Object(小物体)」カテゴリのmAPが改善する可能性があります。
結論:YOLOv8を外観検査に採用すべきケース・すべきでないケース
YOLOv8とSAHIの組み合わせは、微細欠陥検出において有効な手段となりえますが、万能ではありません。最後に、導入判断のための指針を整理します。
導入判断のためのチェックリスト
以下の条件に当てはまる場合、SAHI × YOLOv8の導入を検討すべきです。
- 欠陥サイズが画像全体の1%未満である(数ピクセルレベル)。
- タクトタイムに余裕がある、またはGPUリソースを潤沢に用意できる。
- 見逃し(False Negative)が許されない重要部品の検査である。
高速なコンベアを流れる製品をリアルタイムで全数検査するようなケースでは、標準のYOLOv8で検出できるようカメラの撮像範囲(FOV)を狭めて解像度を稼ぐか、AI以外の画像処理(ルールベース)を組み合わせるアプローチが必要になることがあります。
次のステップ:カスタムデータセットでの学習へ
今回の検証でSAHIの有効性が確認できたら、自社の不良品画像を集め、アノテーションを行い、カスタムモデルを学習させることを検討してください。微細な傷のアノテーションは大変な作業ですが、ここでの品質が最終的な精度に影響します。
技術は常にトレードオフの中にあります。現場にとって最適なバランスを見極め、ビジネスへの最短距離を描くために、まずはこのコードでプロトタイプ(PoC)を動かし、仮説を即座に形にして検証してみてください。
コメント