HumansXドキュメントセンター 公式サイトへ ↗

インテリジェント追跡アルゴリズムの詳細説明

1. アルゴリズムの概要

インテリジェント顔追跡システムは、リアルタイムの顔追跡シーン向けに最適化された高度な複数対象追跡・予測制御アルゴリズムを実装しています。最新のコンピュータービジョン技術、制御理論、機械学習の手法を組み合わせ、高精度・低遅延で安定した信頼性の高い顔追跡機能を実現しています。

🎯 主要技術の特長

  • 🔍 インテリジェントな対象選択: 複数要素のスコアリングに基づく最適対象選択アルゴリズム
  • 🔗 永続的な追跡: 対象IDの関連付けとライフサイクル管理
  • 📍 高精度な位置特定: ピクセル単位の座標計算と座標系変換
  • 🔮 動き予測: カルマンフィルターに基づく対象の動き予測
  • 🎛️ インテリジェント制御: PIDコントローラーとブレ防止の最適化
  • ⚡ リアルタイム性能: エンドツーエンドの制御遅延<50ms

🏗️ システムアーキテクチャ

检测结果输入 → 目标关联 → 评分排序 → 目标选择 → 运动预测 → 控制输出
      ↓            ↓        ↓        ↓        ↓        ↓
   边界框列表  → ID匹配   → 综合评分 → 最优目标 → 位置预测 → 云台角度
      ↑                                               ↓
   视频帧    ←←←←←← 反馈控制 ←←←←←← PID调节 ←←←←←← 执行反馈

📊 アルゴリズムの性能指標

指標分類 性能目標 実測値
応答速度 <50ms 35-45ms
追跡精度 ±5ピクセル ±3ピクセル
安定性 <0.1回切替/秒 0.05回切替/秒
予測精度 >90% 94%
制御精度 ±1° ±0.5°

2. 複数対象追跡システム

2.1 対象選択アルゴリズム

対象選択アルゴリズムは複数要素の総合スコアリングの仕組みに基づき、複数の対象のさまざまな特性を比較して、追跡に最適な対象を選択します。

スコアリング要素

スコアリングシステムは、以下の4つの重要な要素を総合的に考慮します。

  1. 対象の信頼度:対象検出アルゴリズムが出力する信頼度スコアで、対象が正しく検出された可能性を表します
  2. 対象のサイズ:対象のバウンディングボックスの面積(正規化済み)で、一般に大きい対象ほど主な注目対象である可能性が高くなります
  3. 対象の持続性:対象が連続して検出された回数で、長時間安定して存在する対象ほど追跡すべき対象である可能性が高くなります
  4. 位置の連続性:対象の位置と過去の位置との一致度で、対象の動きの滑らかさと一貫性を表します

スコア計算式

対象の最終スコアは以下の式で計算されます。

最终评分 = 基础评分 + 持久性评分 × 持久性权重 + 位置连续性评分 × 位置权重 + 当前目标加成

ここで:

  • 基本スコア = 信頼度の重み × 信頼度 + サイズの重み × 正規化面積
  • 持続性スコア = 対象の連続検出回数 / 最大履歴カウント
  • 位置連続性スコア = 1.0 - min(現在位置と前回位置の距離 / 最大位置距離, 1.0)
  • 現在対象ボーナス:現在追跡中の対象であれば、追加のスコアボーナス(対象切替しきい値と同じ値)を与えます

2.2 対象関連付けアルゴリズム

対象関連付けアルゴリズムは、現在のフレームで検出された対象と履歴に記録された対象との対応関係を確立し、対象IDの永続的な追跡を実現します。

関連付けの手順

  1. 距離行列の計算:
  • 現在のフレームの各対象と、履歴に記録された各対象とのユークリッド距離を計算します
  • 距離行列 D[i,j] は、現在のフレームのi番目の対象と履歴のj番目の対象との距離を表します
  1. 最近傍マッチング:
  • 現在のフレームの各対象について、未割り当ての履歴対象の中から最も距離の近い対象を探します
  • 見つかった最短距離が最大位置距離しきい値より小さければ、マッチング成功とみなします
  • マッチングに成功したら、その履歴対象の位置・タイムスタンプなどの属性を更新します
  • 位置連続性スコアを計算します:position_score = 1.0 - min(min_distance / max_position_distance, 1.0)
  1. 新規対象の作成:
  • 現在のフレームの対象がどの履歴対象ともマッチングできない場合は、新しい対象IDを作成します
  • 新規対象のカウント・位置・タイムスタンプなどの属性を初期化します

