mcpField
C
computer-vision-pipeline

computer-vision-pipeline

github.com/curiositech開発257271 回インストール2 日前に更新
リポジトリ

computer-vision-pipeline について

computer-vision-pipelineは、物体検出、動画解析、マルチオブジェクト追跡のシステム構築を支援するスキルです。フレームの前処理や抽出、バッチ推論、モデルのファインチューニング、追跡手法を扱います。

主な機能

  1. 01物体検出モデルの選定ガイド
  2. 02動画フレームの前処理とサンプリング
  3. 03バッチ推論とNMS調整の説明
  4. 04ByteTrackなどによるマルチオブジェクト追跡
  5. 05YOLOの調整と動画解析スクリプト

活用シーン

  1. 01ドローン映像や野生動物の動画解析
  2. 02リアルタイム物体検出パイプラインの構築
  3. 03動画フレーム間の複数物体の追跡
  4. 04カスタムデータセットでYOLOを調整

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/curiositech/some_claude_skills --skill computer-vision-pipeline

インストール後、Claude Code で/computer-vision-pipelineを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

.claude-plugin/
plugin.json
references/
yolo-guide.md
video-processing.md
tracking-algorithms.md
scripts/
model_trainer.py
video_analyzer.py

詳細

コンピュータービジョンパイプライン

物体検出、追跡、動画解析のための、本番環境ですぐに使えるコンピュータービジョンシステムの構築に精通しています。

使用する場面

✅ 以下の場合に使用:

  • ドローン映像の解析(考古学調査、自然保護)
  • 野生動物のモニタリングと追跡
  • リアルタイム物体検出システム
  • 動画の前処理と解析
  • カスタムモデルのトレーニングと推論
  • マルチオブジェクトトラッキング(MOT)

❌ 以下の場合には使用しない:

  • シンプルな画像フィルター(Pillow/PIL を使用)
  • 写真編集(Photoshop/GIMP を使用)
  • 顔認識 API(AWS Rekognition を使用)
  • 基本的な OCR(Tesseract を使用)

テクノロジーの選定

物体検出モデル
モデル速度(FPS)精度(mAP)用途
YOLOv814053.9%リアルタイム検出
Detectron22558.7%高精度、研究
EfficientDet3555.1%モバイルへのデプロイ
Faster R-CNN1042.0%レガシーシステム

タイムライン:

  • 2015:Faster R-CNN(2段階検出)
  • 2016:YOLO v1(1段階、リアルタイム)
  • 2020:YOLOv5(PyTorch、本番環境対応)
  • 2023:YOLOv8(最先端)
  • 2024:YOLOv8 はリアルタイム検出の業界標準

判断ツリー:

Need real-time (>30 FPS)? → YOLOv8
Need highest accuracy? → Detectron2 Mask R-CNN
Need mobile deployment? → YOLOv8-nano or EfficientDet
Need instance segmentation? → Detectron2 or YOLOv8-seg
Need custom objects? → Fine-tune YOLOv8

よくあるアンチパターン

アンチパターン 1:検出前にフレームを前処理しない

初心者の考え方:「未加工の動画フレームにそのまま検出を実行すればよい」

問題:検出精度が低く、GPU サイクルが無駄になります。

誤った方法:

# ❌ No preprocessing - poor results
import cv2
from ultralytics import YOLO

model = YOLO('yolov8n.pt')
video = cv2.VideoCapture('drone_footage.mp4')

while True:
    ret, frame = video.read()
    if not ret:
        break

    # Raw frame detection - no normalization, no resizing
    results = model(frame)
    # Poor accuracy, slow inference

誤りである理由:

  • 動画の解像度が高すぎます(4K は1フレームあたり8.3メガピクセル)
  • 正規化されていません(ピクセル値が0~1ではなく0~255)
  • アスペクト比が維持されていません
  • 高解像度フレームで GPU メモリがオーバーフローします

正しい方法:

# ✅ Proper preprocessing pipeline
import cv2
import numpy as np
from ultralytics import YOLO

model = YOLO('yolov8n.pt')
video = cv2.VideoCapture('drone_footage.mp4')

# Model expects 640x640 input
TARGET_SIZE = 640

