PyQt5 を基盤とした YOLOv5 検知アプリの GUI 構築技術

システムアーキテクチャの構成要素

本プロジェクトは、高次元の機械学習モデルと軽量なデスクトップアプリケーションフレームワークを結合することで、エンドユーザーが複雑なパラメータ設定を行わずに推論を実行できる環境を提供しています。主要なコンポーネントは、表示層(Presentation Layer)、制御ロジック(Logic Layer)、および推論エンジン(Algorithm Layer)の 3 つの階層に明確に分かれています。
  • View Layer: main_win/ ディレクトリに配置されたクラス群。ユーザーとの直接的なインタラクションを行い、Qt Designer で定義されたウィジェットを使用します。
  • Data & Control Layer: ユーザーからの入力を受け取り、バックグラウンドプロセスへデータを送信するミドルウェアとしての役割を担います。
  • Inference Layer: PyTorch ベースの重みファイルを読み込み、画像または動画ストリームに対して推論処理を実行します。

ディレクトリの物理的な配置は機能ごとに整理されており、保守性を高めています。例えば、ユーティリティ関数は utils/ パスに集約され、独自のパースや画像変換処理を担当します。

開発環境の初期設定

依存関係のインストール

プロジェクトルートに含まれる要件定義ファイルを使用して、必要なライブラリを環境に投入します。この方法により、バージョンの不整合を防ぎつつ、すべてのモジュールを一括で取得できます。

pip install -r requirements.txt

リポジトリの取得と実行

ソースコードを取得した後、以下のコマンドを実行してメインのスクリプトを起動します。

git clone https://github.com/example/pytorch-yolov5-pyqt.git
cd pytorch-yolov5-pyqt
python main.py

初期化が完了すると、モデルの選択画面および入力ソースの設定ダイアログが表示されます。

非同期処理ループの設計

スレッドベースの推論

GUI スレッドのブロックを防ぐため、重い計算処理は別スレッドで実行されます。このアプローチでは、結果をメインウインドウへ返送するためにシグナル・スロット機構を活用します。

from PyQt5.QtCore import QThread, pyqtSignal
import cv2
import torch

class InferenceWorker(QThread):
    frame_updated = pyqtSignal(cv2.Mat)
    meta_info = pyqtSignal(dict)

    def __init__(self, model_path: str, device_id: int):
        super().__init__()
        self.device = f'cuda:{device_id}' if torch.cuda.is_available() else 'cpu'
        self.model_source = model_path
        self.input_stream = None
        self.is_running = False

    def set_input(self, stream_index):
        self.input_stream = stream_index

    def run(self):
        """
        メインループ:フレーム読み込みから描画までを処理
        """
        if self.input_stream == '0':
            cap = cv2.VideoCapture(0)
        else:
            cap = cv2.VideoCapture(self.input_stream)

        model = torch.hub.load('ultralytics/yolov5', 'custom', path=self.model_source)
        
        while self.is_running:
            ret, frame = cap.read()
            if not ret:
                break
            
            results = model(frame)
            annotated_frame = results.render()[0]
            
            # 結果を信号として送信し、GUI を更新
            self.frame_updated.emit(annotated_frame)

推論パイプラインの主要ステップ

  1. デバイスの判定(GPU アクセラレーションの有効性確認)
  2. 事前訓練済み重みのメモリへの読み込み
  3. データ前処理(サイズ正規化など)
  4. モデルによる予測出力
  5. NMS(Non-Maximum Suppression)後のバウンディングボックスの抽出

カスタマイズの戦略

独自モデルの適用

ユーザー独自のトレーニング済みモデルをデプロイする場合、既存の設定ファイルのみを書き換える必要があります。モデルの拡張子に対応するパスを指定すれば、動的に切り替えが可能です。

# 設定パレット内の該当フィールドを更新
self.worker_config['path'] = r'C:\projects\my_custom_trained_model.pt'

なお、ファイル形式が正しく変換された PT ファイルであることを確認してください。

レイアウトの変更

Qt Designer を利用して .ui ファイルを視覚的に編集し、その後、ビルドツールチェーンによって Python コードに変換できます。これは UI の再構築をコーディングレスで行うための標準的な手法です。

pyuic5 -x ui_design.ui -o ui_code.py

機能拡張の提案

新規機能の追加には、以下のフローに沿って実装を行うことを推奨します。

  1. tools/ フォルダ内に新しいヘルパー関数を定義
  2. 必要に応じて設定ウィザードを追加
  3. メインコントローラーにイベントリスナーを登録
  4. 推論ロジック内でそのハンドリングを実装

タグ: PyQt5 YOLOv5 OpenCV PyTorch qthread

7月12日 16:31 投稿