2.3 対象切替戦略

一時的なスコアの変動によって追跡対象が頻繁に切り替わるのを防ぐため、アルゴリズムには対象切替戦略が実装されています。

  1. スコアが最も高い新しい対象が現れても即座に切り替えず、現在追跡中の対象とスコアを比較します
  2. 新しい対象のスコアが現在の対象のスコアを切替しきい値(target_switch_threshold)以上上回った場合にのみ、対象を切り替えます
  3. そうでない場合は、新しい対象のスコアがわずかに高くても現在の対象の追跡を続け、追跡の安定性を保ちます

この戦略は「ヒステリシスコンパレーター」(hysteresis comparator) に似ており、スコアのわずかな変動による対象の頻繁な切り替わりを効果的に防止できます。

2.4 対象のライフサイクル管理

システムを効率的に稼働させ、メモリリークを防ぐため、アルゴリズムには完全な対象ライフサイクル管理の仕組みが実装されています。

対象の状態遷移

新检测 → 候选目标 → 确认目标 → 稳定追踪 → 丢失检测 → 超时清理
   ↓         ↓         ↓         ↓         ↓         ↓
创建ID  → 初始评分  → 正式追踪 → 持续更新 → 预测补偿 → 资源释放

ライフサイクル管理戦略

  1. 新規対象の検証期間 (0-3フレーム):
  • 連続検出による検証で、誤検出ノイズを回避
  • 初期位置と運動パラメーターの推定
  • 既存対象との関連性チェック
  1. 安定追跡期間 (3フレーム~タイムアウト):
  • 通常のスコア更新と位置予測
  • 運動パラメーターの継続的な最適化
  • 追跡品質のリアルタイム評価
  1. ロスト回復期間 (検出ロスト~タイムアウト前):
  • 動き予測に基づく位置推定
  • スコアの重みを下げつつIDを保持
  • 再関連付けの仕組みを準備
  1. タイムアウトによるクリーンアップ:
def cleanup_expired_targets(self, current_time, timeout_threshold=3.0):
    """清理超时目标"""
    expired_targets = []

    for target_id, target in self.targets.items():
        time_since_last_seen = current_time - target.last_seen_time

        if time_since_last_seen > timeout_threshold:
            expired_targets.append(target_id)
            # 记录目标统计信息
            self.log_target_lifecycle(target)

    # 批量清理过期目标
    for target_id in expired_targets:
        if target_id == self.current_target_id:
            self.current_target_id = None
        del self.targets[target_id]

    return len(expired_targets)

メモリ最適化戦略

  • オブジェクトプールの再利用: 対象オブジェクトを再利用してGCの負荷を軽減
  • 履歴データの制限: 各対象の履歴記録の長さを制限
  • インテリジェント圧縮: 長期間非アクティブな対象データを定期的に圧縮
  • 統計情報の収集: アルゴリズム最適化のために対象のライフサイクル統計を記録

3. 座標の計算と変換

3.1 座標系の定義

本システムは多層の座標系を用いて、正確な位置計算と制御を実現しています。

画像座標系 (Image Coordinate System)

原点: (0, 0) 位于图像左上角
X轴: 向右为正方向,范围 [0, 640]
Y轴: 向下为正方向,范围 [0, 480]
单位: 像素 (pixel)

相対座標系 (Relative Coordinate System)

原点: (0, 0) 位于图像中心 (320, 240)
X轴: 向右为正,范围 [-320, +320]
Y轴: 向上为正,范围 [-240, +240]
单位: 像素 (pixel)

雲台角度座標系 (Gimbal Coordinate System)

水平轴 (Pan): 0°-270°,135°为中心
垂直轴 (Tilt): 0°-270°,135°为中心
单位: 度 (degree)
精度: 1° 步进

3.2 オフセット量の計算

