RT-DETRv2による人物検知(ソースコードと実行結果)


ツール利用ガイド
1. このツールの利用シーン
このツールは、動画やウェブカメラの映像から人物を自動検出するプログラムである。監視システム、来客検知、人数カウント、映像解析などの用途に適用できる。RT-DETRv2による検出機能により、人物認識を実現する。
2. 主な機能
- 人物検出: 動画の各フレームから人物を検出し、バウンディングボックスで表示する
- 複数の入力対応: 動画ファイル、ウェブカメラ、サンプル動画の3つの入力モードを選択可能
- 信頼度判定: 検出した人物の信頼度を表示
- 処理結果記録: 各フレームの検出結果をコンソール出力およびresult.txtファイルに保存
3. 基本的な使い方
- プログラム起動: Pythonでプログラムを実行すると、入力モード選択画面が表示される
- 入力モード選択: キーボードで「0」(動画ファイル)、「1」(ウェブカメラ)、「2」(サンプル動画)のいずれかを入力
- 動画ファイル選択: 「0」を選択した場合、ファイル選択ダイアログが開き、動画ファイルを指定
- 検出開始: 選択した入力ソースから映像処理が開始され、人物検出結果がリアルタイム表示される
- プログラム終了: 映像表示画面でキーボードの「q」キーを押下して終了
4. 表示される情報
- デバイス情報: 使用中の処理デバイス(GPU/CPU)とフレーム番号
- 検出結果: 各フレームで検出された人物数と個別の信頼度
- 存在判定: 最大信頼度に基づく人物存在レベルの評価
- バウンディングボックス: 検出した人物を緑色の矩形で囲み、個別の信頼度を表示
- 処理ログ: コンソールには各フレームの詳細結果、result.txtには全処理結果が記録される
Python開発環境,ライブラリ類
ここでは、最低限の事前準備について説明する。機械学習や深層学習を行う場合は、NVIDIA CUDA、Visual Studio、Cursorなどを追加でインストールすると便利である。これらについては別ページ https://www.kkaneko.jp/cc/dev/aiassist.htmlで詳しく解説しているので、必要に応じて参照してください。
Python 3.12 のインストール
インストール済みの場合は実行不要。
管理者権限でコマンドプロンプトを起動(手順:Windowsキーまたはスタートメニュー > cmd と入力 > 右クリック > 「管理者として実行」)し、以下を実行する。管理者権限は、wingetの--scope machineオプションでシステム全体にソフトウェアをインストールするために必要である。
REM Python をシステム領域にインストール
winget install --scope machine --id Python.Python.3.12 -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
【関連する外部ページ】
Python の公式ページ: https://www.python.org/
AI エディタ Windsurf のインストール
Pythonプログラムの編集・実行には、AI エディタの利用を推奨する。ここでは,Windsurfのインストールを説明する。
管理者権限でコマンドプロンプトを起動(手順:Windowsキーまたはスタートメニュー > cmd と入力 > 右クリック > 「管理者として実行」)し、以下を実行して、Windsurfをシステム全体にインストールする。管理者権限は、wingetの--scope machineオプションでシステム全体にソフトウェアをインストールするために必要となる。
winget install --scope machine Codeium.Windsurf -e --silent
【関連する外部ページ】
Windsurf の公式ページ: https://windsurf.com/
必要なライブラリのインストール
コマンドプロンプトを管理者として実行(手順:Windowsキーまたはスタートメニュー > cmd と入力 > 右クリック > 「管理者として実行」)し、以下を実行する
pip install -U torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu126
pip install transformers opencv-python numpy pillow
RT-DETRv2による人物検知プログラム
概要
RT-DETRv2を用いた人物検出プログラムである。動画ファイル、ウェブカメラ、サンプル動画の3つの入力モードから人物を検出する。COCOデータセットのPersonクラス(ID=0)のみに対象を限定して検出を行う。信頼度ベースのフィルタリングを行う。各フレームの処理結果をprint出力およびresult.txtファイルへ保存する。
主要技術
RT-DETRv2 (Real-Time Detection Transformer version 2)
2024年に発表された物体検出Transformerである[1]。RT-DETRを基盤とし、Bag-of-Freebies技術による改善が行われた。選択的マルチスケール特徴抽出により、異なるスケールの特徴に対して異なる数のサンプリングポイントを設定し、デコーダによる処理を可能とする[2]。
Hugging Face Transformers
RTDetrV2ForObjectDetectionモデルとRTDetrImageProcessorを用いた実装である[3]。事前学習済みモデルPekingU/rtdetr_v2_r50vdを使用。
COCOデータセットによる物体分類
Common Objects in Context (COCO)データセットの80クラス分類による事前学習済みモデルを使用する。Personクラス(ID=0)のみに対象を限定して検出を行う。
技術的特徴
Bag-of-Freebies手法
動的データ拡張、スケール適応ハイパーパラメータのカスタマイゼーション、離散サンプリング演算子の導入により、性能向上を狙う[1]。
エンドツーエンド処理
Non-Maximum Suppression (NMS)を必要としない検出フレームワークである。[2]。
参考文献
[1] Lv, W., Zhao, Y., Chang, Q., Huang, K., Wang, G., & Liu, Y. (2024). RT-DETRv2: Improved Baseline with Bag-of-Freebies for Real-Time Detection Transformer. arXiv preprint arXiv:2407.17140. https://arxiv.org/abs/2407.17140
[2] Lv, W., Zhao, Y., Xu, S., Wei, J., Wang, G., Dang, Q., & Liu, Y. (2023). DETRs Beat YOLOs on Real-time Object Detection. arXiv preprint arXiv:2304.08069. https://arxiv.org/abs/2304.08069
[3] Hugging Face Transformers Documentation. RT-DETRv2 Model Documentation. https://huggingface.co/docs/transformers/model_doc/rt_detr_v2
ソースコード
# プログラム名: RT-DETRv2による人物検知プログラム
# 特徴技術名: RT-DETRv2 (Real-Time Detection Transformer version 2)
# 出典: W. Lv, Y. Zhao, Q. Chang, K. Huang, G. Wang, and Y. Liu, "RT-DETRv2: Improved Baseline with Bag-of-Freebies for Real-Time Detection Transformer," arXiv preprint arXiv:2407.17140, 2024.
# 特徴機能: Bag-of-Freebiesによる改良ベースラインと選択的マルチスケール特徴抽出による物体検出
# 学習済みモデル: PekingU/rtdetr_v2_r50vd(RT-DETRv2 ResNet-50ベース、Hugging Face Transformers、URL: https://huggingface.co/PekingU/rtdetr_v2_r50vd)
# 方式設計:
# - 関連利用技術:
# - PyTorch: 深層学習フレームワーク、CUDA対応によるGPU加速
# - OpenCV: 画像処理、カメラ制御、描画処理、動画入出力管理
# - Transformers: Hugging Face Transformersライブラリ
# - 入力と出力: 入力: 動画(ユーザは「0:動画ファイル,1:カメラ,2:サンプル動画」のメニューで選択.0:動画ファイルの場合はtkinterでファイル選択.1の場合はOpenCVでカメラが開く.2の場合はhttps://raw.githubusercontent.com/opencv/opencv/master/samples/data/vtest.aviを使用)、出力: OpenCV画面でリアルタイム表示(検出した人物をバウンディングボックスで表示)、各フレームごとのprint()による処理結果表示、プログラム終了時にresult.txtファイルに保存
# - 処理手順: 1.フレーム取得、2.RT-DETRv2推論実行、3.Personクラス(ID=0)のフィルタリング、4.信頼度閾値による選別、5.バウンディングボックス描画
# - 前処理、後処理: 前処理:PIL Imageへの変換、プロセッサによる自動前処理。後処理:プロセッサによる後処理、信頼度による閾値フィルタリング
# - 追加処理: CUDA/CPU自動検出機能による実行デバイス選択、検出結果の信頼度降順ソートによる表示順制御、presence_levelの判定(最大信頼度ベース、基準を表示)
# - 調整を必要とする設定値: CONF_THRESH(人物検出信頼度閾値、デフォルト0.5)- 値を上げると誤検出が減少するが検出漏れが増加
# 将来方策: CONF_THRESHの動的調整機能。フレーム毎の検出数を監視し、検出数が閾値を超えた場合は信頼度を上げ、検出数が少ない場合は下げる適応的制御の実装
# その他の重要事項: Windows環境専用設計、CUDA対応GPU推奨(自動検出・CPUフォールバック機能付き)、初回実行時は学習済みモデルの自動ダウンロード
# 前準備:
# - pip install -U torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu126
# - pip install transformers opencv-python numpy pillow
import cv2
import tkinter as tk
from tkinter import filedialog
import torch
import numpy as np
from transformers import RTDetrV2ForObjectDetection, RTDetrImageProcessor
from PIL import Image, ImageDraw, ImageFont
import time
import urllib.request
from datetime import datetime
# GPU/CPU自動選択
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f'デバイス: {str(device)}')
# ===== 設定・定数管理 =====
# RT-DETRv2モデル設定
MODEL_NAME = 'PekingU/rtdetr_v2_r50vd'
# 検出パラメータ(調整可能)
CONF_THRESH = 0.5 # 人物検出信頼度閾値(0.0-1.0)
PERSON_CLASS_ID = 0 # COCOデータセットにおけるPersonクラスのID
# 人物の表示色(BGR形式)
PERSON_COLOR = (0, 255, 0) # 緑(バウンディングボックス用)
# フォント設定
FONT_PATH = 'C:/Windows/Fonts/meiryo.ttc'
FONT_SIZE = 30
# プログラム概要表示
print('=== RT-DETRv2人物検出プログラム ===')
print('概要: リアルタイムで人物を検出し、バウンディングボックスで表示します')
print('機能: RT-DETRv2による人物検出(COCOデータセットのPersonクラス)')
print('操作: 0=動画ファイル選択, 1=カメラ, 2=サンプル動画 / qキーで終了')
print('出力: フレームごとでの処理結果表示、終了時にresult.txt保存')
print()
# RT-DETRv2モデル初期化
print(f'RT-DETRv2モデルを初期化中...')
model = RTDetrV2ForObjectDetection.from_pretrained(MODEL_NAME)
processor = RTDetrImageProcessor.from_pretrained(MODEL_NAME)
model.to(device)
model.eval()
print(f'RT-DETRv2モデルの初期化が完了しました')
print()
frame_count = 0
results_log = []
def video_frame_processing(frame):
global frame_count
current_time = time.time()
frame_count += 1
# 画像前処理
frame_pil_input = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
inputs = processor(images=frame_pil_input, return_tensors='pt')
inputs = {k: v.to(device) for k, v in inputs.items()}
# 物体検出の実行(推論)
with torch.no_grad():
outputs = model(**inputs)
# 結果処理(信頼度閾値を直接適用)
target_sizes = torch.tensor([frame.shape[:2]]).to(device)
results = processor.post_process_object_detection(
outputs, target_sizes=target_sizes, threshold=CONF_THRESH
)[0]
persons = []
if len(results['labels']) > 0:
boxes = results['boxes'].cpu().numpy()
scores = results['scores'].cpu().numpy()
labels = results['labels'].cpu().numpy()
# Personクラスのみフィルタリング
person_indices = labels == PERSON_CLASS_ID
if np.any(person_indices):
person_boxes = boxes[person_indices]
person_scores = scores[person_indices]
# 信頼度でソート(降順)
sorted_indices = np.argsort(person_scores)[::-1]
person_boxes = person_boxes[sorted_indices]
person_scores = person_scores[sorted_indices]
# 各人物の処理(安全な座標変換)
for i, (box, score) in enumerate(zip(person_boxes, person_scores)):
box_cpu = box.cpu() if hasattr(box, 'cpu') else box
if hasattr(box_cpu, 'numpy'):
box_numpy = box_cpu.numpy()
else:
box_numpy = box_cpu
if box_numpy.ndim == 1 and len(box_numpy) >= 4:
x1, y1, x2, y2 = map(int, box_numpy[:4])
persons.append({
'box': (x1, y1, x2, y2),
'detection_conf': float(score)
})
# presence判定(最大信頼度ベース)
person_count = len(persons)
if person_count == 0:
presence_level = '気配なし'
max_conf_text = '最大信頼度: N/A'
max_conf_value = 0.0
else:
max_conf_value = max(p['detection_conf'] for p in persons)
max_conf_text = f'最大信頼度: {max_conf_value:.0%}'
if max_conf_value < 0.7:
presence_level = '人影の可能性'
else:
presence_level = '人の存在確認'
result = f'フレーム {frame_count}: {person_count}人検出'
for i, p in enumerate(persons):
result += f' | 人物{i+1}: 信頼度{p["detection_conf"]:.0%}'
result += f' | 判定: {presence_level}(最大信頼度基準: {max_conf_value:.0%})'
# バウンディングボックス(OpenCVで矩形のみ描画)
for i, p in enumerate(persons):
x1, y1, x2, y2 = p['box']
cv2.rectangle(frame, (x1, y1), (x2, y2), PERSON_COLOR, 2)
# テキスト表示はPillowで描画(Meiryo)
img_pil = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
draw = ImageDraw.Draw(img_pil)
font = ImageFont.truetype(FONT_PATH, FONT_SIZE)
# 画面情報
info1 = f'RT-DETRv2 ({device}) | Frame: {frame_count}'
info2 = '操作: q=終了'
draw.text((10, 30), info1, font=font, fill=(255, 255, 255))
draw.text((10, 70), info2, font=font, fill=(255, 255, 0))
# 判定結果
draw.text((10, 110), presence_level, font=font, fill=(0, 255, 0))
draw.text((10, 150), max_conf_text, font=font, fill=(0, 180, 255))
draw.text((10, 190), f'Person: {person_count}', font=font, fill=(255, 0, 0))
# 各人物ラベル(Pillowで描画)
for i, p in enumerate(persons):
x1, y1, x2, y2 = p['box']
draw.text((x1, max(0, y1 - 30)), f'Person {i+1}', font=font, fill=(0, 255, 0))
draw.text((x1, y2 + 5), f'Conf:{p["detection_conf"]:.1%}', font=font, fill=(255, 255, 255))
# RGB→BGRに戻す
frame = cv2.cvtColor(np.array(img_pil), cv2.COLOR_RGB2BGR)
return frame, result, current_time
print("0: 動画ファイル")
print("1: カメラ")
print("2: サンプル動画")
choice = input("選択: ")
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)
else:
# サンプル動画ダウンロード・処理
SAMPLE_URL = 'https://raw.githubusercontent.com/opencv/opencv/master/samples/data/vtest.avi'
SAMPLE_FILE = 'vtest.avi'
urllib.request.urlretrieve(SAMPLE_URL, SAMPLE_FILE)
cap = cv2.VideoCapture(SAMPLE_FILE)
if not cap.isOpened():
print('動画ファイル・カメラを開けませんでした')
exit()
# メイン処理
print('\n=== 動画処理開始 ===')
print('操作方法:')
print(' q キー: プログラム終了')
try:
while True:
ret, frame = cap.read()
if not ret:
break
MAIN_FUNC_DESC = "RT-DETRv2による人物検出"
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.txt', 'w', encoding='utf-8') as f:
f.write('=== 結果 ===\n')
f.write(f'処理フレーム数: {frame_count}\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.txtに保存しました')