def preprocess_frame(frame):
    # Resize while maintaining aspect ratio
    h, w = frame.shape[:2]
    scale = TARGET_SIZE / max(h, w)
    new_w, new_h = int(w * scale), int(h * scale)

    resized = cv2.resize(frame, (new_w, new_h), interpolation=cv2.INTER_LINEAR)

    # Pad to square
    pad_w = (TARGET_SIZE - new_w) // 2
    pad_h = (TARGET_SIZE - new_h) // 2

    padded = cv2.copyMakeBorder(
        resized,
        pad_h, TARGET_SIZE - new_h - pad_h,
        pad_w, TARGET_SIZE - new_w - pad_w,
        cv2.BORDER_CONSTANT,
        value=(114, 114, 114)  # Gray padding
    )

    # Normalize to 0-1 (if model expects it)
    # normalized = padded.astype(np.float32) / 255.0

    return padded, scale

while True:
    ret, frame = video.read()
    if not ret:
        break

    preprocessed, scale = preprocess_frame(frame)
    results = model(preprocessed)

    # Scale bounding boxes back to original coordinates
    for box in results[0].boxes:
        x1, y1, x2, y2 = box.xyxy[0]
        x1, y1, x2, y2 = x1/scale, y1/scale, x2/scale, y2/scale

パフォーマンスの比較:

  • 未加工の4Kフレーム:5 FPS、72% mAP
  • 前処理済み640x640:45 FPS、89% mAP

タイムラインの背景:

  • 2015:手動での前処理が必要
  • 2020:YOLOv5 に自動リサイズが追加
  • 2023:YOLOv8 はスマートな前処理に対応していますが、明示的に制御するほうが効果的です

アンチパターン 2:動画のすべてのフレームを処理する

初心者の考え方:「1フレーム残らず検出を実行すればよい」

問題:フレームの99%は重複しており、計算リソースが無駄になります。

誤った方法:

# ❌ Process every frame (30 FPS video = 1800 frames/min)
import cv2
from ultralytics import YOLO

model = YOLO('yolov8n.pt')
video = cv2.VideoCapture('drone_footage.mp4')

detections = []

while True:
    ret, frame = video.read()
    if not ret:
        break

    # Run detection on EVERY frame
    results = model(frame)
    detections.append(results)

# 10-minute video = 18,000 inferences (15 minutes on GPU)

誤りである理由:

  • 隣接するフレームはほぼ同一です
  • 重複した処理に計算リソースの95%を浪費します
  • 処理時間が長くなります
  • 結果の保存に膨大なストレージが必要です

正しい方法 1:フレームのサンプリング

# ✅ Sample every Nth frame
import cv2
from ultralytics import YOLO

model = YOLO('yolov8n.pt')
video = cv2.VideoCapture('drone_footage.mp4')

SAMPLE_RATE = 30  # Process 1 frame per second (if 30 FPS video)

frame_count = 0
detections = []

while True:
    ret, frame = video.read()
    if not ret:
        break

    frame_count += 1

    # Only process every 30th frame
    if frame_count % SAMPLE_RATE == 0:
        results = model(frame)
        detections.append({
            'frame': frame_count,
            'timestamp': frame_count / 30.0,
            'results': results
        })

# 10-minute video = 600 inferences (30 seconds on GPU)

正しい方法 2:シーン変化検出を使った適応型サンプリング

# ✅ Only process when scene changes significantly
import cv2
import numpy as np
from ultralytics import YOLO

model = YOLO('yolov8n.pt')
video = cv2.VideoCapture('drone_footage.mp4')

def scene_changed(prev_frame, curr_frame, threshold=0.3):
    """Detect scene change using histogram comparison"""
    if prev_frame is None:
        return True

    # Convert to grayscale
    prev_gray = cv2.cvtColor(prev_frame, cv2.COLOR_BGR2GRAY)
    curr_gray = cv2.cvtColor(curr_frame, cv2.COLOR_BGR2GRAY)

    # Calculate histograms
    prev_hist = cv2.calcHist([prev_gray], [0], None, [256], [0, 256])
    curr_hist = cv2.calcHist([curr_gray], [0], None, [256], [0, 256])

    # Compare histograms
    correlation = cv2.compareHist(prev_hist, curr_hist, cv2.HISTCMP_CORREL)

    return correlation < (1 - threshold)

prev_frame = None
detections = []

while True:
    ret, frame = video.read()
    if not ret:
        break

    # Only run detection if scene changed
    if scene_changed(prev_frame, frame):
        results = model(frame)
        detections.append(results)

    prev_frame = frame.copy()

# Adapts to video content - static shots skip frames, action scenes process more

削減効果:

  • すべてのフレーム:18,000回の推論
  • 1 FPSでサンプリング:600回の推論(97%削減)
  • 適応型:約1,200回の推論(93%削減)