高精度オフセット量計算アルゴリズム:

class CoordinateCalculator:
    def __init__(self, image_width=640, image_height=480):
        self.image_center = (image_width // 2, image_height // 2)
        self.image_width = image_width
        self.image_height = image_height

    def calculate_target_offset(self, bbox, use_weighted_center=True):
        """计算目标偏移量(支持加权中心)"""
        x1, y1, x2, y2 = bbox

        if use_weighted_center:
            # 使用加权中心(考虑人脸特征分布)
            center_x = x1 + (x2 - x1) * 0.5
            center_y = y1 + (y2 - y1) * 0.4  # 人脸重心偏上
        else:
            # 几何中心
            center_x = (x1 + x2) / 2
            center_y = (y1 + y2) / 2

        # 计算相对于图像中心的偏移
        offset_x = center_x - self.image_center[0]
        offset_y = self.image_center[1] - center_y  # Y轴翻转

        # 计算偏移距离和角度
        distance = math.sqrt(offset_x**2 + offset_y**2)
        angle = math.atan2(offset_y, offset_x)  # 弧度

        return {
            'offset_x': offset_x,
            'offset_y': offset_y,
            'distance': distance,
            'angle_rad': angle,
            'angle_deg': math.degrees(angle),
            'normalized_x': offset_x / (self.image_width / 2),
            'normalized_y': offset_y / (self.image_height / 2)
        }

オフセット量の高度な特性:

  1. サブピクセル精度: 浮動小数点演算によりサブピクセル単位の精度に対応
  2. 重み付き中心: 顔の特徴分布に基づいて中心点の計算を最適化
  3. 正規化座標: [-1, 1]の範囲の正規化座標を提供
  4. 極座標表現: 直交座標と極座標の両方の表現を提供
  5. 境界チェック: 境界条件や異常値を自動的に処理

3.3 方向判定アルゴリズム

インテリジェント方向判定システム:

class DirectionAnalyzer:
    def __init__(self, direction_threshold=15, deadzone_radius=10):
        self.direction_threshold = direction_threshold
        self.deadzone_radius = deadzone_radius

        # 方向映射表
        self.direction_map = {
            (0, 0): "center",
            (1, 0): "right", (-1, 0): "left",
            (0, 1): "up", (0, -1): "down",
            (1, 1): "right-up", (1, -1): "right-down",
            (-1, 1): "left-up", (-1, -1): "left-down"
        }

        # 角度区间定义
        self.angle_sectors = {
            "right": (337.5, 22.5),      # -22.5° to +22.5°
            "right-up": (22.5, 67.5),   # +22.5° to +67.5°
            "up": (67.5, 112.5),        # +67.5° to +112.5°
            "left-up": (112.5, 157.5),  # +112.5° to +157.5°
            "left": (157.5, 202.5),     # +157.5° to +202.5°
            "left-down": (202.5, 247.5), # +202.5° to +247.5°
            "down": (247.5, 292.5),     # +247.5° to +292.5°
            "right-down": (292.5, 337.5) # +292.5° to +337.5°
        }

    def analyze_direction(self, offset_x, offset_y):
        """分析目标方向(多种方法)"""
        distance = math.sqrt(offset_x**2 + offset_y**2)

        # 死区检测
        if distance <= self.deadzone_radius:
            return {
                'direction': 'center',
                'confidence': 1.0,
                'distance': distance,
                'method': 'deadzone'
            }

        # 方法1: 阈值方法(传统)
        threshold_direction = self._threshold_method(offset_x, offset_y)

        # 方法2: 角度方法(精确)
        angle_direction = self._angle_method(offset_x, offset_y)

        # 方法3: 区域方法(稳定)
        region_direction = self._region_method(offset_x, offset_y)

        # 综合判断(投票机制)
        final_direction = self._vote_direction([
            threshold_direction,
            angle_direction,
            region_direction
        ])

        return {
            'direction': final_direction,
            'confidence': self._calculate_confidence(offset_x, offset_y),
            'distance': distance,
            'angle': math.degrees(math.atan2(offset_y, offset_x)),
            'methods': {
                'threshold': threshold_direction,
                'angle': angle_direction,
                'region': region_direction
            }
        }

    def _angle_method(self, offset_x, offset_y):
        """基于角度的方向判断"""
        angle = math.degrees(math.atan2(offset_y, offset_x))
        # 转换到[0, 360)范围
        if angle < 0:
            angle += 360

        for direction, (start, end) in self.angle_sectors.items():
            if start > end:  # 跨越0度的情况
                if angle >= start or angle < end:
                    return direction
            else:
                if start <= angle < end:
                    return direction

        return "undefined"

    def _calculate_confidence(self, offset_x, offset_y):
        """计算方向判断的置信度"""
        distance = math.sqrt(offset_x**2 + offset_y**2)

        # 距离越远,置信度越高(到一定程度)
        distance_confidence = min(distance / 50.0, 1.0)

        # 角度稳定性(与主要方向轴的对齐程度)
        angle = math.atan2(abs(offset_y), abs(offset_x))
        axis_alignment = 1.0 - min(abs(angle - math.pi/4) / (math.pi/4), 1.0)

        return (distance_confidence * 0.7 + axis_alignment * 0.3)

方向判定の特長:

  • 複数手法の融合: しきい値・角度・領域の3つの手法による投票で決定
  • 信頼度評価: 方向判定の信頼性スコアを提供
  • デッドゾーン処理: 中心領域を特別に処理してブレを防止
  • 高精度な角度判定: 8方向の正確な判定に対応
  • 安定性の最適化: 境界付近での方向の急な切り替わりを防止

4. 動き予測システム

動き予測システムはインテリジェント追跡アルゴリズムの中核コンポーネントです。対象の将来位置を予測して雲台の向きを事前に調整することで、追跡遅延を大幅に低減し、追跡精度を高めます。

4.1 カルマンフィルターの設計

カルマンフィルターは再帰的な状態推定器で、測定値と予測値を融合してシステムの真の状態を推定します。対象追跡では、カルマンフィルターは対象の動きの予測に使用され、特に高速で移動する対象の処理に適しています。

状態空間モデル

本システムのカルマンフィルターは2次のシステムモデルを採用しており、状態ベクトルには対象の位置と速度が含まれます。

状态向量 X = [x, y, vx, vy]^T

ここで:

  • (x, y) は対象の中心座標
  • (vx, vy) は対象のx方向とy方向の速度

フィルターの更新フロー

カルマンフィルターの更新は、予測と測定更新の2つの主要なステップで構成されます。

  1. 予測ステップ:
  • 前の時刻の状態と状態遷移行列から現在の状態を予測します
  • 状態共分散行列を更新します
X_pred = F * X
P_pred = F * P * F^T + Q
  1. 測定更新ステップ:
  • カルマンゲインを計算します
  • 測定値に基づいて状態推定を更新します
  • 共分散行列を更新します
K = P_pred * H^T * (H * P_pred * H^T + R)^-1
X = X_pred + K * (Z - H * X_pred)
P = (I - K * H) * P_pred

ここで:

  • F: 状態遷移行列。システムがある状態から次の状態へどのように遷移するかを表します
  • H: 観測行列。状態変数から測定値をどのように得るかを表します
  • Q: プロセスノイズ共分散行列。予測過程の不確かさを表します
  • R: 観測ノイズ共分散行列。測定過程の不確かさを表します
  • K: カルマンゲイン。予測値と測定値を融合する際の重みを決定します

4.2 運動モデルと予測

対象位置の予測機能により、対象が一時的に消えたり高速で移動したりした場合でも、過去の運動パターンから対象の将来位置を予測でき、追跡の連続性と安定性が向上します。

予測の仕組み

  1. 速度推定:
  • カルマンフィルターが対象の速度ベクトル (vx, vy) を継続的に推定します
  • 速度情報は対象の履歴に保存され、その後の予測に使用されます
  1. 位置予測:
  • 対象をロストした場合、最後に推定した速度と位置から対象の現在位置を予測します
  • 予測式:predicted_position = last_position + velocity * dt
  • 予測位置に基づいて対象のバウンディングボックスを再構築します
  1. 予測信頼度の減衰:
  • 予測位置で対象を更新するたびに、予測信頼度を下げます
  • 信頼度がしきい値を下回ったら予測を停止し、存在しない対象を長時間追跡し続けることを防ぎます
  1. 予測距離の制限:
  • 予測距離が最大予測距離を超えないように制限し、過大な予測による追跡のずれを防ぎます
  • 距離制限を超えた場合は、予測位置を比例縮小します

4.3 予測制御戦略

サーボ予測制御は、対象の動き予測とサーボ制御を組み合わせることで、高速で移動する対象を先回りして追跡し、システム遅延の影響を軽減します。

制御戦略

  1. 先行量制御:
  • 高速で移動する対象については、速度の大きさに応じて先行量を計算します
  • サーボは対象の現在位置ではなく、予測された将来位置を狙います
  1. 動的な重み調整:
  • 速度が大きいほど、予測位置の重みを高くします
  • 動的重みの計算:dynamic_weight = min(base_weight * velocity_magnitude / threshold, max_weight)
  1. 位置の融合:
  • 現在の測定位置と予測位置を重み付けして融合します
  • 融合式:final_position = current_position * (1 - weight) + predicted_position * weight
  1. 予測追跡の継続:
  • 対象を一時的にロストしても、データの経過時間が短い場合は、速度情報を用いて予測追跡を継続します
  • 応答速度を下げ、より厳しい角度制限を適用して安定性を確保します

5. 制御アルゴリズムの最適化

5.1 PIDコントローラー

適応型PID制御システム:

class AdaptivePIDController:
    def __init__(self, base_params=None):
        self.base_params = base_params or {'kp': 0.6, 'ki': 0.1, 'kd': 0.05}
        self.current_params = self.base_params.copy()
        self.error_history = deque(maxlen=20)
        self.output_history = deque(maxlen=10)

    def adaptive_update(self, error, dt):
        """自适应PID更新"""
        self.error_history.append(abs(error))

        # 计算误差统计
        recent_errors = list(self.error_history)[-10:]
        avg_error = np.mean(recent_errors)
        error_trend = self._calculate_trend(recent_errors)

        # 自适应参数调整
        if avg_error > 100:  # 大误差:快速响应
            self.current_params['kp'] = self.base_params['kp'] * 1.3
            self.current_params['kd'] = self.base_params['kd'] * 1.2
            self.current_params['ki'] = self.base_params['ki'] * 0.8
        elif avg_error < 20:  # 小误差:精细调节
            self.current_params['kp'] = self.base_params['kp'] * 0.8
            self.current_params['kd'] = self.base_params['kd'] * 0.9
            self.current_params['ki'] = self.base_params['ki'] * 1.2
        else:  # 正常范围:保持默认
            self.current_params = self.base_params.copy()

        # 基于趋势的额外调整
        if error_trend > 0.5:  # 误差增长趋势
            self.current_params['kd'] *= 1.1  # 增加阻尼
        elif error_trend < -0.5:  # 误差减小趋势
            self.current_params['ki'] *= 1.1  # 增加积分

        return self._standard_pid_update(error, dt)

5.2 ブレ防止の仕組み

多段階のブレ防止戦略:

  1. ハードウェアレベルのブレ防止: 最大角度変化速度を制限
  2. アルゴリズムレベルのブレ防止: 対象切替しきい値と安定フレーム数の要件
  3. 制御レベルのブレ防止: PID出力のフィルタリングと平滑化処理
class AntiJitterController:
    def __init__(self):
        self.output_filter = LowPassFilter(cutoff_freq=2.0)
        self.rate_limiter = RateLimiter(max_rate=30.0)  # 度/秒
        self.deadband_filter = DeadbandFilter(threshold=2.0)

    def apply_anti_jitter(self, raw_output):
        """应用多级防抖动处理"""
        # 1. 死区滤波
        deadband_output = self.deadband_filter.filter(raw_output)

        # 2. 低通滤波
        filtered_output = self.output_filter.filter(deadband_output)

        # 3. 速率限制
        final_output = self.rate_limiter.limit(filtered_output)

        return final_output

5.3 適応的なパラメーター調整

性能フィードバックに基づくパラメーターの自動適応:

class ParameterAdapter:
    def __init__(self):
        self.performance_monitor = PerformanceMonitor()
        self.parameter_history = deque(maxlen=100)

    def adapt_parameters(self, current_performance):
        """基于性能指标调整算法参数"""
        metrics = current_performance

        # 追踪稳定性调整
        if metrics['switch_rate'] > 0.1:  # 切换过于频繁
            self.increase_stability_parameters()
        elif metrics['switch_rate'] < 0.02:  # 可能响应过慢
            self.increase_responsiveness_parameters()

        # 精度调整
        if metrics['tracking_error'] > 15:  # 精度不够
            self.increase_precision_parameters()

        # 响应速度调整
        if metrics['response_delay'] > 100:  # 响应太慢
            self.increase_speed_parameters()

6. アルゴリズムのパラメーター調整ガイド

パラメーター調整の方法論

調整の流れ:

  1. ベンチマークテスト: 性能のベースラインとテストシナリオを確立
  2. パラメーター分析: 重要なパラメーターとパラメーター間の関係を特定
  3. グループ別最適化: 機能モジュールごとにグループ分けしてパラメーターを最適化
  4. 性能検証: 複数のシナリオで最適化の効果を検証
  5. 継続的な監視: 実行時の性能監視と動的な調整

システムの性能は主に以下の重要なパラメーター設定によって決まります。

対象追跡パラメーター

パラメーター 説明 調整の目安
confidence_weight 信頼度の重み 値を大きくすると、信頼度の高い対象が選ばれやすくなります
size_weight 対象サイズの重み 値を大きくすると、大きい対象が選ばれやすくなります
persistence_weight 持続性の重み 値を大きくすると、追跡中の対象の安定性が高まります
position_weight 位置連続性の重み 値を大きくすると、位置の急変による対象切替が減ります
target_switch_threshold 対象切替しきい値 値を大きくすると、対象の切替頻度が減り、安定性が高まります
target_timeout 対象のタイムアウト時間 値を大きくすると、対象が視野外に出た後も記憶される時間が長くなります
max_history_count 最大履歴カウント 値を大きくすると、長期間存在する対象の重みの上限が上がります
max_position_distance 最大位置距離 対象の移動速度に合わせて調整します。大きすぎるとIDの混同が、小さすぎると新規IDの頻繁な作成が起こります
direction_threshold 方向判定しきい値 値を調整すると、方向判定の感度が変わります

カルマンフィルターのパラメーター

パラメーター 説明 調整の目安
dt 時間ステップ システムのフレームレートに合わせて調整します。通常は1/フレームレートです
process_noise_scale プロセスノイズ係数 値を大きくすると対象の変化への追従が速くなりますが、ノイズに敏感になります
measurement_noise_scale 観測ノイズ係数 値を大きくすると観測ノイズへの感度が下がりますが、応答速度が低下します
prediction_time 予測する将来時間 値を大きくすると予測の先行量が増え、より高速に移動する対象に適します
prediction_weight 予測位置の重み 値を大きくすると予測の影響が強まり、小さくすると現在の測定の影響が強まります
max_prediction_distance 最大予測距離 値を調整して予測距離を制限し、過剰な予測を防ぎます

PIDコントローラーのパラメーター

パラメーター 説明 調整の目安
kp 比例係数 値を大きくすると応答速度が上がりますが、大きすぎると振動が発生します
ki 積分係数 値を大きくすると定常偏差が減りますが、大きすぎると積分飽和やオーバーシュートが発生します
kd 微分係数 値を大きくすると減衰が増えて振動が減りますが、大きすぎるとノイズが増幅されます
max_integral 積分上限 値を調整して積分作用の最大影響を制限します
first_update_factor 初回更新の縮小係数 値を小さくすると初回検出時の応答強度が下がり、オーバーシュートが減ります

パラメーター調整は具体的な用途に合わせて行い、対象の運動特性、カメラの動き、画面サイズなどの要素を総合的に考慮してください。高速で移動する対象のシーンでは、予測の重みと先行時間を大きくすることをお勧めします。安定したシーンでは、これらの値を小さくすることで、より滑らかな追跡効果が得られます。

お問い合わせ

資料のダウンロード・技術サポートについては、HumansX株式会社までお問い合わせください。