OCR表示安定化をバッファ方式から追跡方式(OcrTextTracker)へ置き換え#648
Conversation
|
@copilot 説明とタイトルを日本語で記載して。 |
タイトルと説明を日本語に更新しました。バッファ関連設定の削除だけでなく、OCRテキスト追跡を |
There was a problem hiding this comment.
Pull request overview
本PRは、従来のフレームバッファ方式(OcrBufferFilter)を廃止し、OCR直後にテキスト領域を継続追跡して安定化する方式(OcrTextTracker)へ置き換えることで、OCR表示の安定性と性能を改善しつつ、不要になった設定項目・リソースを整理し、追跡品質をテストで担保する変更です(Issue #643対応)。
Changes:
OcrBufferFilterを削除し、IOcrTextTracker/OcrTextTrackerを追加して OCR 後段に追跡処理を導入- One-shot モードおよびバッファ関連パラメータ(
BufferSize,IsSuppressVibe,IsEnableRecover)を削除し、設定/UI/リソース/Designer を整理 - 追跡精度・性能特性を検証するテストプロジェクト(
WindowTranslator.Tests)を追加
Reviewed changes
Copilot reviewed 59 out of 61 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| WindowTranslator/Program.cs | IOcrTextTracker のDI登録を追加 |
| WindowTranslator/Modules/Main/MainViewModelBase.cs | OCR直後に追跡処理を挿入し、表示ONで追跡状態をリセット |
| WindowTranslator/Modules/Ocr/IOcrTextTracker.cs | 追跡処理インターフェースを新規追加 |
| WindowTranslator/Modules/Ocr/OcrTextTracker.cs | テキスト領域の1対1割当て+分割/統合/復帰を含む追跡ロジックを新規追加 |
| WindowTranslator/Modules/Ocr/OcrBufferFilter.cs | 旧バッファ方式フィルターを削除 |
| WindowTranslator/FilterPriority.cs | OcrBufferFilter の優先度定義を削除 |
| WindowTranslator/Modules/Settings/AllSettingsViewModel.cs | One-shot設定の保存/表示を削除 |
| WindowTranslator/Modules/ErrorReport/ErrorReportViewModel.cs | エラーレポート出力から One-shot 設定を削除 |
| WindowTranslator/Properties/Resources.resx | One-shot のリソースキー削除 |
| WindowTranslator/Properties/Resources.en.resx | 同上(英語) |
| WindowTranslator/Properties/Resources.ar.resx | 同上(アラビア語) |
| WindowTranslator/Properties/Resources.cs.resx | 同上(チェコ語) |
| WindowTranslator/Properties/Resources.de.resx | 同上(ドイツ語) |
| WindowTranslator/Properties/Resources.es.resx | 同上(スペイン語) |
| WindowTranslator/Properties/Resources.fa.resx | 同上(ペルシア語) |
| WindowTranslator/Properties/Resources.fil.resx | 同上(フィリピン語) |
| WindowTranslator/Properties/Resources.fr.resx | 同上(フランス語) |
| WindowTranslator/Properties/Resources.hi.resx | 同上(ヒンディー語) |
| WindowTranslator/Properties/Resources.hu.resx | 同上(ハンガリー語) |
| WindowTranslator/Properties/Resources.id.resx | 同上(インドネシア語) |
| WindowTranslator/Properties/Resources.ko.resx | 同上(韓国語) |
| WindowTranslator/Properties/Resources.ms.resx | 同上(マレー語) |
| WindowTranslator/Properties/Resources.pl.resx | 同上(ポーランド語) |
| WindowTranslator/Properties/Resources.pt-BR.resx | 同上(ポルトガル語) |
| WindowTranslator/Properties/Resources.ru.resx | 同上(ロシア語) |
| WindowTranslator/Properties/Resources.th.resx | 同上(タイ語) |
| WindowTranslator/Properties/Resources.tr.resx | 同上(トルコ語) |
| WindowTranslator/Properties/Resources.vi.resx | 同上(ベトナム語) |
| WindowTranslator/Properties/Resources.zh-CN.resx | 同上(中国語・簡体) |
| WindowTranslator/Properties/Resources.zh-TW.resx | 同上(中国語・繁体) |
| WindowTranslator/Properties/Resources.Designer.cs | One-shot のプロパティを削除し生成コードを同期 |
| WindowTranslator.Abstractions/Modules/IOcrModule.cs | BasicOcrParam からバッファ関連パラメータを削除 |
| WindowTranslator.Abstractions/UserSettings.cs | TargetSettings.IsOneShotMode を削除 |
| WindowTranslator.Abstractions/Properties/Resources.resx | バッファ関連キーを削除 |
| WindowTranslator.Abstractions/Properties/Resources.en.resx | 同上(英語) |
| WindowTranslator.Abstractions/Properties/Resources.ar.resx | 同上(アラビア語) |
| WindowTranslator.Abstractions/Properties/Resources.cs.resx | 同上(チェコ語) |
| WindowTranslator.Abstractions/Properties/Resources.de.resx | 同上(ドイツ語) |
| WindowTranslator.Abstractions/Properties/Resources.es.resx | 同上(スペイン語) |
| WindowTranslator.Abstractions/Properties/Resources.fa.resx | 同上(ペルシア語) |
| WindowTranslator.Abstractions/Properties/Resources.fil.resx | 同上(フィリピン語) |
| WindowTranslator.Abstractions/Properties/Resources.fr.resx | 同上(フランス語) |
| WindowTranslator.Abstractions/Properties/Resources.hi.resx | 同上(ヒンディー語) |
| WindowTranslator.Abstractions/Properties/Resources.hu.resx | 同上(ハンガリー語) |
| WindowTranslator.Abstractions/Properties/Resources.id.resx | 同上(インドネシア語) |
| WindowTranslator.Abstractions/Properties/Resources.ko.resx | 同上(韓国語) |
| WindowTranslator.Abstractions/Properties/Resources.ms.resx | 同上(マレー語) |
| WindowTranslator.Abstractions/Properties/Resources.pl.resx | 同上(ポーランド語) |
| WindowTranslator.Abstractions/Properties/Resources.pt-BR.resx | 同上(ポルトガル語) |
| WindowTranslator.Abstractions/Properties/Resources.ru.resx | 同上(ロシア語) |
| WindowTranslator.Abstractions/Properties/Resources.th.resx | 同上(タイ語) |
| WindowTranslator.Abstractions/Properties/Resources.tr.resx | 同上(トルコ語) |
| WindowTranslator.Abstractions/Properties/Resources.vi.resx | 同上(ベトナム語) |
| WindowTranslator.Abstractions/Properties/Resources.zh-CN.resx | 同上(中国語・簡体) |
| WindowTranslator.Abstractions/Properties/Resources.zh-TW.resx | 同上(中国語・繁体) |
| WindowTranslator.Abstractions/Properties/Resources.Designer.cs | バッファ関連プロパティを削除し生成コードを同期 |
| WindowTranslator.Tests/WindowTranslator.Tests.csproj | テストプロジェクトを新規追加 |
| WindowTranslator.Tests/OcrTextTrackerAccuracyTests.cs | 追跡の精度/性能/互換性を検証するテストを追加 |
| WindowTranslator.Tests/OcrTrackingAccuracyScenarios.cs | シナリオベースの精度計測データを追加 |
| WindowTranslator.Tests/RandomizedOcrTrackingAccuracyScenarios.cs | 乱数シナリオ生成・精度評価を追加 |
| WindowTranslator.sln | テストプロジェクトをソリューションに追加 |
Files not reviewed (2)
- WindowTranslator.Abstractions/Properties/Resources.Designer.cs: Generated file
- WindowTranslator/Properties/Resources.Designer.cs: Generated file
Freeesia
left a comment
There was a problem hiding this comment.
OcrTextTracker.csをレビューしました。
全体として非常に良くできた実装だと思います。
- 1対1割当はハンガリアン法(JV法)による最小コスト割当で、候補の列挙順に依存しない決定的な対応付けになっている
- 分割・統合・休眠復元はビットマスクDP(
SelectStructureComponent)で資源数最大→スコア最大の順に厳密に選択され、状態数もMaxStructureSelectionStatesで制限済み lockによるスレッド保護、Resetでの状態全消去、RemoveTrackTreeでの休眠子トラックの連鎖削除など、ライフサイクル管理も一貫している- 組合せ生成は
MaxStructureCandidates=6で上限が抑えられており爆発しない
明確なバグは見つかりませんでした。インラインで数点、性能と一貫性についてコメントしています。
| return -1; | ||
| } | ||
|
|
||
| double text = TextSimilarity(track.ConfirmedText, observation.SourceText); |
There was a problem hiding this comment.
【性能】ここは「アクティブトラック×観測」の全ペアで到達するパスで、早期リターン(L472)は overlap == 0 かつ距離ゲート超過の場合だけなので、近接するペアはほぼ毎回Levenshteinを計算することになります。
TrySelectCombinedText側にはCanReachTextSimilarityによる文字列長ベースの事前除外があるのに対し、こちらには無いのが非対称です。テキスト量の多い画面(一覧UIなど)では毎フレームここが支配的になり得るので、長さ比が閾値に届かないペアはLevenshteinをスキップする同様のゲートを入れておくと安心です(L490の text < 0.15 判定は長さ比だけで先に棄却できるケースが多いはず)。
| private static bool IsStrongOneToOneCandidate(MatchCandidate candidate) | ||
| => candidate.Score >= StrongOneToOneScore | ||
| && NormalizeText(candidate.Tracks[0].ConfirmedText) | ||
| == NormalizeText(candidate.Combined.SourceText); |
There was a problem hiding this comment.
【一貫性】強い1対1判定ではNormalizeText(NFKC+空白圧縮)で比較しているのに対し、ScoreAssignment内のTextSimilarity(L477)は生文字列同士のLevenshteinです。
OCRでは全角/半角や空白の揺れが頻出するので、正規化前提のここでは一致扱いされるのに、スコア計算側では類似度が下がってMinimumAssignmentScoreを割る、という非対称が起きえます。TextSimilarity側も正規化後の文字列で比較するか、少なくともConfirmedTextを正規化済みで保持する形に揃えることを検討してもよさそうです。
| .Where(track => (!track.IsDormant && track.MissedFrames > MaxMissedFrames) | ||
| || (track.IsDormant | ||
| && !matchedTracks.Contains(track) | ||
| && timestamp - track.DormantSince > dormantRetention)) |
There was a problem hiding this comment.
【確認】休眠中の子トラックはDormantSinceが更新されないため、統合された親が安定して表示され続けている間も、復元候補(Restore)に一度も選ばれなければ5秒(dormantRetention)で削除されます。
その後に親が再び分割された場合、子トラックのID・確定文字列は失われ新規トラック扱いになりますが、これは意図した設計でしょうか?「親が生きている間は子を保持し続ける」(=期限判定を親の生存に連動させる)方が、長時間表示後の分割で翻訳キャッシュや表示の連続性を保てる気がします。メモリ保持量とのトレードオフなので、現状の挙動が意図的ならこのままで問題ありません。
| } | ||
| selected.AddRange(SelectStructureComponent(component)); | ||
| } | ||
| return OrderStructureCandidates(selected).ToList(); |
There was a problem hiding this comment.
【nit】SelectStructureComponentの先頭(L730)でもOrderStructureCandidatesを呼んでいるため、コンポーネント分解→選択のパスではソートが二重に実行されます。正しさには影響しませんが、ResourceCount降順など8キーの複合ソートなので、候補が多いフレームでは無駄が気になるところです。ソート済み配列をSelectStructureComponentへ渡す形にすれば1回で済みます。
概要
OcrBufferFilter(直近フレームのOCR結果を平坦化して類似検索する方式)を廃止し、テキスト領域をフレーム間で継続追跡するOcrTextTrackerに置き換える。issue #643 の設計方針に基づく実装。主な変更
追跡処理の新規実装(
IOcrTextTracker/OcrTextTracker)IOcrModule.RecognizeAsyncの直後に変更(MainViewModelBase)。DIにはScopedで登録。旧実装・関連機能の削除
OcrBufferFilter(IFilterModule、Levenshtein類似度によるバッファ内重複検索・振動抑制・復元処理)を削除。BasicOcrParamのBufferSize/IsSuppressVibe/IsEnableRecoverと、対応する全言語のリソース文字列を削除。TargetSettings.IsOneShotMode(One-shotモード)と関連コード(設定画面、初回キャプチャ制御、エラーレポート出力)を削除。テスト
WindowTranslator.Testsを追加。OcrBufferFilter相当ロジック(テスト内に再実装した比較用モデル)との比較で、安定化の一致率が基本シナリオで約80%→95%以上(14ポイント以上改善)、ランダム化シナリオでも平均10ポイント以上改善することを確認。動作確認
dotnet test WindowTranslator.Tests: 53件すべて成功Close #643