アンチパターン 3:バッチ推論を使用しない

初心者の考え方:「画像を1枚ずつ処理すればよい」

問題:データを待つ間、GPU は時間の80%をアイドル状態で過ごします。

誤った方法:

# ❌ Sequential processing - GPU underutilized
import cv2
from ultralytics import YOLO
import time

model = YOLO('yolov8n.pt')

# 100 images to process
image_paths = [f'frame_{i:04d}.jpg' for i in range(100)]

start = time.time()

for path in image_paths:
    frame = cv2.imread(path)
    results = model(frame)  # Process one at a time
    # GPU utilization: ~20%

elapsed = time.time() - start
print(f"Processed {len(image_paths)} images in {elapsed:.2f}s")
# Output: 45 seconds

誤りである理由:

  • GPU は画像を1枚ずつ読み込む CPU を待たなければなりません
  • 並列化されていません
  • GPU 使用率が約20%です
  • スループットが低下します

正しい方法:

# ✅ Batch inference - GPU fully utilized
import cv2
from ultralytics import YOLO
import time

model = YOLO('yolov8n.pt')

image_paths = [f'frame_{i:04d}.jpg' for i in range(100)]

BATCH_SIZE = 16  # Process 16 images at once

start = time.time()

for i in range(0, len(image_paths), BATCH_SIZE):
    batch_paths = image_paths[i:i+BATCH_SIZE]

    # Load batch
    frames = [cv2.imread(path) for path in batch_paths]

    # Batch inference (single GPU call)
    results = model(frames)  # Pass list of images
    # GPU utilization: ~85%

elapsed = time.time() - start
print(f"Processed {len(image_paths)} images in {elapsed:.2f}s")
# Output: 8 seconds (5.6x faster!)

パフォーマンスの比較:

方法所要時間(画像100枚)GPU 使用率スループット
順次処理45秒20%2.2 img/s
バッチ(16)8秒85%12.5 img/s
バッチ(32)6秒92%16.7 img/s

バッチサイズの調整:

# Find optimal batch size for your GPU
import torch

def find_optimal_batch_size(model, image_size=(640, 640)):
    for batch_size in [1, 2, 4, 8, 16, 32, 64]:
        try:
            dummy_input = torch.randn(batch_size, 3, *image_size).cuda()

            start = time.time()
            with torch.no_grad():
                _ = model(dummy_input)
            elapsed = time.time() - start

            throughput = batch_size / elapsed
            print(f"Batch {batch_size}: {throughput:.1f} img/s")
        except RuntimeError as e:
            print(f"Batch {batch_size}: OOM (out of memory)")
            break

# Find optimal batch size before production
find_optimal_batch_size(model)

アンチパターン 4:非極大値抑制(NMS)の調整を無視する

問題:重複検出、物体の見落とし、後処理の遅延が発生します。

誤った方法:

# ❌ Use default NMS settings for everything
from ultralytics import YOLO

model = YOLO('yolov8n.pt')

# Default settings (iou_threshold=0.45, conf_threshold=0.25)
results = model('crowded_scene.jpg')

# Result: 50 bounding boxes, 30 are duplicates!

誤りである理由:

  • デフォルトの IoU=0.45 は、物体が密集している場合には許容範囲が広すぎます
  • デフォルトの conf=0.25 では、品質の低い検出も含まれます
  • 用途に応じた調整がありません

正しい方法:

# ✅ Tune NMS for your use case
from ultralytics import YOLO

model = YOLO('yolov8n.pt')

# Sparse objects (dolphins in ocean)
sparse_results = model(
    'ocean_footage.jpg',
    iou=0.5,    # Higher IoU = allow closer boxes
    conf=0.4    # Higher confidence = fewer false positives
)

# Dense objects (crowd, flock of birds)
dense_results = model(
    'crowded_scene.jpg',
    iou=0.3,    # Lower IoU = suppress more duplicates
    conf=0.5    # Higher confidence = filter noise
)

# High precision needed (legal evidence)
precise_results = model(
    'evidence.jpg',
    iou=0.5,
    conf=0.7,   # Very high confidence
    max_det=50  # Limit max detections
)

NMS パラメーターガイド:

用途IoUConf最大検出数
物体がまばらな場合(野生動物)0.50.4100
物体が密集している場合(群衆)0.30.5300
高精度が必要な場合(証拠)0.50.750
リアルタイム(速度優先)0.450.3100

