インテリジェント追跡アルゴリズムの詳細説明
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.0 - min(現在位置から前回位置までの距離 / 最大位置距離, 1.0)
- 現在ターゲットのボーナス:現在追跡中のターゲットであれば、追加のスコアボーナス(ターゲット切り替えしきい値と同値)が加算されます。
2.2 ターゲット関連付けアルゴリズム
ターゲット関連付けアルゴリズムは、現在のフレームで検出されたターゲットと履歴上のターゲットとの対応関係を確立し、ターゲットIDの持続的な追跡を実現する役割を担います。
関連付けの手順
- 距離行列の計算 :
- 現在のフレームの各ターゲットと、履歴上の各ターゲットとのユークリッド距離を計算します
- 距離行列 D[i, j] は、現在のフレームの i 番目のターゲットと履歴上の j 番目のターゲットとの距離を表します
- 最近傍マッチング :
- 現在のフレームの各ターゲットについて、未割り当ての履歴ターゲットの中から最も近いターゲットを探します
- 見つかった最短距離が最大位置距離のしきい値より小さければ、マッチング成功とみなします
- マッチングに成功したら、履歴ターゲットの位置やタイムスタンプなどの属性を更新します
- 位置連続性スコアを計算します:
position_score = 1.0 - min(min_distance / max_position_distance, 1.0)
- 新規ターゲットの作成 :
- 現在のフレームのターゲットがどの履歴ターゲットともマッチしない場合、新しいターゲットIDを作成します
- 新規ターゲットのカウント、位置、タイムスタンプなどの属性を初期化します
2.3 ターゲット切り替え戦略
短期的なスコアの変動によって追跡ターゲットが頻繁に切り替わるのを防ぐため、アルゴリズムには一連のターゲット切り替え戦略が実装されています。
- 新たに最高スコアのターゲットが現れても即座には切り替えず、現在追跡中のターゲットと比較します
- 新しいターゲットのスコアが現在のターゲットのスコアを切り替えしきい値(
target_switch_threshold)以上上回った場合にのみ、ターゲットを切り替えます - それ以外の場合は、新しいターゲットのスコアがわずかに高くても現在のターゲットの追跡を続け、追跡の安定性を保ちます
この戦略は「ヒステリシスコンパレータ」(hysteresis comparator)に似ており、スコアのわずかな変動による頻繁なターゲット切り替えを効果的に防ぐことができます。
2.4 ターゲットのライフサイクル管理
システムを効率よく稼働させ、メモリリークを防ぐため、アルゴリズムには完全なターゲットライフサイクル管理の仕組みが実装されています。
ターゲットの状態遷移
新检测 → 候选目标 → 确认目标 → 稳定追踪 → 丢失检测 → 超时清理
↓ ↓ ↓ ↓ ↓ ↓
创建ID → 初始评分 → 正式追踪 → 持续更新 → 预测补偿 → 资源释放
ライフサイクル管理ポリシー
- 新規ターゲットの検証期間(0〜3フレーム):
- 連続検出による検証で、誤検出ノイズを排除します
- 初期位置と動きのパラメータを推定します
- 既存ターゲットとの関連性をチェックします
- 安定追跡期間(3フレーム〜タイムアウト):
- 通常のスコア更新と位置予測
- 動きのパラメータを継続的に最適化
- 追跡品質をリアルタイムに評価
- ロスト回復期間(検出喪失〜タイムアウト前):
- 動き予測に基づく位置推定
- スコアの重みを下げつつIDは保持
- 再関連付けの仕組みを準備
- タイムアウト時のクリーンアップの仕組み :
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 座標系の定義
本システムは多層の座標系を用いて、正確な位置計算と制御を実現しています。
画像座標系
原点: (0, 0) 位于图像左上角
X轴: 向右为正方向,范围 [0, 640]
Y轴: 向下为正方向,范围 [0, 480]
单位: 像素 (pixel)
相対座標系
原点: (0, 0) 位于图像中心 (320, 240)
X轴: 向右为正,范围 [-320, +320]
Y轴: 向上为正,范围 [-240, +240]
单位: 像素 (pixel)
雲台座標系
水平轴 (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,1] の範囲の正規化座標を提供します
- 極座標表現:直交座標と極座標の両方の表現を提供します
- 境界チェック:境界ケースや外れ値を自動的に処理します
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つの主要なステップで構成されます。
- 予測ステップ :
- 前の時刻の状態と状態遷移行列に基づいて現在の状態を予測します
- 状態共分散行列を更新します
X_pred = F * X
P_pred = F * P * F^T + Q
- 測定更新ステップ :
- カルマンゲインを計算します
- 測定値に基づいて状態推定を更新します
- 共分散行列を更新します
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 運動モデルと予測
ターゲット位置予測機能により、ターゲットが消失したり高速で移動したりした場合でも、過去の動きのパターンからターゲットの将来位置を予測でき、追跡の連続性と安定性が向上します。
予測の仕組み
- 速度推定 :
- カルマンフィルタがターゲットの速度ベクトル(vx, vy)を継続的に推定します
- 速度情報はターゲットの履歴に保存され、以降の予測に使用されます
- 位置予測 :
- ターゲットを見失った場合、最後に推定された速度と位置を用いてターゲットの現在位置を予測します
- 予測式:predicted_position = last_position + velocity * dt
- 予測位置からターゲットのバウンディングボックスを再構築します
- 予測信頼度の減衰 :
- 予測位置でターゲットを更新するたびに、予測の信頼度を下げます
- 信頼度がしきい値を下回ったら予測を停止し、存在しないターゲットを長時間追跡し続けることを防ぎます
- 予測距離の制限 :
- 予測距離が最大予測距離を超えないよう制限し、過剰な予測による追跡のずれを防ぎます
- 距離制限を超えた場合は、予測位置をスケーリングします
4.3 予測制御戦略
サーボ予測制御は、ターゲットの動き予測とサーボ制御を組み合わせることで、高速移動するターゲットを先回りして追跡し、システム遅延の影響を低減します。
制御戦略
- 先行制御 :
- 高速移動するターゲットに対しては、速度に応じて先行量を計算します
- サーボはターゲットの現在位置ではなく、予測された将来位置に向けて照準を合わせます
- 動的な重み調整 :
- 速度が大きいほど、予測位置の重みを大きくします
- 動的重みの計算:dynamic_weight = min(base_weight * velocity_magnitude / threshold, max_weight)
- 位置の融合 :
- 現在の測定位置と予測位置を重み付きで融合します
- 融合式:final_position = current_position * (1 - weight) + predicted_position * weight
- 予測追跡の継続 :
- ターゲットを一時的に見失っても、データの有効期限が切れて間もない場合は、速度情報を用いて予測追跡を継続します
- 安定性を確保するため、応答速度を下げ、より厳しい角度制限を適用します
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 揺れ防止の仕組み
多段階の揺れ防止戦略 :
- ハードウェアレベルの揺れ防止:角度変化の最大速度を制限します
- アルゴリズムレベルの揺れ防止:ターゲット切り替えしきい値と安定フレーム数の要件を設けます
- 制御レベルの揺れ防止 :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. アルゴリズムのパラメータチューニングガイド
パラメータチューニングの方法論
チューニングの流れ :
- ベンチマーク :性能のベンチマークとテストシナリオを確立します
- パラメータ分析 :主要パラメータとパラメータ間の関係を特定します
- グループ別最適化 :機能モジュールごとにグループ分けしてパラメータを最適化します
- 性能検証 :複数のシーンで最適化の効果を検証します
- 継続的な監視:実行時の性能を監視し、動的にチューニングします
システムの性能は、主に以下の主要パラメータの設定に左右されます。
ターゲット追跡パラメータ
| パラメータ | 説明 | 調整のヒント |
|---|---|---|
confence_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株式会社までお問い合わせください。
ドキュメント