YOLO11による物体検出
【概要】YOLO11を使用してリアルタイム物体検出を実行。Enhanced Feature Extractionにより物体検出の学習を実行し、5種類のモデルサイズによる精度と速度の比較実験が可能。Windows環境での実行手順、プログラムコード、実験アイデアを含む。


目次
概要
技術名: YOLO11(You Only Look Once version 11)
発表: 2024年9月30日、Ultralytics YOLO Vision 2024 (YV24) にて正式発表
新規性・特徴: YOLO11は、Enhanced Feature Extraction(強化された特徴抽出)を採用した最新の物体検出技術である。C3k2(Cross Stage Partial with kernel size 2:カーネルサイズ2のクロスステージ部分接続)ブロックによる効率的な特徴抽出、C2PSA(Convolutional block with Parallel Spatial Attention:並列空間アテンション付き畳み込みブロック)による空間アテンション機構、SPPF(Spatial Pyramid Pooling - Fast:高速空間ピラミッドプーリング)による多スケール特徴統合により、物体検出を実現する。
技術革新:
- C3k2ブロック:2つの小さな畳み込みによる効率的なCSP Bottleneck(クロスステージ部分ボトルネック:異なる段階の特徴を部分的に接続する構造)実装、処理速度向上
- C2PSA:空間アテンション機構(画像内の重要な領域に注意を向ける仕組み)により重要な領域に焦点、小物体検出精度向上
- SPPF:異なるスケールでの特徴プーリング(複数の解像度で特徴を統合する手法)による多スケール物体検出能力向上
- 統合アーキテクチャ:単一ネットワークでの効率的な物体検出処理
アプリケーション例: 自動運転、監視システム、工業検査、ロボットビジョン、リアルタイム映像解析、品質管理、セキュリティ監視、スポーツ解析
使用する学習済みモデル
YOLO11事前学習済みモデル:
- 学習データセット: MS COCO 2017(80クラス物体検出)
- 検出可能物体: 人、車両、動物、家具、電子機器など80種類
- 出力形式: バウンディングボックス + クラス確率 + 信頼度
- 入力解像度: 640×640ピクセル(デフォルト)
- モデルサイズ: Nano版(軽量)からExtra Large版(高精度)まで5種類
- 技術特徴: C3k2ブロック、C2PSA空間アテンション、SPPF多スケール処理
事前準備
Python, Windsurfをインストールしていない場合の手順(インストール済みの場合は実行不要)。
- 管理者権限でコマンドプロンプトを起動する(手順:Windowsキーまたはスタートメニュー > cmd と入力 > 右クリック > 「管理者として実行」)。
- 以下のコマンドをそれぞれ実行する(winget コマンドは1つずつ実行)。
REM Python をシステム領域にインストール
winget install --scope machine --id Python.Python.3.12 -e --silent
REM Windsurf をシステム領域にインストール
winget install --scope machine --id Codeium.Windsurf -e --silent
REM Python のパス設定
set "PYTHON_PATH=C:\Program Files\Python312"
set "PYTHON_SCRIPTS_PATH=C:\Program Files\Python312\Scripts"
echo "%PATH%" | find /i "%PYTHON_PATH%" >nul
if errorlevel 1 setx PATH "%PATH%;%PYTHON_PATH%" /M >nul
echo "%PATH%" | find /i "%PYTHON_SCRIPTS_PATH%" >nul
if errorlevel 1 setx PATH "%PATH%;%PYTHON_SCRIPTS_PATH%" /M >nul
REM Windsurf のパス設定
set "WINDSURF_PATH=C:\Program Files\Windsurf"
if exist "%WINDSURF_PATH%" (
echo "%PATH%" | find /i "%WINDSURF_PATH%" >nul
if errorlevel 1 setx PATH "%PATH%;%WINDSURF_PATH%" /M >nul
)
必要なパッケージのインストール
管理者権限でコマンドプロンプトを起動し、以下のコマンドを実行する:
pip install -U torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu126
pip install ultralytics opencv-python numpy
YOLO11物体検出プログラム
概要
このプログラムはカメラまたは動画ファイルから入力される映像データを解析し、画像内の複数物体を同時に検出・分類・位置特定する。YOLO11を用いて、バウンディングボックスとクラス確率を直接予測する[1][2]。
主要技術
- YOLO11物体検出アルゴリズム
You Only Look Once第11版は、画像全体を一度の評価で処理し、物体の位置特定と分類を同時実行する単一段階検出器である。C3k2ブロック、C2PSA空間アテンション機構、SPPF多スケール特徴プーリングによる改良アーキテクチャを採用[1][3]。
参考文献
- [1] Jocher, G., & Qiu, J. (2024). Ultralytics YOLO11 (Version 11.0.0). GitHub. https://github.com/ultralytics/ultralytics
- [2] Redmon, J., Divvala, S., Girshick, R., & Farhadi, A. (2016). You only look once: Unified, real-time object detection. In Proceedings of the IEEE conference on computer vision and pattern recognition (pp. 779-788).
- [3] Ultralytics. (2024). YOLO11: Enhanced feature extraction for object detection. Ultralytics Documentation. https://docs.ultralytics.com/models/yolo11/
ソースコード
# プログラム名: YOLO11物体検出プログラム
# 特徴技術名: YOLO11
# 出典: Ultralytics YOLO11 (https://github.com/ultralytics/ultralytics)
# 特徴機能: YOLO11による物体検出。COCO 80クラス全体を検出
# 学習済みモデル: YOLO11 COCO事前学習済みモデル(80クラス全体)
# - yolo11n.pt(Nanoモデル、2.6M params、mAP50-95: 39.5%)
# - yolo11s.pt(Smallモデル、9.4M params、mAP50-95: 47.0%)
# - yolo11m.pt(Mediumモデル、20.1M params、mAP50-95: 51.5%)
# - yolo11l.pt(Largeモデル、25.3M params、mAP50-95: 53.4%)
# - yolo11x.pt(Extra Largeモデル、56.9M params、mAP50-95: 54.7%)
# - 全モデルMS COCO 2017データセット(80クラス物体検出)対応
# 方式設計:
# - 関連利用技術:
# - PyTorch: 深層学習フレームワーク、CUDA対応によるGPU加速
# - OpenCV: 画像処理、カメラ制御、描画処理、動画入出力管理
# - 入力と出力: 入力: 動画(ユーザは「0:動画ファイル,1:カメラ,2:サンプル動画」のメニューで選択.0:動画ファイルの場合はtkinterでファイル選択.1の場合はOpenCVでカメラが開く.2の場合はhttps://github.com/opencv/opencv/raw/master/samples/data/vtest.aviを使用)、出力: OpenCV画面でリアルタイム表示(検出したオブジェクトをバウンディングボックスで表示)、各フレームごとにprint()による処理結果出力、プログラム終了時にresult.txtファイルに保存
# - 処理手順: 1.フレーム取得、2.YOLO11推論実行、3.COCO 80クラス全体の検出、4.信頼度閾値による選別、5.バウンディングボックス描画
# - 前処理、後処理: 前処理:YOLO11内部で自動実行(640x640リサイズ、正規化)。後処理:YOLO11内部処理により重複除去を含む後処理が自動実行。信頼度による閾値フィルタリングのみ実施
# - 追加処理: CUDA/CPU自動検出機能により、GPU搭載環境では自動的に処理速度向上。検出結果の信頼度降順ソートにより重要な検出を優先表示
# - 調整を必要とする設定値: CONF_THRESHOLD(オブジェクト検出信頼度閾値、デフォルト0.25)- 値を上げると誤検出が減少するが検出漏れが増加
# 将来方策: CONF_THRESHOLDの動的調整機能。フレーム毎の検出数を監視し、検出数が閾値を超えた場合は信頼度を上げ、検出数が少ない場合は下げる適応的制御の実装
# その他の重要事項: Windows環境専用設計、CUDA対応GPU推奨(自動検出・CPUフォールバック機能付き)、初回実行時は学習済みモデルの自動ダウンロード
# 前準備:
# - pip install -U torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu126
# - pip install ultralytics opencv-python numpy pillow
import cv2
import tkinter as tk
from tkinter import filedialog
import os
import torch
import numpy as np
from ultralytics import YOLO
import warnings
import time
import urllib.request
from datetime import datetime
from PIL import Image, ImageDraw, ImageFont
warnings.filterwarnings('ignore')
# ===== 設定・定数管理 =====
# モデル情報
MODEL_INFO = {
'n': {'name': 'nano', 'desc': '小', 'params': '2.6M', 'mAP': '39.5%'},
's': {'name': 'small', 'desc': '小', 'params': '9.4M', 'mAP': '47.0%'},
'm': {'name': 'medium', 'desc': '中', 'params': '20.1M', 'mAP': '51.5%'},
'l': {'name': 'large', 'desc': '大', 'params': '25.3M', 'mAP': '53.4%'},
'x': {'name': 'extra large', 'desc': '特大', 'params': '56.9M', 'mAP': '54.7%'}
}
# COCO 80クラス名
COCO_CLASSES = [
'person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train', 'truck', 'boat', 'traffic light',
'fire hydrant', 'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep', 'cow',
'elephant', 'bear', 'zebra', 'giraffe', 'backpack', 'umbrella', 'handbag', 'tie', 'suitcase', 'frisbee',
'skis', 'snowboard', 'sports ball', 'kite', 'baseball bat', 'baseball glove', 'skateboard', 'surfboard',
'tennis racket', 'bottle', 'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple',
'sandwich', 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair', 'couch',
'potted plant', 'bed', 'dining table', 'toilet', 'tv', 'laptop', 'mouse', 'remote', 'keyboard', 'cell phone',
'microwave', 'oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase', 'scissors', 'teddy bear',
'hair drier', 'toothbrush'
]
# クラスごとの色生成(HSVからBGRに変換)
def generate_colors(num_classes):
colors = []
for i in range(num_classes):
hue = int(180.0 * i / num_classes)
hsv = np.uint8([[[hue, 255, 255]]])
bgr = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)[0][0]
colors.append((int(bgr[0]), int(bgr[1]), int(bgr[2])))
return colors
CLASS_COLORS = generate_colors(len(COCO_CLASSES))
SAMPLE_VIDEO_URL = 'https://github.com/opencv/opencv/raw/master/samples/data/vtest.avi'
SAMPLE_VIDEO_FILE = 'vtest.avi'
RESULT_FILE = 'result.txt'
# カメラ設定(必要に応じて調整)
WINDOW_WIDTH = 1280
WINDOW_HEIGHT = 720
FPS = 30
# 検出パラメータ(調整可能)
CONF_THRESHOLD = 0.25 # オブジェクト検出信頼度閾値(0.0-1.0)
# フォント設定(Pillow使用)
FONT_PATH = 'C:/Windows/Fonts/meiryo.ttc'
FONT_SIZE_MAIN = 20
FONT_SIZE_LABEL = 18
# ユーザガイダンス
print('=== YOLO11オブジェクト検出プログラム ===')
print('概要: リアルタイムでオブジェクトを検出し、バウンディングボックスで表示します')
print('機能: YOLO11による物体検出(COCOデータセット80クラス)')
print('操作: qキーで終了')
print('出力: 各フレームごとに処理結果を表示し、終了時にresult.txtへ保存')
print()
# モデル選択
print('使用するYOLO11モデルを選択してください:')
print('n: Nano (2.6M params, mAP 39.5%)')
print('s: Small (9.4M params, mAP 47.0%)')
print('m: Medium (20.1M params, mAP 51.5%)')
print('l: Large (25.3M params, mAP 53.4%)')
print('x: Extra Large (56.9M params, mAP 54.7%)')
print()
model_choice = input('モデル選択 (n/s/m/l/x) [デフォルト: n]: ').strip().lower()
if model_choice not in ['n', 's', 'm', 'l', 'x']:
model_choice = 'n'
print('デフォルトのnanoモデルを使用します')
MODEL_SIZE = model_choice
MODEL_NAME = f'yolo11{MODEL_SIZE}.pt'
# システム初期化
print()
print('システム初期化中...')
start_time = time.time()
# GPU/CPU自動選択(統一)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f'デバイス: {str(device)}')
# YOLO11モデル初期化
try:
print(f'YOLO11{MODEL_SIZE}モデルを初期化中...')
model = YOLO(MODEL_NAME)
model.to(device)
print(f'YOLO11{MODEL_SIZE}モデルの初期化が完了しました')
print(f'モデル: {MODEL_INFO[MODEL_SIZE]["name"]} ({MODEL_INFO[MODEL_SIZE]["params"]} params, mAP {MODEL_INFO[MODEL_SIZE]["mAP"]})')
except Exception as e:
print(f'YOLO11{MODEL_SIZE}モデルの初期化に失敗しました')
print(f'エラー: {e}')
exit()
print(f'{str(device).upper()}使用モード')
print('初期化完了')
print()
# グローバル変数
frame_count = 0
results_log = []
def draw_text_pil(bgr_frame, texts):
"""
Pillow + Meiryoで日本語テキストを描画する。
texts: list of dict with keys {text, org, color}
"""
font_main = ImageFont.truetype(FONT_PATH, FONT_SIZE_MAIN)
font_label = ImageFont.truetype(FONT_PATH, FONT_SIZE_LABEL)
img_pil = Image.fromarray(cv2.cvtColor(bgr_frame, cv2.COLOR_BGR2RGB))
draw = ImageDraw.Draw(img_pil)
for item in texts:
text = item['text']
x, y = item['org']
color = item['color'] # RGB
font = font_main if item.get('font', 'main') == 'main' else font_label
draw.text((x, y), text, font=font, fill=color)
return cv2.cvtColor(np.array(img_pil), cv2.COLOR_RGB2BGR)
def video_frame_processing(frame):
"""
フレーム処理
- 推論実行
- バウンディングボックス描画
- 結果文字列の生成(B案: 各検出ボックスのクラス、信頼度、座標をCSV風で列挙)
"""
global frame_count
current_time = time.time()
frame_count += 1
# 推論実行(閾値はmodel側で適用。後段の二重判定は行わない)
results = model(frame, conf=CONF_THRESHOLD, verbose=False)
objects = []
r0 = results[0]
if r0.boxes is not None and len(r0.boxes) > 0:
boxes = r0.boxes.xyxy.cpu().numpy()
confs = r0.boxes.conf.cpu().numpy()
classes = r0.boxes.cls.cpu().numpy()
# 信頼度でソート(降順)
sorted_indices = np.argsort(confs)[::-1]
boxes = boxes[sorted_indices]
confs = confs[sorted_indices]
classes = classes[sorted_indices]
for box, conf, cls in zip(boxes, confs, classes):
x1, y1, x2, y2 = map(int, box)
class_id = int(cls)
class_name = COCO_CLASSES[class_id] if 0 <= class_id < len(COCO_CLASSES) else str(class_id)
objects.append({
'box': (x1, y1, x2, y2),
'conf': float(conf),
'class_id': class_id,
'class_name': class_name
})
# 描画処理(矩形はOpenCV、テキストはPillow)
for obj in objects:
x1, y1, x2, y2 = obj['box']
class_id = obj['class_id']
color = CLASS_COLORS[class_id] if 0 <= class_id < len(CLASS_COLORS) else (0, 255, 0)
cv2.rectangle(frame, (x1, y1), (x2, y2), color, 2)
# ラベル・情報テキスト(Pillowで日本語表示)
text_items = []
for obj in objects:
x1, y1, x2, y2 = obj['box']
class_name = obj['class_name']
conf_pct = f'{obj["conf"]*100:.1f}%'
# RGB色に変換
b, g, r = CLASS_COLORS[obj['class_id']] if 0 <= obj['class_id'] < len(CLASS_COLORS) else (0, 255, 0)
text_items.append({'text': f'{class_name}', 'org': (x1, max(0, y1 - 22)), 'color': (r, g, b), 'font': 'label'})
text_items.append({'text': f'Conf:{conf_pct}', 'org': (x1, min(y2 + 5, frame.shape[0]-20)), 'color': (255, 255, 255), 'font': 'label'})
info1 = f'YOLO11{MODEL_SIZE} ({str(device).upper()}) | Frame: {frame_count} | Objects: {len(objects)}'
info2 = '操作: q キーで終了'
text_items.append({'text': info1, 'org': (10, 10), 'color': (255, 255, 255), 'font': 'main'})
text_items.append({'text': info2, 'org': (10, 35), 'color': (255, 255, 0), 'font': 'label'})
frame = draw_text_pil(frame, text_items)
# 出力用の結果文字列(B案: CSV風列挙)
if len(objects) == 0:
result = 'count=0'
else:
parts = []
for obj in objects:
x1, y1, x2, y2 = obj['box']
parts.append(f'class={obj["class_name"]},conf={obj["conf"]:.3f},box=[{x1},{y1},{x2},{y2}]')
result = f'count={len(objects)}; ' + ' | '.join(parts)
return frame, result, current_time
# 入力選択
print('入力ソースを選択してください:')
print('0: 動画ファイル')
print('1: カメラ')
print('2: サンプル動画')
print()
choice = input('選択 (0/1/2): ').strip()
temp_file = None
if choice == '0':
root = tk.Tk()
root.withdraw()
path = filedialog.askopenfilename()
if not path:
exit()
cap = cv2.VideoCapture(path)
elif choice == '1':
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
if not cap.isOpened():
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
# 必要に応じて解像度設定(任意)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, WINDOW_WIDTH)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, WINDOW_HEIGHT)
cap.set(cv2.CAP_PROP_FPS, FPS)
else:
# サンプル動画ダウンロード・処理
try:
urllib.request.urlretrieve(SAMPLE_VIDEO_URL, SAMPLE_VIDEO_FILE)
temp_file = SAMPLE_VIDEO_FILE
except Exception as e:
print(f"動画のダウンロードに失敗しました: {SAMPLE_VIDEO_URL}")
print(f"エラー: {e}")
exit()
cap = cv2.VideoCapture(SAMPLE_VIDEO_FILE)
if not cap.isOpened():
print('動画ファイル・カメラを開けませんでした')
exit()
# メイン処理
print('\n=== 動画処理開始 ===')
print('操作方法:')
print(' q キー: プログラム終了')
MAIN_FUNC_DESC = "YOLO11 物体検出"
try:
while True:
ret, frame = cap.read()
if not ret:
break
processed_frame, result, current_time = video_frame_processing(frame)
cv2.imshow(MAIN_FUNC_DESC, processed_frame)
if choice == '1': # カメラの場合は時刻付き
print(datetime.fromtimestamp(current_time).strftime("%Y-%m-%d %H:%M:%S.%f")[:-3], result)
else: # 動画ファイルまたはサンプル動画の場合はフレーム番号付き
print(frame_count, result)
results_log.append(result)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
finally:
print('\n=== プログラム終了 ===')
cap.release()
cv2.destroyAllWindows()
if results_log:
with open(RESULT_FILE, 'w', encoding='utf-8') as f:
f.write('=== YOLO11オブジェクト検出結果 ===\n')
f.write(f'処理フレーム数: {frame_count}\n')
f.write(f'使用モデル: YOLO11{MODEL_SIZE} ({MODEL_INFO[MODEL_SIZE]["name"]})\n')
f.write(f'使用デバイス: {str(device).upper()}\n')
if device.type == 'cuda':
f.write(f'GPU: {torch.cuda.get_device_name(0)}\n')
f.write('\n')
f.write('\n'.join(results_log))
print(f'\n処理結果を{RESULT_FILE}に保存しました')
if temp_file and os.path.exists(temp_file):
os.remove(temp_file)
使用方法
- プログラムを実行
- カメラを選んだ場合,カメラに向かって様々な物体を映すと、バウンディングボックスとクラス名、信頼度が表示される
- 検出された各物体にはクラス名と信頼度が表示される
- YOLO11のC2PSA並列空間アテンション機構により、複雑な背景や小物体においても検出精度が向上する
- フレーム情報でEnhanced Feature Extractionの動作状況を確認できる
- 'q'キーを押すとプログラムが終了する
実験・探求のアイデア
YOLO11モデル選択実験
プログラム冒頭のMODEL_NAMEを変更することで、異なるYOLO11モデルを比較できる:
yolo11n.pt
:Nano版(最高効率、エッジデバイス最適)yolo11s.pt
:Small版(バランス型、実用性重視)yolo11m.pt
:Medium版(汎用用途、精度向上)yolo11l.pt
:Large版(高精度重視、計算コスト増)yolo11x.pt
:Extra Large版(最高性能、最大計算要求)
空間アテンション機構の検証実験
C2PSAの並列空間アテンション効果を定量的に評価:
- 小物体検出:C2PSAによる小さな物体の検出精度向上の測定
- 複数物体検出:密集環境での物体分離能力の評価
- 部分遮蔽対応:遮蔽された物体の検出復元性能
- 複雑背景処理:背景が複雑な環境での物体検出精度
体験・実験・探求のアイデア
アーキテクチャ改良効果の測定: C3k2とC2PSAの技術革新により、従来困難であった複雑シーンでの性能向上を定量的に測定
リアルタイム応用実験:
- 自動運転シミュレーション:車両、歩行者、道路標識の精密検出
- 監視システム:異常物体の自動検出
- 工業検査:製品の欠陥自動検出
- スポーツ解析:選手とボールの追跡
多スケール検出能力の実験: SPPFによる異なるサイズの物体同時検出性能を評価