RF-DETRによる物体検出・BoT-SORTによる追跡とBoT-SORTの可視化,TTAの機能付き(COCO 80クラス)(ソースコードと説明と利用ガイド)
【概要】
RF-DETRを用いた物体検出システムで、動画やウェブカメラからCOCO 80クラスの物体をリアルタイムで検出する。CLAHE前処理とTTAにより暗所でも高精度な検出が可能。BoT-SORTによる物体追跡機能を搭載し、フレーム間での継続的な追跡を実現する。【その他情報】
【目次】
第1章 プログラム利用ガイド
色分けによる検出の可視化
- 緑色の太枠(4px) - 高信頼度検出(CONF_THRESH = 0.25以上)
- 黄色の太枠(4px) - 低信頼度検出(0.1以上0.25未満で追跡に使用)
- シアン色の太枠(4px) - 新規トラック(新しく出現した物体)
画面表示の改善
- 左上に色分けの凡例を表示
- 各検出ボックスに「[高]」「[低]」「[新]」のラベルを追加
- 統計情報に「高:X 低:Y 新:Z」の形式で内訳を表示
設定値
- BOTSORT_VIZ = True - 可視化機能の有効化
- LOW_CONF_THRESH = 0.1 - 低信頼度検出の最小閾値
可視化により、BoT-SORTがどのように動作しているかが明確に分かります:
- 第1段階:緑色の高信頼度検出と既存トラックの、動きと外観特徴を用いた関連付け
- 第2段階:黄色の低信頼度検出による遮蔽物体の回復
- 新規検出:シアン色で新しく登場した物体を強調
プログラムを実行すると、これらの色分けがリアルタイムで確認できます。
第2章 事前準備
ここでは、最低限の事前準備について説明する。機械学習や深層学習を行う場合は、NVIDIA CUDA、Visual Studio、Cursorなどを追加でインストールすると便利である。これらについては別ページ https://www.kkaneko.jp/cc/dev/aiassist.htmlで詳しく解説しているので、必要に応じて参照してください。
第3章 Python 3.12 のインストール
Pythonのインストールを行い、Pythonのプログラムを実行する環境を整える。扱う環境は、Windows搭載パソコンである。金子研究室では、Python 3.12.10を推奨する。
[Windows での Python 3.12 のインストール手順を見るには、ここをクリック]
Windows での Python 3.12 のインストール
以下のいずれかの方法でPython 3.12をインストールする。Pythonがインストール済みの場合、この手順は不要である。
方法 1:winget によるインストール
【インストールコマンドの実行方法】
管理者権限でコマンドプロンプトを起動する(手順:Windowsキーまたはスタートメニュー → cmd と入力 → 右クリック → 「管理者として実行」)。そして、コマンド全体をコマンドプロンプトにコピー&ペーストする。
--scope machine を指定することで、システム全体(全ユーザー向け)にインストールされる。このオプションの実行には管理者権限が必要である。インストール完了後、コマンドプロンプトを再起動するとPATHが反映される。
REM Python 3.12 をシステム領域にインストール
winget install --id Python.Python.3.12 -e --scope machine --silent --accept-source-agreements --accept-package-agreements --override "/quiet InstallAllUsers=1 PrependPath=1 Include_test=0 Include_pip=1 Include_launcher=1 InstallLauncherAllUsers=1 TargetDir=\"C:\Program Files\Python312\""
REM Python と Scripts を PATH 先頭に追加
powershell -NoProfile -Command "$p='C:\Program Files\Python312'; $s=\"$p\Scripts\"; $c=[Environment]::GetEnvironmentVariable('Path','Machine'); if((Test-Path $p) -and (';'+$c+';' -notlike \"*;$p;*\") -and (';'+$c+';' -notlike \"*;$s;*\")){[Environment]::SetEnvironmentVariable('Path',\"$p;$s;$c\",'Machine')}"
方法 2:インストーラーによるインストール
- Python公式サイト(https://www.python.org/downloads/)にアクセスし、「Download Python 3.x.x」ボタンからWindows用インストーラーをダウンロードする。
- ダウンロードしたインストーラーを実行する。
- 初期画面の下部に表示される「Add python.exe to PATH」にチェックを入れてから「Customize installation」を選択する。このチェックを入れ忘れると、コマンドプロンプトから
pythonコマンドを実行できない。 - 「Install Python 3.xx for all users」にチェックを入れ、「Install」をクリックする。
インストールの確認
コマンドプロンプトで以下を実行する。
python --version
バージョン番号(例:Python 3.12.x)が表示されればインストール成功である。「'python' は、内部コマンドまたは外部コマンドとして認識されていません。」と表示される場合は、インストールが正常に完了していない。
第4章 Python の開発環境 Visual Studio Code のインストールと Python 用の設定
Python の開発環境Visual Studio Code(プログラムを編集するソフトウェア。以下、VS Code)を整える。
[Windows での Visual Studio Code のインストールと Python 用の設定手順を見るには、ここをクリック]
Windows での Visual Studio Code のインストールと Python 用の設定手順
1. VS Code と拡張機能のインストール
以下のコマンドにより,既存の VS Code を削除し,全ユーザー共有の設定で再インストールしたうえで,拡張機能(VS Code に機能を追加するソフトウェア)をまとめて導入する.
【インストールコマンドの実行方法】
管理者権限でコマンドプロンプトを起動する(手順:Windows キーまたはスタートメニュー → cmd と入力 → 右クリック → 「管理者として実行」)。そして,コマンド全体をコマンドプロンプトにコピー&ペーストする。
インストールコマンド
REM ============================================================
REM Microsoft Visual Studio Code
REM ============================================================
winget uninstall -e --id Microsoft.VisualStudioCode --silent --disable-interactivity --accept-source-agreements
rmdir /s /q C:\ProgramData\vscode-extensions 2>nul
rmdir /s /q "%APPDATA%\Code" 2>nul
rmdir /s /q "%USERPROFILE%\.vscode" 2>nul
rmdir /s /q "%LOCALAPPDATA%\Microsoft\vscode-update" 2>nul
REM VS Code をシステム領域に新規インストール
winget install --scope machine --id Microsoft.VisualStudioCode -e --silent --accept-source-agreements --accept-package-agreements
REM 全ユーザー共有の拡張機能フォルダ
mkdir C:\ProgramData\vscode-extensions 2>nul
icacls "C:\ProgramData\vscode-extensions" /grant "Everyone:(OI)(CI)M" /T
REM スタートメニューのショートカットを --extensions-dir 付きで再作成
rmdir /s /q "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Visual Studio Code" 2>nul
del "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Visual Studio Code.lnk" 2>nul
powershell -NoProfile -Command "$s=New-Object -ComObject WScript.Shell; $lnk=$s.CreateShortcut('C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Visual Studio Code.lnk'); $lnk.TargetPath='C:\Program Files\Microsoft VS Code\Code.exe'; $lnk.Arguments='--extensions-dir \"C:\ProgramData\vscode-extensions\"'; $lnk.Save()"
REM ショートカットの検証
powershell -NoProfile -Command "$s=New-Object -ComObject WScript.Shell; $lnk=$s.CreateShortcut('C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Visual Studio Code.lnk'); Write-Host 'TargetPath:' $lnk.TargetPath; Write-Host 'Arguments:' $lnk.Arguments"
REM ファイル / フォルダ右クリックの「Code で開く」を登録
reg add "HKLM\SOFTWARE\Classes\*\shell\VSCode\command" /ve /d "\"C:\Program Files\Microsoft VS Code\Code.exe\" --extensions-dir \"C:\ProgramData\vscode-extensions\" \"%1\"" /f
reg add "HKLM\SOFTWARE\Classes\Directory\shell\VSCode\command" /ve /d "\"C:\Program Files\Microsoft VS Code\Code.exe\" --extensions-dir \"C:\ProgramData\vscode-extensions\" \"%1\"" /f
reg add "HKLM\SOFTWARE\Classes\Directory\Background\shell\VSCode\command" /ve /d "\"C:\Program Files\Microsoft VS Code\Code.exe\" --extensions-dir \"C:\ProgramData\vscode-extensions\" \"%V\"" /f
REM --extensions-dir 付きで起動する code.cmd ラッパを作成
REM (%* を echo で書くと対話的 cmd で失われるため、PowerShell で [char]37+'*' を書き出す)
powershell -NoProfile -Command "$pct=[char]37; $q=[char]34; $c='@echo off'+[char]13+[char]10+$q+'C:\Program Files\Microsoft VS Code\bin\code.cmd'+$q+' --extensions-dir '+$q+'C:\ProgramData\vscode-extensions'+$q+' '+$pct+'*'+[char]13+[char]10; [IO.File]::WriteAllText('C:\ProgramData\vscode-extensions\vscode.cmd',$c,[Text.Encoding]::ASCII)"
REM 拡張機能のインストール
set "CODE=C:\Program Files\Microsoft VS Code\bin\code.cmd"
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --uninstall-extension GitHub.copilot
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --uninstall-extension GitHub.copilot-chat
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --install-extension ms-python.python
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --install-extension ms-python.vscode-pylance
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --install-extension ms-python.debugpy
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --install-extension MS-CEINTL.vscode-language-pack-ja
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --install-extension saoudrizwan.claude-dev
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --install-extension rust-lang.rust-analyzer
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --install-extension tamasfe.even-better-toml
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --install-extension anthropic.claude-code
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --install-extension almenon.arepl
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --list-extensions --show-versions
echo === セットアップ完了 ===
2. Python インタプリタの選択
同一マシンに複数の Python がインストールされている場合,VS Code で使用する Python 本体(インタプリタ:Python プログラムを解釈・実行するソフトウェア)を選択する必要がある.
- コマンドパレット(コマンド名で機能を呼び出す VS Code の入力欄)を開く(
Ctrl+Shift+P) Python: Select Interpreterと入力する
- 表示される一覧から,使用する Python(例:
C:\Program Files\Python312\python.exe)を選択する.
必要なパッケージのインストール
管理者権限でコマンドプロンプトを起動する
(手順:Windowsキーまたはスタートメニュー → cmd と入力 → 右クリック → 「管理者として実行」)。
REM PyTorch をインストール(GPU対応版)
set "CUDA_TAG=cu128"
set "PYTHON_PATH=C:\Program Files\Python312"
"%PYTHON_PATH%\Scripts\pip" install --no-user -U numpy torch torchvision torchaudio --index-url https://download.pytorch.org/whl/%CUDA_TAG%
pip install --no-user -U rfdetr opencv-python numpy pillow boxmot supervision
第5章 RF-DETRによる物体検出プログラム・BoT-SORTによる追跡とTTAの機能付き(COCO 80クラス)
概要
このプログラムは、RF-DETRを用いた物体検出システムである。動画ファイル、ウェブカメラ、サンプル動画から取得した映像に対してリアルタイムで物体検出を実行し、COCOデータセット80クラスの物体をバウンディングボックスで表示する。検出精度の向上を目的として、CLAHE(コントラスト制限付き適応ヒストグラム均一化)とTTA(Test-Time Augmentation)を組み合わせた前処理を実装している[1][2]。
主要技術
RF-DETR(Roboflow Detection Transformer)
Roboflowが開発したTransformerベースのリアルタイム物体検出モデルである[1][2]。DINOv2による自己教師あり事前学習済みバックボーンと、Deformable DETR・LW-DETRの設計を組み合わせ、COCOデータセットで60 mAPを超える初のリアルタイム物体検出モデルとなった。NMS(非最大抑制)を必要としないエンドツーエンドのアーキテクチャを採用し、RT-DETRv2を含む既存のリアルタイム検出器より高い精度を達成する。Apache 2.0ライセンスで提供される。
CLAHE(Contrast Limited Adaptive Histogram Equalization)
Zuiderveldが1994年に提案したコントラスト強化手法である[3][4]。画像を小領域(タイル)に分割し、各タイルでヒストグラム均一化を適用する。コントラスト制限機能により、ノイズの過度な増幅を防止する。
BoT-SORT
カルマンフィルタとカメラモーション補正を組み合わせた物体追跡手法である[7]。低信頼度検出も含めた2段階の関連付けに加え、外観特徴(ReID)によるマッチングをオプションで有効化でき、遮蔽環境でもByteTrackより安定した追跡を実現する。
技術的特徴
- Test-Time Augmentation(TTA)による検出精度向上
推論時に元画像と水平反転画像の両方を処理し、Non-Maximum Suppression(NMS)で結果を統合する[5][6]。この手法により物体の向きに対する頑健性が向上し、検出漏れが減少する。
- CLAHE前処理による暗部環境対応
YUV色空間のY(輝度)チャンネルにCLAHEを適用し、暗い場所や逆光環境での検出精度を向上させる[3][4]。clipLimit=3.0、tileGridSize=(8,8)のパラメータを使用する。
- GPU/CPU自動検出システム
CUDA対応GPUの有無を自動判定し、利用可能な場合はGPU処理、そうでない場合はCPU処理に自動切り替えを行う。
- 固定信頼度閾値フィルタリング
物体検出の信頼度閾値(CONF_THRESHOLD=0.25)とTTA用のNMS閾値(NMS_THRESHOLD=0.6)による安定したフィルタリングを実装する。
- BoT-SORT物体追跡
フレーム間での物体の継続的な追跡により、一時的な検出失敗や遮蔽に対する頑健性を提供する。各物体に固有のIDを割り当て、軌跡を管理する。
実装の特色
リアルタイム映像処理に特化した設計を採用し、以下の機能を備える:
- 3つの入力ソース選択(動画ファイル、ウェブカメラ、サンプル動画)
- 日本語対応のリアルタイム結果表示(Pillow + Meiryoフォント使用)
- 3種類のモデルサイズ選択(RFDETRSmall、RFDETRMedium、RFDETRLarge)
- BoT-SORT追跡による物体ID管理機能
- 検出結果の自動ファイル出力機能(result.txt)
- フレーム処理結果の詳細ログ出力
- 色分けされたクラス別バウンディングボックス表示
参考文献
[1] Robinson, I., Robicheaux, P., & Popov, M. (2025). RF-DETR: SOTA Real-Time Object Detection Model. Roboflow. https://github.com/roboflow/rf-detr
[2] Roboflow. (2026). RF-DETR Documentation. https://rfdetr.roboflow.com/
[3] Zuiderveld, K. (1994). Contrast limited adaptive histogram equalization. Graphics gems IV, 474-485.
[4] OpenCV Team. (2024). Histogram Equalization Documentation. https://docs.opencv.org/4.x/d5/daf/tutorial_py_histogram_equalization.html
[5] Shanmugam, D., Blalock, D., Balakrishnan, G., & Guttag, J. (2021). When and why test-time augmentation works. arXiv preprint arXiv:2011.11156.
[6] Machine Learning Mastery. (2020). How to Use Test-Time Augmentation. https://machinelearningmastery.com/how-to-use-test-time-augmentation-to-improve-model-performance-for-image-classification/
[7] Aharon, N., Orfaig, R., & Bobrovsky, B. (2022). BoT-SORT: Robust Associations Multi-Pedestrian Tracking. arXiv:2206.14651.
ソースコード
# -*- coding: utf-8 -*-
"""
RF-DETRによる物体検出プログラム・BoT-SORTによる追跡とTTAの機能付き(COCO 80クラス)
特徴技術名: RF-DETR + BoT-SORT
出典: Robinson, I., Robicheaux, P., & Popov, M. (2025). RF-DETR: SOTA Real-Time
Object Detection Model. Roboflow. https://github.com/roboflow/rf-detr
Aharon, N. et al. (2022). BoT-SORT: Robust Associations Multi-Pedestrian
Tracking. arXiv:2206.14651.
特徴機能: NMSフリーのTransformer物体検出(RF-DETR、DINOv2バックボーン)に、
カメラモーション補正と外観特徴(ReID)を統合したBoT-SORTによる追跡を組み合わせる。
CLAHEによる暗部補正とTTA(水平反転)による検出精度向上を実装。
学習済みモデル: RF-DETR (RFDETRSmall / RFDETRMedium / RFDETRLarge)
- 概要: COCOデータセット80クラス対応、DINOv2バックボーン、Apache 2.0ライセンス
- URL: 自動ダウンロード (https://github.com/roboflow/rf-detr)
ReIDモデル: osnet_x0_25_msmt17(boxmotが自動ダウンロード)
方式設計:
関連利用技術:
- RF-DETR: DINOv2バックボーンを用いたTransformerベースのリアルタイム物体検出モデル
- BoT-SORT: カルマンフィルタ・カメラモーション補正・ReIDを統合した追跡(boxmotライブラリ)
- CLAHE: 暗部・逆光環境向けコントラスト補正
- OpenCV: 画像・動画処理、日本語フォント表示対応
入力と出力:
入力: 動画(ユーザは「0:動画ファイル,1:カメラ,2:サンプル動画」のメニューで選択.
0:動画ファイルの場合はtkinterでファイル選択.1の場合はOpenCVでカメラが開く.
2の場合はhttps://raw.githubusercontent.com/opencv/opencv/master/samples/data/vtest.aviを使用)
出力: OpenCV画面でリアルタイム表示。色分けされたバウンディングボックスと追跡情報を表示。
各フレームごとにprint()で処理結果表示。プログラム終了時にresult.txtファイルに保存。
処理手順:
1. CLAHEによる暗部補正前処理
2. RF-DETRによる物体検出(TTA:元画像と水平反転画像を統合)
3. 高信頼度・低信頼度検出の色分け
4. BoT-SORTによる追跡(動き予測・カメラモーション補正・ReID)
5. 日本語フォント使用による結果可視化
前処理: CLAHEによるコントラスト補正、TTA用の水平反転画像生成
後処理: TTA結果のNMSによる統合、検出結果のフィルタリング、追跡ID管理
追加処理: 日本語テキスト描画による視認性向上、色分け凡例表示
調整を必要とする設定値:
- CONF_THRESHOLD: 検出信頼度閾値(高信頼度・低信頼度検出の分離基準)
- LOW_CONF_THRESH: 低信頼度検出の最小閾値(追跡に使用する下限)
- NMS_THRESHOLD: TTA統合時のNMS閾値
将来方策: 検出信頼度閾値の自動調整機能、複数カメラ対応、リアルタイム性能最適化
その他の重要事項: Windows環境設計、メイリョフォント使用
前準備:
pip install --no-user -U rfdetr opencv-python numpy pillow boxmot supervision torch
"""
# 調整可能な設定値
CONF_THRESHOLD = 0.25 # 高信頼度検出の閾値
LOW_CONF_THRESH = 0.1 # 低信頼度検出の最小閾値(追跡に使用)
NMS_THRESHOLD = 0.6 # TTA統合用NMS閾値
BOTSORT_VIZ = True # 可視化機能の有効化
FONT_SIZE = 20
FONT_PATH = 'C:/Windows/Fonts/meiryo.ttc'
import cv2
import tkinter as tk
from tkinter import filedialog
import numpy as np
import torch
from torchvision.ops import nms
from PIL import Image, ImageDraw, ImageFont
import urllib.request
import time
from datetime import datetime
from boxmot import BotSort
from pathlib import Path
# GPU/CPU自動選択
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f'デバイス: {str(device)}')
if device.type == 'cuda':
torch.backends.cudnn.benchmark = True
def apply_clahe(frame):
"""CLAHEによる暗部・逆光補正(YUV色空間のYチャンネルに適用)"""
yuv = cv2.cvtColor(frame, cv2.COLOR_BGR2YUV)
clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8, 8))
yuv[:, :, 0] = clahe.apply(yuv[:, :, 0])
return cv2.cvtColor(yuv, cv2.COLOR_YUV2BGR)
def detect_with_tta(frame_rgb):
"""TTA(元画像+水平反転)による物体検出とNMS統合"""
flipped_rgb = cv2.flip(frame_rgb, 1)
w = frame_rgb.shape[1]
all_boxes, all_scores, all_labels = [], [], []
for img_array, is_flipped in [(frame_rgb, False), (flipped_rgb, True)]:
detections = model.predict(img_array, threshold=LOW_CONF_THRESH)
boxes = torch.from_numpy(detections.xyxy.astype(np.float32))
if is_flipped and boxes.shape[0] > 0:
boxes = boxes.clone()
x1 = w - torch.from_numpy(detections.xyxy[:, 2].astype(np.float32))
x2 = w - torch.from_numpy(detections.xyxy[:, 0].astype(np.float32))
boxes[:, 0] = x1
boxes[:, 2] = x2
all_boxes.append(boxes)
all_scores.append(torch.from_numpy(detections.confidence.astype(np.float32)))
all_labels.append(torch.from_numpy(detections.class_id.astype(np.float32)))
boxes_cat = torch.cat(all_boxes, dim=0)
scores_cat = torch.cat(all_scores, dim=0)
labels_cat = torch.cat(all_labels, dim=0)
if boxes_cat.shape[0] == 0:
return np.empty((0, 4)), np.empty((0,)), np.empty((0,))
keep = nms(boxes_cat, scores_cat, NMS_THRESHOLD)
return boxes_cat[keep].numpy(), scores_cat[keep].numpy(), labels_cat[keep].numpy()
frame_count = 0
results_log = []
def video_frame_processing(frame):
global frame_count
current_time = time.time()
frame_count += 1
# CLAHE前処理
enhanced_frame = apply_clahe(frame)
frame_rgb = cv2.cvtColor(enhanced_frame, cv2.COLOR_BGR2RGB)
# RF-DETRによる検出(TTA付き)
boxes, scores, labels = detect_with_tta(frame_rgb)
high_count, low_count, new_count = 0, 0, 0
# BoT-SORT用の検出配列(N, 6: x1,y1,x2,y2,conf,cls)を構築
if boxes.shape[0] > 0:
dets = np.concatenate([boxes, scores.reshape(-1, 1), labels.reshape(-1, 1)], axis=1).astype(np.float32)
else:
dets = np.empty((0, 6), dtype=np.float32)
# BoT-SORTによる追跡更新
tracks = tracker.update(dets, frame) # --> (x1,y1,x2,y2,id,conf,cls,ind)
ann_frame = frame.copy()
img_pil = Image.fromarray(cv2.cvtColor(ann_frame, cv2.COLOR_BGR2RGB))
draw = ImageDraw.Draw(img_pil)
tracking_data = []
if tracks.shape[0] > 0:
for t in tracks:
x1, y1, x2, y2, track_id, conf, cls, _ = t
x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2)
track_id = int(track_id)
cls = int(cls)
if conf >= CONF_THRESHOLD:
level = '高'
box_color = (0, 255, 0)
high_count += 1
else:
level = '低'
box_color = (255, 255, 0)
low_count += 1
is_new = track_id not in seen_track_ids
if is_new:
seen_track_ids.add(track_id)
box_color = (0, 255, 255)
level = '新'
new_count += 1
cv2.rectangle(ann_frame, (x1, y1), (x2, y2), box_color, 4)
label_text = f"ID:{track_id} [{level}] {conf:.2f}"
draw.text((x1, max(0, y1 - 25)), label_text, font=font, fill=box_color)
tracking_data.append({
'id': track_id, 'class': cls, 'confidence': conf,
'level': level, 'bbox': (x1, y1, x2, y2)
})
ann_frame = cv2.cvtColor(np.array(img_pil), cv2.COLOR_RGB2BGR)
# 色分け凡例表示
if BOTSORT_VIZ:
img_pil_legend = Image.fromarray(cv2.cvtColor(ann_frame, cv2.COLOR_BGR2RGB))
draw_legend = ImageDraw.Draw(img_pil_legend)
draw_legend.text((10, 10), '緑:高信頼度 黄:低信頼度 シアン:新規トラック', font=font, fill=(255, 255, 255))
status_text = f'高:{high_count} 低:{low_count} 新:{new_count}'
draw_legend.text((10, 35), status_text, font=font, fill=(0, 255, 255))
ann_frame = cv2.cvtColor(np.array(img_pil_legend), cv2.COLOR_RGB2BGR)
result = f"フレーム:{frame_count}|高:{high_count}|低:{low_count}|新:{new_count}|" + \
"|".join(f"ID{d['id']}:cls{d['class']}:{d['confidence']:.2f}" for d in tracking_data)
return ann_frame, result, current_time
# メイン処理
print('========================================')
print('RF-DETR + BoT-SORT 物体検出・追跡プログラム')
print('========================================')
print('概要: RF-DETRによる物体検出とBoT-SORTによる追跡を統合')
print('特徴: CLAHE前処理とTTAにより暗所でも高精度な検出が可能')
print('注意事項:')
print(' - GPU使用時は処理が高速化されます')
print(' - 初回実行時はモデルのダウンロードに時間がかかります')
print('操作方法:')
print(' q キー: プログラム終了')
print('========================================')
print('\nモデルサイズ選択:')
print('0: RFDETRSmall(軽量・高速)')
print('1: RFDETRMedium(標準・推奨)')
print('2: RFDETRLarge(高精度)')
model_choice = input('選択: ')
print(f'\nRF-DETRモデル初期化中...')
if model_choice == '0':
from rfdetr import RFDETRSmall
model = RFDETRSmall()
MODEL_NAME = 'RFDETRSmall'
elif model_choice == '2':
from rfdetr import RFDETRLarge
model = RFDETRLarge()
MODEL_NAME = 'RFDETRLarge'
else:
from rfdetr import RFDETRMedium
model = RFDETRMedium()
MODEL_NAME = 'RFDETRMedium'
print('RF-DETR初期化完了')
print('BoT-SORTトラッカー初期化中...')
tracker = BotSort(
reid_weights=Path('osnet_x0_25_msmt17.pt'),
device=device,
half=False,
with_reid=True,
)
seen_track_ids = set()
print('BoT-SORT初期化完了')
font = ImageFont.truetype(FONT_PATH, FONT_SIZE)
print('日本語フォント: 設定完了')
print("\n0: 動画ファイル")
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 = "RF-DETR + BoT-SORT トラッキング"
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(f'使用モデル: {MODEL_NAME}\n')
f.write('\n=== フレームごとの結果 ===\n')
f.write('\n'.join(results_log))
print(f'\n処理結果をresult.txtに保存しました')