This commit is contained in:
agomizi1cm committed 2026-08-09 21:41:44 +09:00
commit c5bcb95d74
172 files changed
+9487

No files matched your search

+23
View File
@@ -0,0 +1,23 @@
# 実験チェックリスト
## 実験前
- [ ] カメラ位置を固定し、高さ・角度・サイネージとの位置関係を記録した
- [ ] 通行方向、顔が映る範囲、照明、逆光を確認した
- [ ] 音声ファイル、内容、音量を確認した
- [ ] Prompt / Control条件を確認した
- [ ] `camera_position_note`を入力した
- [ ] GUI起動だけではカメラが起動せず、Start後に映像が出ることを確認した
## 実験中
- [ ] 条件、カメラ位置、音量を途中変更していない
- [ ] 異常、遮蔽、混雑をセッションメモに記録した
## 実験後
- [ ] unified logsとperson_analysis_tableが保存された
- [ ] Phase 8解析とquality checkを実行した
- [ ] not_evaluable/no_pose_estimatedが過剰でない
- [ ] Prompt / Control双方の有効解析人数を確認した
- [ ] pilot reportを生成した
+27
View File
@@ -0,0 +1,27 @@
# 実験環境記録テンプレート
| 項目 | 記録内容 |
|---|---|
| 実験日 | |
| 実験場所 | |
| カメラ製品名 | |
| カメラ設置高さ | |
| カメラ角度 | |
| 解像度 | |
| FPS | |
| サイネージ位置 | |
| 評価領域 | |
| トリガーライン | |
| 照明条件 | |
| 逆光の有無 | |
| 通行方向 | |
| PC仕様 | |
| CPU | |
| GPU | |
| OS | |
| Pythonバージョン | |
| 使用モデル | |
| confidence threshold | |
| image size | |
| 平均FPS | |
| 備考 | |
+26
View File
@@ -0,0 +1,26 @@
# デジタルサイネージ声掛けパイロット実験
- **protocol_id**: protocol_20260809
- **title**: デジタルサイネージ声掛けパイロット実験
- **version**: 0.10.0
- **created_at**: 2026-08-09T21:18:19+09:00
- **purpose**: 音声提示と通行人の顔向き反応を観測する
- **target_location**: laboratory
- **signage_description**: デジタルサイネージ
- **camera_position_description**: サイネージ正面寄り。顔が見える位置に調整する。
- **camera_height_cm**: None
- **camera_angle_description**: 要記録
- **walking_direction_description**: 要記録
- **lighting_condition**: 要記録
- **voice_prompt_text**: こんにちは。こちらをご覧ください。
- **voice_file_path**: assets/audio/prompt.wav
- **voice_volume**: 0.8
- **trigger_strategy**: trigger_line_crossing
- **trigger_line_description**: vertical 0.55
- **response_window_sec**: 3.0
- **turn_weak_threshold_deg**: 20.0
- **face_process_every_n_frames**: 2
- **prompt_condition_rule**: トリガー時に音声を提示する
- **control_condition_rule**: 同じトリガー時刻を記録し音声は提示しない
- **privacy_note**: 顔認証・個人識別は行わず、track_idは実行中だけの一時IDとして扱う。
- **notes**: カメラ位置、照明、通行方向をセッションごとに固定・記録する
@@ -0,0 +1,16 @@
# 中間発表結果テンプレート
## 研究目的
## システム構成
## 実装済み機能
## 実験条件
## パイロット結果
- Prompt/Control有効解析人数
- 反応率と反応率差
- 反応時間
- 最大Yaw変化
## 除外理由とログ品質
## 現時点の課題
## 今後の予定
## 注意
少数サンプルの有意差や因果関係を断定しない。顔未検出を「見ていない」と扱わない。
+29
View File
@@ -0,0 +1,29 @@
# Phase 10 実験運用・品質確認仕様
Phase 10は新しい認識アルゴリズムではなく、本実験前の運用固定、記録、品質確認、中間発表準備を行う。
## 固定すべき条件
カメラ位置・高さ・角度、サイネージ位置、通行方向、照明、顔が映る向き、音声内容・音量、トリガーライン、response window、turn閾値、顔処理頻度を記録する。カメラ位置は主要な実験条件である。
PromptとControlでは音声提示以外を可能な限り同一にする。Controlは音声なしでpseudo prompt時刻を記録する。顔未検出は反応なしではなく評価不能である。
## 生成物
- `experiment_protocol.md/.yaml`: 設定から再現可能な実験条件を生成する。
- セッションメモ: 条件、操作者、位置、照明、問題をUTF-8 YAMLで保存する。
- `quality_issues.csv`, `quality_report.md`: 欠損、条件不足、有効率、評価不能率、Pose欠損、カメラメモ、反応時間、plotsを検査する。
- `pilot_report.md`: Phase 8結果を記述的に整理する。
- `midterm_summary.md`: 発表スライドへ転記しやすいMarkdownを作る。
## CLIとGUI
`protocol`, `quality-check`, `pilot-report`, `presentation-summary`はカメラやYOLOを初期化しない。GUIのQuality & Reportsタブでも別スレッドから同じ処理を呼び出す。
## 品質判定の限界
quality checkはログ品質の目安であり、研究上の妥当性を保証しない。少数サンプルの有意差や因果関係を断定しない。照明、通行方向、カメラ位置、ID switchが結果へ影響する。
## Phase 11
パイロット実験を収集し、品質Issueに基づいてカメラ位置・閾値を調整し、有効解析人数と除外理由を確認する。
+56
View File
@@ -0,0 +1,56 @@
# Phase 11 パイロット実験診断仕様
## 目的
Phase 7統合ログとPhase 8解析結果を用い、本実験へ進めるデータ品質かを診断する。新しい認識アルゴリズムではなく、実データに基づく運用・品質・設定改善支援である。
## 入力
- `*_person_analysis_table.csv`
- `*_session_summary.csv`
- Phase 8解析ディレクトリ
- Phase 10品質Issue
顔向き評価不能と「評価可能だが反応なし」を混同しない。`valid_for_voice_analysis=false`を反応なしへ含めない。
## 診断
Prompt/Controlの総数、有効解析人数、反応率、有効音声解析率、not_evaluable率、no_pose_estimated率、条件人数比、セッション品質、camera_position_noteを確認する。
- `ready`: 両条件が目標人数以上で、各品質閾値、人数バランス、カメラ記録を満たす。
- `needs_minor_adjustment`: 最低人数はあるが目標未達、または条件バランスに軽微な問題がある。
- `needs_major_adjustment`: 有効率、評価不能率、Pose取得率、カメラ位置記録に重大な問題がある。
- `insufficient_data`: 条件欠損、最低人数未満、空データ。
- `error`: 必須列破損等で診断不能。
## 改善提案
ルールを明示し、カメラ位置、顔処理、閾値・response window確認、サンプル数、条件バランス、ログ・プロトコルをhigh/medium/lowで提案する。自動的に設定値を書き換えない。
## セッション比較
セッション単位で有効率、反応率、評価不能率、Pose未推定率、反応時間、カメラ位置メモを集計し、good/caution/poorに分類する。
## 変更履歴
`CalibrationHistory`は変更前後、理由、操作者、関連report IDをUTF-8 BOM CSVへ追記する。同じchange_idは拒否する。
## 出力
- `pilot_diagnostic_report.md`
- `pilot_diagnostic_metrics.csv`
- `improvement_recommendations.csv`
- `session_quality_summary.csv`
- `calibration_history.csv`
## CLI・GUI
`pilot-diagnostics`, `calibration-add`, `calibration-list`はカメラ、YOLO、MediaPipe、音声を初期化しない。GUI Diagnosticsタブも同じ処理をワーカースレッドで実行する。
## 制約
readyは研究デザインの妥当性を保証しない。少数サンプルの有意差は不安定であり、高い反応率も音声との因果関係を証明しない。照明、通行方向、混雑、カメラ位置、ID switchの影響を別途確認する。
## Phase 12
改善履歴を反映して本実験データを収集し、Prompt/Control双方のセッション数・有効人数を確保し、最終解析と報告へ進む。
+7
View File
@@ -0,0 +1,7 @@
# Phase 1 仕様概要
Webカメラまたは動画からフレームを取得し、Ultralytics YOLO(初期値 `yolo11n.pt`)で `person` のみを検出する。各フレームにはBounding Box、信頼度、フレーム内人数、評価領域内人数、FPS、番号、時刻、評価領域、仮想トリガーラインを描画できる。
評価領域は normalized/pixel 座標に対応し、人物の下辺中央点が領域内かを判定する。領域外の検出も破棄しない。CSVには人物ごとに1行を保存し、設定により空フレームも記録する。動画保存は既定で無効である。
Phase 1では追跡、人物ID、通過・ユニーク人数集計、顔ランドマーク、Head Pose、振り向き判定、音声制御、統計解析を行わない。Phase 2では `list[Detection]` をByteTrackベースの追跡器へ渡す予定である。
+69
View File
@@ -0,0 +1,69 @@
# Phase 2 人物追跡仕様
## 1. 目的
フレーム単位のYOLO人物検出を追跡し、1実行内の一時ID、軌跡、領域イベント、トリガー通過、方向、人物単位summaryを生成する。顔推定・振り向き判定・音声制御は対象外である。
## 2. 構成と追跡方式
```text
PersonDetector -> list[Detection] -> PersonTracker -> list[TrackedPerson]
|
v
TrackManager
events / states / counters
```
Ultralytics同梱の `BYTETracker` を使用する。既存依存とバージョンを揃えられ、高信頼検出と低信頼検出の二段階関連付けが遮蔽に有効なためである。内部のResults・トラック型は `tracker.py` の入力アダプタと出力正規化から外へ出さない。
## 3. DetectionからTrackedPersonへの変換
Detectionのxyxy、信頼度、class IDをByteTrack入力へ変換する。出力BBoxを画像内へクリップし、不正Boxとperson以外を除外する。公開IDは整数で、外部tracker IDを実行内で単調増加するIDへ写像する。確定状態、age、missedを独自dataclassへ格納する。
## 4. ByteTrack設定
高・低信頼閾値、新規track閾値、match閾値、buffer、最低確定フレーム、最大miss、score融合をYAMLで設定する。追跡有効時は `skip_frames=0` を要求し、推論を飛ばした検出を再利用しない。
## 5. TrackManager
人物ごとに初回・最終時刻、表示・missフレーム、上限付き軌跡、確定状態、領域・交差イベントを保持する。最大missを超えるとlostとfinalizedを生成し、動画終端、Ctrl+C、通常終了時は全active trackを同じ経路で最終化する。
## 6. 評価領域
足元点を使用する。初回が領域内なら即時進入とする。それ以外の進入と退出は設定数の連続フレームで確定し、同一種類のイベントを重複生成しない。
## 7. トリガーライン
縦線はleft/right、横線はtop/bottomの反対側への移動を検出する。確定track、最低点数、デッドバンド、最小変位を要求し、既定ではIDごとに1回だけ記録する。
## 8. 移動方向
トリガーラインを通過済みで通過方向がある場合、観測済みの `trigger_crossing_direction` を最終的な `movement_direction` として最優先する。これにより、通過後に停止した人物がsummaryでstationaryへ上書きされることを防ぐ。通過方向がない場合のみ、直近 `direction_window_points` の最初と最後の足元点を比較する。支配的な軸と符号から4方向を決め、十分な変位がない場合だけstationary、点不足はunknownとする。
## 9. 人数定義
- Active Tracks: activeかつ確定
- Total Unique Tracks: 実行中に一度でも確定したID
- Region Visitors: 領域進入済み確定ID
- Trigger Crossings: ライン通過済み確定ID
- Completed Passers: 最終化済みで最低表示時間・領域・交差条件を満たすID
## 10. CSV
Phase 1検出CSVに加え、tracking_frames(人物・フレーム単位)、events(イベント単位、metadata JSON)、track_summary(最終人物単位)を `data/logs/tracking` へUTF-8 BOM付きで保存する。summaryはtrack IDごとに重複防止する。
## 11. 例外と停止
初期化失敗はTrackerError、状態管理はTrackManagementError、CSVはTrackingLogErrorの体系を用意する。単一フレームのtracker更新失敗は記録して空出力とし、次フレームを継続する。停止時は最終化、ログ、tracker、camera、writer、windowの順で確実に解放する。一時停止中は取得・追跡・miss・ログ・時刻を進めない。
## 12. テスト
外部モデル不要でdataclass、縦横交差、デッドバンド、重複防止、進入退出ヒステリシス、stale/finalize、方向、集計妥当性、3種CSV、BOM、JSONを検証する。ByteTrack実映像性能は手動評価対象とする。
## 13. 受入・手動評価
同一人物IDの維持、複数ID、遮蔽、進入・退出・交差の一回性、方向、終了summary、カウンタ分離を確認する。シナリオは左右通過、2人並行・交差、遮蔽、ライン停止・往復、浅い領域進入、画面端、再入場、30分運転、CSV整合である。ID switch、fragmentation、誤track、見逃し、実数対システム数、交差誤り、平均・最低FPSを記録する。
## 14. Phase 3への引き継ぎ
`list[TrackedPerson]` のtrack ID、BBox、confidence、領域状態と `TrackState.trajectory` をFaceProcessorへ渡し、`HeadPoseResult(track_id, pitch, yaw, roll)` と対応付ける。追跡IDは顔認証ではなく、再起動・再入場・遮蔽で変わり得る一時IDである。
+72
View File
@@ -0,0 +1,72 @@
# Phase 3 顔向き推定仕様
## 推奨依存環境
MediaPipeとNumPy/OpenCVの要件衝突を避けるため、Phase 3の推奨・固定環境は `mediapipe==0.10.21`、`numpy==1.26.4`、`opencv-contrib-python==4.11.0.86` の組み合わせとする。`opencv-contrib-python` が通常の `cv2` APIも提供するため、`opencv-python` は同じ仮想環境へ導入しない。既存環境に両方が存在する場合は、関連する4パッケージをアンインストールしてから `requirements.txt` を再インストールする。
## 1. 目的と構成
Phase 2の `TrackedPerson` ごとに顔ランドマークと近似Head Poseを取得し、track ID、frame、時刻に対応付ける。Phase 4の基準Yaw・振り向き判定の入力基盤であり、本Phaseでは判定・音声・反応時間を扱わない。
```text
TrackedPerson -> FaceROI -> FaceProcessor(MediaPipe) -> FaceLandmark
|
v
HeadPoseEstimator(solvePnP)
|
v
HeadPoseResult -> FaceTrackManager -> CSV / display
```
## 2. FaceROI
人物Box上端から `roi_height_ratio`(既定0.45)までを候補とし、候補の幅・高さを `roi_expand_ratio` だけ拡張して画像内へクリップする。最小寸法、確定track、評価領域条件で除外する。面積の大きい領域内人物を優先し、1フレームの最大処理人数を制限する。
## 3. MediaPipe Face Mesh
各ROIをBGRからRGBへ変換してFace Meshへ渡す。複数顔の場合はROI中心に最も近い顔を採用する。正規化されたROI座標をフレーム全体のpixel座標へ変換し、MediaPipe型を外へ漏らさない。例外や未検出はtrack単位のfailure resultに変換する。
## 4. 使用ランドマークとHead Pose
MediaPipe index 1(nose tip)、152(chin)、33/263(左右目尻)、61/291(左右口角)を使う。顔の上下・左右へ広く分布し、一般的な6点solvePnP近似と対応しやすいためである。簡易3Dモデルの単位は任意で、相対形状が重要である。モデルのY軸はOpenCV画像座標と同じ下向きを正とし、正面顔が約180°回転として解かれる座標系不一致を避ける。
OpenCV `solvePnP` と `Rodrigues` で回転行列を求め、X/Y/Z回転をPitch/Yaw/Rollとしてdegreeで返す。本実装上、正のPitchはX軸正回転、正のYawはY軸正回転、正のRollはZ軸正回転である。ただし画像座標、カメラ設置、鏡像反転によって直感的な左右・上下と符号が一致しない場合がある。
顔平面の軸反転によるsolvePnPの等価解では、直立した正面顔でもRollが±180°付近になることがある。本研究では通常の直立した通行人を対象とするため、Rollを軸方向として `[-90°, 90°)` の等価表現へ正規化する。例えば -170°は10°、170°は-10°として扱う。上下逆さの顔を区別する用途にはこの正規化を使用できない。
## 5. カメラ行列の近似と制約
焦点距離をframe width、主点を画像中心、歪み係数をゼロとする。カメラキャリブレーションを行わないため絶対角度には系統誤差があり、同一条件下の変化量を優先する。Phase 4前に実機で符号と基準値を確認する。
## 6. 平滑化と頻度制御
推定成功値をtrack ID別EMA(既定alpha 0.4)で平滑化し、失敗時は更新しない。`process_every_n_frames=N` はNフレームごとに処理し、間引きフレームはface CSVへ書かず画面では直近値を使う。`max_persons_per_frame` でCPU負荷を制御する。
## 7. 状態とログ
`FaceTrackManager` は処理対象フレーム、顔検出・pose成功数、成功率、最新角度、Yaw最小・最大・平均、上限付き時系列を保持する。
- `face_frames.csv`: frame、track ID、成否、角度、landmark数、ROI、失敗理由
- `face_summary.csv`: track別成功率、Yaw統計、最終角度、有効性
UTF-8 BOM付きで、summaryはtrack IDごとに一度だけ出力する。
## 8. 表示
track付近へYaw/Pitch/RollまたはFace NG、FaceROIを表示する。全ランドマーク表示は負荷を考慮して既定false。左上にface enabled、Face OK、Pose OKを表示する。無効時もPhase 1・2描画を維持する。
## 9. 例外・無効状態
`roi_too_small`、`face_not_detected`、`insufficient_landmarks`、`solvepnp_failed`、`angle_out_of_range`、`mediapipe_error` を結果で区別する。真横付近の近似誤差を許容する既定上限は120°とする。範囲外でも計算済みraw角度はCSVと画面へ残し、符号・閾値調整に利用する。face無効・処理間引きは結果とCSV行を生成しない。tracker無効時はtrack IDを安定管理できないためfaceを自動無効化し、実行ログに警告する。フレーム単位の失敗は検出・追跡を停止させない。
## 10. テスト
実モデルなしでROI比率・拡張・クリップ・除外、モデル型、成功率とYaw統計、カメラ行列、点不足、Euler変換、角度範囲、EMA用状態、CSV/BOM/失敗行/summary重複を検証する。MediaPipeは遅延importし、標準pytestは未導入環境でも実推論を要求しない。
## 11. 実機確認
正面、右、左、上、下、首傾斜について角度と符号を記録する。通行中track IDとの対応、顔なし人物、複数人、最大処理人数、face CSV、CPU平均・最低FPSを確認する。右・左Yawが逆方向へ変化すること、上下Pitch、傾斜Roll、正面安定性を重点評価する。
## 12. Phase 4への引き継ぎ
安定提供する値はtrack ID、frame、timestamp、face/pose成否、Pitch/Yaw/Roll、failure reason、顔検出率、pose推定率である。Phase 4はrecent historyから基準Yaw、変化量、振り向きレベル、開始・最大・継続時間、品質除外を算出する。
+72
View File
@@ -0,0 +1,72 @@
# Phase 4 振り向き判定仕様
## 1. Phase 4の目的
track ID付きHead PoseのYaw時系列から、サイネージ方向への顔向き変化、継続時間、強度、評価可否を算出する。音声提示や声掛け後反応はPhase 5の対象である。
## 2. システム構成
```text
HeadPoseResult -> TurnDetector -> TurnFrameResult / TurnEvent / TurnTrackState
TrackManager finalize ---------> TurnTrackManager -> summary
```
## 3. HeadPoseResultからTurnFrameResultへの変換
有効な `HeadPoseResult` をtrack ID別の状態へ入力し、baseline、現在Yaw、raw delta、サイネージ方向delta、candidate、confirmed、levelを持つ `TurnFrameResult` へ変換する。顔処理を間引いたフレームではTurn更新もframeログも行わない。
## 4. サイネージ方向Yawの定義
`positive` は `current - baseline`、`negative` は `baseline - current` をサイネージ方向deltaとし、サイネージへ向く変化を正に統一する。カメラ・鏡像設定ごとに実機で符号を確認する。
## 5. 基準Yaw取得
既定 `first_valid` はwindow内の最初の有効Yawを最低3点集め中央値とする。`before_trigger` はトリガー通過前だけ、`region_entry_window` は領域進入後の指定windowだけ収集する。中央値で瞬間ノイズを抑える。Phase 5で声掛け前windowを追加可能な状態構造とする。
## 6. 振り向きレベル分類
10/20/35/50°をsubtle/weak/medium/strong境界とする。weak以上を主判定とし、subtleは補助反応として保持する。最大delta、発生frame/time、最強levelをtrack単位で保持する。
## 7. 継続時間条件
weak以上は0.30秒、subtleは0.20秒の継続を要求する。elapsed timeで測り、0.30秒以内のpose gapは継続、超過時はcandidateを終了する。
## 8. 顔検出不能ケースの扱い
顔未検出は「振り向きなし」ではない。no face、no pose、baselineなし、sample不足、顔・pose成功率不足をsummaryの除外理由として区別し、`not_evaluable` とする。評価可能で未確定の場合のみ `evaluable_no_turn` とする。
## 9. face_appeared補助イベント
一定時間顔/poseが得られなかった後の有効poseは `face_appeared` 補助イベントとするが、単独ではconfirmedにしない。
## 10. TurnDetector状態管理
TurnDetectorは上限付きYaw/baseline履歴、candidate開始、最終確認、最大delta、最強level、成功率を管理する。イベントはbaseline acquired、face appeared、candidate started、confirmed、level changed、lost、track finalized。confirmedイベントとsummaryはtrack ID単位で重複防止する。
## 11. TurnLogger CSV仕様
- `turn_frames.csv`: frameごとのbaseline、Yaw、delta、candidate、confirmed、level、失敗理由
- `turn_events.csv`: 状態遷移とUTF-8 JSON metadata
- `turn_summary.csv`: 人物単位の成功率、baseline、最大delta、時刻、level、評価可否
すべてUTF-8 BOM付きで、summaryはtrack ID単位に重複を防ぐ。event metadataは `ensure_ascii=False` のJSONで保存する。
## 12. 画面表示
人物付近にTurn levelとdelta、左上に評価可能数、confirmed、subtle、weak+を表示する。評価不能は `Turn:N/A`。一時停止中は状態・時刻・CSVを更新しない。
## 13. 例外処理
tracker、face、head poseのいずれかが無効ならTurnを自動無効化してPhase 1〜3を継続する。顔・pose失敗は評価不能結果として扱い、追跡処理を停止しない。ログI/Oエラーは `TurnLogError` として既存例外体系へ統合する。
## 14. テスト
純粋な合成HeadPoseResultで符号、全境界、中央値baseline、継続、短/長gap、最大delta、イベント一回性、face appeared、評価不能、全CSV/BOM/JSON/summary重複を検証する。実モデル例外は既存FaceProcessorで結果化され、Turnは評価不能として扱う。
## 15. 実機確認手順
静止状態で正面・サイネージ・反対方向を向き、符号を確定する。通過では非注視、軽い/明確/瞬間反応、最初から注視、左右両方向、複数人、face appearedを試す。signage方向、baseline、current、delta、level、confirmed、顔・pose率、除外理由を記録する。
## 16. Phase 5への引き継ぎ
安定インターフェースはtrack ID、baseline/current/delta、level、confirmed、turn start/confirmed time、最大delta、face appeared、分析可否、除外理由である。Phase 5は音声提示時刻を追加し、提示前baselineと提示後response latencyを計算する。
+89
View File
@@ -0,0 +1,89 @@
# Phase 5 音声声掛け制御仕様
## 1. Phase 5の目的
一時track IDに対して再現可能な位置で音声提示またはpseudo promptを行い、その後の振り向き観測を保存する。統計的因果推論は対象外とする。
## 2. システム構成
`TrackEvent + TrackedPerson + TurnFrameResult -> VoicePromptController -> AudioPlayer / VoiceLogger` と接続する。外部pygame型はAudioPlayer内だけで扱う。
## 3. AudioPlayer
pygameを遅延importし、Soundを非同期再生する。disabled/noop、ファイル欠落、初期化・再生失敗はFalseとして継続する。overlapはskip(既定)、restart、allowを選べる。
## 4. VoicePromptController
track別eligibility、prompt実行、response window、反応、最終summaryとイベント重複防止を管理する。
## 5. VoicePromptMode
`prompt`、`control`、`disabled`を独自Enum・文字列で表し、CSVにも同じ値を保存する。
## 6. prompt / control / disabled
promptは音声再生成功時を開始点とする。controlは無音のpseudo promptを同じ開始点として記録する。disabledはcontrollerとvoice CSVを生成しない。
## 7. 声掛け条件
trigger line crossing(既定)、region entry、fixed position、first confirmed trackを選べる。
## 8. trigger_line_crossingの仕様
Phase 2の `trigger_crossed` eventを使用する。一定位置で発生し、実験条件を揃えやすいため既定とする。
## 9. fixed_x_positionの仕様
foot x/yがpixel閾値以上(increasing)または以下(decreasing)で候補となる。one-prompt制約で連続発火を防ぐ。
## 10. 声掛け対象条件
confirmed、領域内、非stale、最低track age、未prompt、未turnを設定に応じて要求する。skip理由もdecision/eventへ残す。
## 11. 重複声掛け防止
既定では同じtrack IDのprompt attemptまたはpseudo prompt後は再実行しない。track IDは個人識別ではなく、ID switch時は別trackになり得る。
## 12. 全体クールダウン
成功promptまたはpseudo promptから既定3秒は別trackへの開始を抑止する。残り時間を画面表示する。
## 13. 反応観測ウィンドウ
開始後3秒以内のweak以上の確定turnをresponseとし、elapsed time差をreaction timeとする。期限超過時はexpired eventを一度出す。
## 14. Phase 4 Turnとの接続
delta最大値、最終level、confirmed時刻をtrack IDで関連付ける。subtleとface appearedは補助情報であり主responseではない。
## 15. response_detected判定
window内の `turn_confirmed` かつweak/medium/strongを必要とする。声掛け後の観測であって因果関係の断定ではない。
## 16. controlモードの解析上の意味
同位置相当からの自然振り向きを観測し、prompt条件との比較開始点を揃える。音声は一切再生しない。
## 17. VoiceLogger CSV仕様
decisions、events、summaryをUTF-8 BOMで保存する。metadataは `ensure_ascii=False` JSON、summaryはtrack ID単位で重複排除する。
## 18. 画面表示
人物付近へwaiting/played/control/failed、左上へmode、prompt数、response数、cooldownを表示する。
## 19. 例外処理
音声欠落・pygame失敗はアプリを停止しない。tracker無効時はVoiceを無効化する。Turn無効時もprompt可能だが分析は `turn_disabled` とする。
## 20. テスト
実音声を鳴らさずmock backend/playerでload、overlap、prompt/control/failure、重複、cooldown、response、expiry、CSV BOM/JSON/dedupを検証する。
## 21. 実機確認手順
音声を `assets/audio/prompt.wav` に置き、promptでライン通過・音量・cooldown・一回制限、controlで無音pseudo event、見る/見ない場合のresponse/expiry、欠落ファイル時の継続を確認する。音声内容・音量・再生機器を固定し、周囲とプライバシーへ配慮する。
## 22. Phase 6への引き継ぎ
track ID、mode、eligibility、prompt/pseudo時刻、window、response、reaction time、response level、最大delta、分析可否・除外理由を安定して提供する。Phase 6は人物状態遷移と実験セッション管理を追加する。
+61
View File
@@ -0,0 +1,61 @@
# Phase 6 人物状態管理仕様
## 1. Phase 6の目的
Phase 2〜5に分散する人物情報をtrack ID単位の実験状態と最終summaryへ統合する。個人識別は行わない。
## 2. システム構成
`Track / Face / Turn / Voice outputs -> PersonStateManager -> Snapshot / Event / Summary -> PersonStateLogger`。既存managerと既存CSVは維持する。
## 3. PersonStateManager
各出力をtrack IDで対応付け、累積フラグ、現在status、遷移イベント、最終summaryを生成する。終了時は残trackを必ずfinalizeする。
## 4. PersonExperimentStatus
new、tracked、inside_region、eligible、prompted、pseudo_prompted、observing_response、responded、no_response、completed、excluded、not_evaluable、lostを定義する。
## 5. PersonExclusionReason
tracker/voice/turn disabled、no face/pose、baseline/sample/rate不足、not eligible、already turned、prompt/audio failure、short track、ID switch疑い、prompt前/観測中lost、outside region、unknownを統一語彙とする。
## 6. 状態遷移ルール
通常はnew→tracked→inside→eligible→prompted/pseudo→observing→responded/no_response→completed。表示statusはexcluded、completed、lost、responded、no_response、observing、prompt、eligible、not evaluable、inside、tracked、newの優先順とする。responseフラグはlost後も失わない。
## 7. 除外理由の統一
Turn/Voiceのfinal reasonを共通Enumへ正規化する。最低duration、trigger要件、eligibility要件もfinalize時に評価する。not evaluableをexcludedへ含めるかは設定可能で、既定false。
## 8. Track / Face / Turn / Voiceとの連携
TrackEventから領域、line、lost、方向、HeadPoseResultからface/pose、Turnからlevel/confirmed/delta/validity、Voiceからeligibility、prompt、window、response、reaction timeを取り込む。
## 9. prompt/controlモードとの関係
promptはprompted、controlはpseudo_promptedとなるが、その後は共通のobserving/responded/no_response遷移を使う。
## 10. PersonStateLogger CSV仕様
frames、events、summaryの3 CSVをUTF-8 BOMで追加保存する。metadataは日本語保持JSON、summaryはtrack ID単位で重複排除する。
## 11. 画面表示
人物付近に短縮State、左上にtracked/eligible/prompted/observing/responded/excludedの現在数を表示する。
## 12. 例外処理
tracker無効時はPerson Stateを警告して無効化する。face/turn/voice無効時も人物追跡自体は継続し、対応値と統一理由へ反映する。ログI/Oは独自例外とする。
## 13. テスト
実モデルなしでEnum、優先規則、除外、Track/Face/Turn/Voice統合、prompt/control遷移、finalize、CSV BOM/JSON/dedupを検証する。
## 14. 実機確認手順
promptではtracked→inside→eligible→prompted→observing→response/no response→completed、controlではpseudo経由の同型遷移を確認する。無効化時はperson-state CSVが生成されないことも確認する。
## 15. Phase 7への引き継ぎ
track ID、status/previous status、event type、exclusion、voice mode、prompt/pseudo、response/reaction、turn level/confirmed、Turn/Voice分析可否を安定して提供し、Phase 7の時系列統合イベントへ渡す。
+55
View File
@@ -0,0 +1,55 @@
# Phase 7 統合イベント・解析テーブル仕様
## 1. Phase 7の目的
既存ログを維持し、イベント、人物解析行、セッション集計、整合性issueをPhase 8向けに追加する。因果関係は断定しない。
## 2. システム構成
Track/Turn/Voice/Person State event→UnifiedEventBuilder→Logger。PersonStateSummary→AnalysisTableBuilder→SessionSummaryBuilder/ConsistencyChecker。
## 3. UnifiedEvent
experiment/session/event ID、source、track/frame/time、人物・Voice・Turn・response・除外・severity・JSON metadataを固定列で持つ。
## 4. UnifiedEventBuilder
既存イベントをsource付きschemaへ変換し、session/frame/source/sequence形式の衝突しにくいIDを生成する。elapsed/frame/sourceで安定ソートし、important onlyにも対応する。
## 5. UnifiedEventLogger
4 CSVをUTF-8 BOMで保存し、event ID、track分析行、session summaryの重複を防ぐ。metadataは `ensure_ascii=False` JSON。
## 6. AnalysisTableBuilder
Person State summaryを中心にprompt/control/disabled共通の人物解析行を生成する。Turn falseとTurn評価不能を別列で保持する。
## 7. SessionSummaryBuilder
track数、除外、分析可能数、prompt/pseudo、response、reaction平均・中央値、Turn level、FPS、issue数を集計する。
## 8. LogConsistencyChecker
promptなしresponse、負reaction、turnなしresponse、windowなしprompt、不正pseudo mode、unknown condition、理由なしexcluded、重複summaryをwarning化し停止しない。
## 9. CSV仕様
`unified_events`、`person_analysis_table`、`session_summary`、`log_consistency_issues`を `data/logs/unified` に追加する。既存CSVは置換しない。
## 10. response_rate定義
`response_detected_count / valid_voice_analysis_tracks`。分母0では空値(None)。全trackや評価不能者を分母へ入れない。
## 11. 顔向き評価不能の扱い
`turn_confirmed=false AND valid_for_turn_analysis=true`は評価可能な非反応、`valid_for_turn_analysis=false`は評価不能として分離する。
## 12. prompt / control比較
prompt condition、prompt played、pseudo prompt、window、response、reaction、Turn、validityを同一列で保存する。
## 13. camera_position_note
設定またはCLIから人物解析行とsession summaryへ保存する。カメラ位置、サイネージとの角度、顔可視性を記述する。
## 14. 既存ログとの関係
Detection、Tracking、Face、Turn、Voice、Person Stateログはすべて維持する。face frameは既定でunified eventへ入れない。
## 15. 例外処理
unified無効時はPhase 6相当。person state無効時は解析表を生成せずevent統合だけ可能。tracker無効時は人物解析不能の警告対象となる。
## 16. テスト
実モデルなしで4モデル、各source変換、stable sort/filter、prompt/control/disabled行、分母、平均/中央値、issue、4 CSV/BOM/JSON/dedupを検証する。
## 17. 実機確認手順
prompt/control双方でcamera noteを指定し、該当イベント、condition、reaction、集計を確認する。正常時issueが重大でないこと、無効時にunified CSVが出ないことを確認する。
## 18. Phase 8への引き継ぎ
session ID、condition、prompt/pseudo、response/reaction、Turn level/delta、分析可否、status、excluded/reasonとsession response rateを安定して提供する。
+38
View File
@@ -0,0 +1,38 @@
# Phase 8 統計解析仕様
## 1. Phase 8の目的
Prompt/Controlの観測反応率、反応時間、Yaw変化を基本統計・検定・効果量で比較する。因果関係は断定しない。
## 2. 入力データ仕様
単一または再帰探索した複数の `person_analysis_table.csv`。session summaryもloaderで読込可能。
## 3. 解析対象の定義
主反応解析は `valid_for_voice_analysis=True` のみ。数値欠損は各metricから除く。
## 4. prompt/control条件
`prompt_condition`がprompt/controlの行を同一schemaで比較する。disabled/unknownは主比較外。
## 5. response_rate定義
response count / valid voice analysis count。分母0はNone。
## 6. 顔向き評価不能の扱い
分析不能をno responseへ混ぜない。件数はcondition summaryと除外集計へ残す。
## 7. 条件別summary
全件、valid、response/no response、率、除外、reaction/Yaw記述統計、Turn levelを出力する。
## 8. 反応率検定
autoは期待度数5未満でFisher、それ以外で2x2カイ二乗。率差、odds ratio、φを併記する。
## 9. reaction_time_sec比較
response detected行のみをMann–Whitney U(既定)またはWelch tで比較する。
## 10. max_yaw_delta比較
valid turn、valid voice、全non-nullの分母設定から選択し、同じ数値検定を行う。
## 11. turn_level分布
none、face appeared、subtle、weak、medium、strong、not evaluableを条件別集計する。
## 12. 除外理由集計
条件内全件を分母にreason別count/ratioを保存する。
## 13. 出力CSV仕様
condition、response test、numeric、Turn distribution、exclusion、run summaryの6表をUTF-8 BOMで保存する。
## 14. グラフ出力
matplotlib Aggで反応率bar、reaction/Yaw box、Turn分布、除外理由を英語ラベルPNGへ保存する。空データでも停止しない。
## 15. CLI
`python main.py analyze --input data/logs/unified --output data/analysis`。解析経路はApplicationをimportしない。
## 16. テスト
読込・型変換・必須列、検定選択、空標本、分母、summary、CSV BOM、overwrite、Agg plotを合成データで検証する。
## 17. 結果解釈の注意
p値は因果を証明しない。小標本ではFisherを使い効果量を併記する。session ID、カメラ位置、trigger条件が異なるデータを無批判に混ぜない。
## 18. Phase 9への引き継ぎ
6 CSVと5 PNGを安定した結果閲覧・ファイル選択GUIへ提供する。
+64
View File
@@ -0,0 +1,64 @@
# Phase 9 GUI仕様
## 目的と構成
Phase 1〜8の実験実行、条件設定、映像確認、状態監視、ログ確認、統計解析をWindows向けローカルGUIから操作できるようにする。GUIは研究用プロトタイプであり、既存CLIを置き換えない。
`MainWindow`は表示、`ExperimentController`は既存`Application`のワーカースレッド実行、`AnalysisController`はPhase 8の`run_analysis_cli`実行を担当する。カメラ、YOLO、各Phaseの処理やロガーはGUIへ複製しない。
## MainWindowと各パネル
- Experiment: camera/video、Prompt/Control/Disabled、音声、音量、顔処理頻度、Yaw方向、統合ログを設定する。
- Preview: OpenCV BGR画像をRGBへ変換し、縦横比を維持して表示する。
- Status: FPS、frame、active/total tracks、crossings、prompt/pseudo prompt/response、turn、ログ場所を表示する。
- Logs: 開始・終了、解析状態、警告、例外を表示する。
- Analysis: 入出力、再帰検索、グラフ、Fisher/カイ二乗、Mann–Whitney/Welch tを設定する。
GUI起動直後にはカメラとYOLOを初期化せず、Start後にだけ`Application`を生成する。
## ExperimentController
GUI入力をdefault YAML、experiment YAMLの後に最優先上書きとしてマージする。Applicationの二重起動を拒否し、start/stop/pause/resumeを協調的に制御する。プレビューは`gui.preview_max_fps`で間引く。
## AnalysisController
Phase 8解析を別スレッドで実行し、カメラやYOLOを初期化しない。完了時に生成ファイル一覧を返す。実験終了後の自動解析も選択できる。
## Application連携とRuntimeMetrics
`Application`へ描画済みフレームと`RuntimeMetrics`の任意コールバックを追加した。CLI時は未指定なので従来動作を維持する。`RuntimeMetrics`はframe、elapsed time、FPS、追跡数、訪問・通過数、顔検出数、振り向き数、音声条件、prompt/pseudo/response数、人物状態内訳、ログ場所を保持する。
## スレッドと停止
映像処理と統計解析はGUIスレッド外で実行する。Widget更新はQt Signal/SlotでGUIスレッドに戻す。Stopは`Application.request_stop()`を呼び、既存finally処理がsummary確定、logger close、Face/Audio/Tracker close、Camera/VideoWriter release、OpenCV window破棄を行う。finalizeに数秒かかる場合がある。
## 入力検証
camera indexは0以上、volumeは0〜1、face interval/max personsは1以上、動画入力は既存ファイル必須、voice modeはprompt/control/disabled、Yaw方向はpositive/negativeとする。Promptで音声が未指定または存在しない場合は警告する。
## 結果を開く機能
Windowsでは`os.startfile`、macOS/Linuxでは標準ファイルマネージャーを使用する。解析結果一覧のダブルクリックで保存場所を開く。
## テスト
GUI非依存モデル、入力検証、mock Applicationによる開始・停止・一時停止、mock解析runner、BGR→RGB変換をテストする。PySide6がない環境ではQt依存テストのみskipするため、カメラを起動しない。
## 手動確認
1. `python main.py gui`で起動し、Start前にカメラLEDとYOLOロードが始まらないこと。
2. Promptで音声を選択し、通過、prompt count、response count、Stop後の統合ログを確認する。
3. Controlで音声が鳴らずpseudo prompt countが増えることを確認する。
4. 動画入力、pause/resume、プレビュー、状態表示を確認する。
5. Analysisから`data/logs/unified`を解析し、CSVとplotsを生成・表示できることを確認する。
## 既知の制約
- 実験前にCLIでも実機動作を確認する。
- CPU環境ではプレビューによりFPSが低下する可能性があり、表示FPSと処理FPSは一致しないことがある。
- GUIはID switch、顔認証、個人識別を解決しない。
- 統計結果は因果関係を直接証明しない。
## Phase 10への引き継ぎ
`GuiExperimentRequest`、`GuiAnalysisRequest`、`RuntimeMetrics`、Controllerのstart/stop/pause/resumeと完了コールバックを安定インターフェースとして、実験プロトコル、条件ローテーション、チェックリスト、品質確認を追加できる。
+10
View File
@@ -0,0 +1,10 @@
# パイロット実験計画
目的は、本実験前にカメラ位置、顔向き取得率、音声提示、ログ品質を確認することである。通行人の観測であり、顔認証や個人識別は行わない。
- 場所、サイネージ、カメラ位置を固定する。
- Promptはトリガー時に音声を提示する。
- Controlは同じトリガー時刻を記録し、音声を提示しない。
- 目安として各条件で有効解析人数20人以上を収集する。本実験の正式なサンプルサイズ設計ではない。
- track、条件、反応、反応時間、Yaw、除外理由、照明、通行方向、異常を記録する。
- カメラ位置変更、音声異常、ログ欠損時は中止して記録する。