反パターン 5:フレーム間の追跡がない

初学者の考え:「各フレームで個別に検出を実行します」

問題点:個々の物体を数えたり、動きを追跡したり、軌跡を作成したりできません。

誤った方法:

# ❌ Independent frame detection - no object identity
from ultralytics import YOLO
import cv2

model = YOLO('yolov8n.pt')
video = cv2.VideoCapture('dolphins.mp4')

detections = []

while True:
    ret, frame = video.read()
    if not ret:
        break

    results = model(frame)
    detections.append(results)

# Result: Can't tell if frame 10 dolphin is same as frame 20 dolphin
# Can't count unique dolphins
# Can't track trajectories

誤りである理由:

  • フレーム間で物体の同一性を保持できません
  • 個々の物体を数えられません
  • 動きのパターンを分析できません
  • 軌跡を作成できません

正しい方法:追跡(ByteTrack)を使用します

# ✅ Multi-object tracking with ByteTrack
from ultralytics import YOLO
import cv2

# YOLO with tracking
model = YOLO('yolov8n.pt')
video = cv2.VideoCapture('dolphins.mp4')

# Track objects across frames
tracks = {}

while True:
    ret, frame = video.read()
    if not ret:
        break

    # Run detection + tracking
    results = model.track(
        frame,
        persist=True,     # Maintain IDs across frames
        tracker='bytetrack.yaml'  # ByteTrack algorithm
    )

    # Each detection now has persistent ID
    for box in results[0].boxes:
        track_id = int(box.id[0])  # Unique ID across frames
        x1, y1, x2, y2 = box.xyxy[0]

        # Store trajectory
        if track_id not in tracks:
            tracks[track_id] = []

        tracks[track_id].append({
            'frame': len(tracks[track_id]),
            'bbox': (x1, y1, x2, y2),
            'conf': box.conf[0]
        })

# Now we can analyze:
print(f"Unique dolphins detected: {len(tracks)}")

# Trajectory analysis
for track_id, trajectory in tracks.items():
    if len(trajectory) > 30:  # Only long tracks
        print(f"Dolphin {track_id} appeared in {len(trajectory)} frames")
        # Calculate movement, speed, etc.

追跡の利点:

  • 個々の物体を数えられます(フレームごとの検出数ではありません)
  • 軌跡や動きのパターンを作成できます
  • 時間経過に伴う動作を分析できます
  • 一時的な誤検出を除外できます

追跡アルゴリズム:

アルゴリズム速度堅牢性オクルージョンへの対応
ByteTrack高速良好優秀
SORT非常に高速普通普通
DeepSORT中程度優秀良好
BotSORT中程度優秀優秀

本番環境向けチェックリスト

□ Preprocess frames (resize, pad, normalize)
□ Sample frames intelligently (1 FPS or scene change detection)
□ Use batch inference (16-32 images per batch)
□ Tune NMS thresholds for your use case
□ Implement tracking if analyzing video
□ Log inference time and GPU utilization
□ Handle edge cases (empty frames, corrupted video)
□ Save results in structured format (JSON, CSV)
□ Visualize detections for debugging
□ Benchmark on representative data

使用する場合と避ける場合

シナリオ適切かどうか
考古学調査のためにドローン映像を分析する✅ はい - カスタム物体検出
動画内の野生動物を追跡する✅ はい - 検出 + 追跡
群衆の人数を数える✅ はい - 密集した物体の検出
リアルタイムの防犯カメラ✅ はい - YOLOv8 によるリアルタイム処理
休暇中の写真を整理する❌ いいえ - 写真管理アプリを使用します
顔認識によるログイン❌ いいえ - AWS Rekognition API を使用します
ナンバープレートを読み取る❌ いいえ - 専用の OCR を使用します

参考資料

  • /references/yolo-guide.md - YOLOv8 のセットアップ、トレーニング、推論のパターン
  • /references/video-processing.md - フレーム抽出、シーン検出、最適化
  • /references/tracking-algorithms.md - ByteTrack、SORT、DeepSORT の比較

スクリプト

  • scripts/video_analyzer.py - フレームを抽出し、検出を実行してタイムラインを生成します
  • scripts/model_trainer.py - カスタムデータセットで YOLO をファインチューニングし、重みをエクスポートします

このスキルが対象とする分野:コンピュータービジョン | 物体検出 | 動画分析 | YOLO | 追跡 | ドローン映像 | 野生動物のモニタリング

コメント