TIAS Shot(WinForms / .NET Framework 4.8 / x64 の舌診撮影ソフト)の検証プロファイル.verifier は本ファイルだけを頼りに検証する.
経緯: 2026-09-18 時点では「verifier はハードウェア結合層(カメラ・UI・スレッド)を担保できない」としてプロファイルを作らなかった.その後,ヘッドレスのセルフテストモード(TIASshot.exe --selftest,SELFTEST ビルドフラグ)で起動時の依存解決・プレビュー経路・校正〜保存の一部を実機なしで自動確認できるようになったため,本プロファイルを作成した.
scripts/verify/run_selftest.py が,クリーンビルド(Debug|x64)→ 既存テスト(NUnit)→ TIASshot.exe --selftest を実行し,終了コードと結果ファイルで判定する.| ID | 確認内容 | 実コードを通す範囲 | 代替している部分 |
|---|---|---|---|
deps | 起動時にアセンブリ解決エラー(FileLoadException / FileNotFoundException)が出ない | TIASshot.exe.config のバインディングリダイレクトと bin の DLL バージョンの一致,本体参照の推移的ロード,bin 内の全管理 DLL のロード,OpenCvSharp(ネイティブ DLL・Mat 演算・Mat.AsSpan(System.Memory)・ArUco),BitmapConverter と BitmapUtil.FastClone の往復,config.xml・TCC CSV の読み込み,Form1 の実コンストラクタ(InitializeComponent) | Form1_Load(カメラ・光源への接続)は実行しない |
preview | プレビュー経路(カメラコールバック → UI 所有コピー(FastClone)→ 表示用 Bitmap)が動く | CameraBase(コンストラクタ・BootCheck・ProcessCalibrationFrame),Form1.ShowImage・MainRefreshTimer_Tick(実タイマー),PreviewMonitor(実コンストラクタ・UpdateImage・RefreshTimer_Tick).入力 Bitmap 解放後も表示コピーが有効であること(所有権モデル)を確認 | カメラは偽カメラ(SelfTest/SelfTestCamera.Lucam のコールバック手順を再現).フォームは非表示・InitializeComponent を呼ばないヘッドレス版コンストラクタ.副ディスプレイの存在は模擬 |
calib-save | 校正〜保存が一通り動く | ChartDetector(ArUco 検出・固定判定・ホモグラフィ・マスク),CameraBase.CalcTcc・ColorCorrector(変換行列算出・CSV 保存),CameraBase.ShotOne → RunShotLoop → SaveThread → SaveImages(sRGB 変換画像の保存).保存物の読み戻し・行列の有限性・変換後の色票が参照値に戻ることを確認 | チャートは合成画像(ArUco と色票をコードで描画).ゲイン反映は偽カメラが画像へ乗算して模擬.保存先は一時フォルダ |
--full 時の nuget restore による nuget.org からのパッケージ取得のみ例外)config.xml の File/SaveFolder,既定 C:\TIAS_Data).セルフテストはこれらに触れない設計であり,verifier も触れないscripts/verify/run_hwtest.py)経由でだけ接続してよい.本番の撮影データフォルダは実機テストでも触れない(保存先は一時フォルダに差し替わる)リポジトリルートで実行する.
| 用途 | コマンド |
|---|---|
| 通常(コード変更の確認) | python scripts/verify/run_selftest.py |
| 依存更新(NuGet パッケージ・バインディングリダイレクトの変更)の確認 | python scripts/verify/run_selftest.py --full |
--no-clean(Debug 出力を消さない)・--skip-tests(既存テストを省略)は開発時の短縮用であり,判定には使わない(verifier は上表のコマンドだけを使う)--full は packages を退避して nuget restore からやり直す(git clone 直後と同じ状態.ENV_04「クリーン環境での検証」).復元に失敗した場合は退避した packages を自動で戻す.packages の退避(改名)自体に失敗した場合(Visual Studio が使用中等)は packages を変更せずに終了コード 2 で止まる.verify/selftest/run-<日時>/(.gitignore 済み.実行ごとに別ディレクトリ)summary.json(各ステップの成否)・build.log・test.log・restore.log(--full 時)・selftest-result.txt(セルフテストの詳細.UTF-8 BOM 付き)0=全て合格,1=不合格あり(ビルド失敗・テスト失敗・セルフテスト失敗),2=前提条件を満たさない(→「検証不能」)summary.json の selftest_exit_code): 0=全項目合格,1=不合格あり,2=セルフテスト自体の異常,3=タイムアウト(5 分.ハングの疑い)selftest-result.txt は項目ごとに [PASS] <ID>: ... / [FAIL] <ID>: ... の見出し行と,その下の詳細行(- 情報,WARN: 参考,FAIL: 失敗理由)で構成され,最終行が RESULT: PASS (3/3) または RESULT: FAIL (...) になるFAIL: 行には例外型・メッセージ・対象アセンブリ名([assembly: ...])・Fusion ログの要点([fusion: ...])・スタックの先頭が入る.依存の問題はここで特定できるTIASshot.exe の標準出力は OS のコードページ(cp932)で出るため,直接実行すると文字化けすることがある(ランナーは標準出力を使わない)PLAN_06 の実機テスト(TIASshot.exe --hwtest,HWTEST ビルドフラグ).実際の Form1 を表示し,指定した機種のカメラと光源を操作して検査する.
リポジトリルートで実行する.対象は ImagingSource だけで,Lumenera の実機テストは行わない(PLAN_06.Lumenera は解像度が相対的に低く今後あまり使わない見込みのため).ユーザーが明示的に Lumenera の検査を指示した場合に限り --camera lucam を使う.
| 用途 | コマンド |
|---|---|
| Lumenera を検査する(通常は行わない.ユーザーの明示指示があるときだけ) | python scripts/verify/run_hwtest.py --camera lucam |
| ImagingSource を検査する(チャート不要の検査) | python scripts/verify/run_hwtest.py --camera iscam |
| ImagingSource を検査する(チャートが必要な検査.上の行に続けて実行する) | python scripts/verify/run_hwtest.py --camera iscam --with-chart |
--with-chart(チャートが必要な検査.PLAN_06 フェーズ 2)を指定すると,チャート不要の検査(preview〜reconnect)の代わりに calibrate・shot・close-saving・close-calibrating を行う(connect・cleanup は両方で行う).校正は止めない.チャート不要の検査は行わないため,--camera iscam と --camera iscam --with-chart をカラーチャートをはめたまま続けて実行する(付け外しは不要)--keep(TIASshot.exe の --hwtest-keep)を付けると,合格時も作業フォルダ(%TEMP%\TIASshot-hwtest\work-*)を残し,--with-chart では校正後のフレームとその変換画像を証拠の画像(evidence\calibrated-frame-raw.png・evidence\calibrated-frame-srgbNN.png.NN は変換の次元)として保存する.画像を人間に見せたいときや,色の誤差を調べるときに使う(判定は変わらない)--with-chart は約 50〜55 秒(校正 約 9〜10 秒・撮影 約 16 秒・保存中に閉じる 約 20〜24 秒・校正中に閉じる 約 3.5〜4 秒).実機テスト内部の全体の上限はチャート不要 600 秒・--with-chart 1200 秒,ランナーの打ち切りはそれぞれ 720 秒・1320 秒--no-clean(Debug 出力を消さない)は開発時の短縮用であり,判定には使わないTIASshot.exe --hwtest --camera <機種> --hwtest-out <結果ファイル> を実行ファイルのフォルダで実行する.NUnit テスト・セルフテストは実行しない.verify/hwtest/run-<日時>/(summary.json・build.log・hwtest-result.txt(UTF-8 BOM 付き))0=全項目合格,1=不合格あり(ビルド失敗・検査の不合格・タイムアウト),2=前提条件を満たさない(→「検証不能」.ツール未導入・TIASshot 起動中・指定機種が見つからない・引数不正)summary.json の hwtest_exit_code): 0=全項目合格,1=不合格あり,2=実機テスト自体の異常(引数不正・指定機種が見つからない),3=タイムアウト(各項目の上限または全体(チャート不要 10 分・--with-chart 20 分).ハングの疑い),null=ランナーが打ち切った(チャート不要 720 秒・--with-chart 1320 秒)--with-chart なし)| ID | 確認内容 | 測定値と判定(しきい値は ImagingSource の実測(PLAN_06 フェーズ 1)から決めた.結果ファイルの表記は「暫定」のまま) |
|---|---|---|
connect | 指定した機種だけに接続でき,機種名・シリアル番号が取れる | 列挙した台数,Connect() の成否と所要時間,機種名・シリアル番号 |
preview | プレビューが流れる | 最初のフレームまでの時間,フレームレート(下限 10 fps),本モニタへの表示,平均輝度と飽和画素の割合 |
exposure-gain | 露光・ゲインの設定がフレームに効く | 先に基準の明るさを探す(元の露光に最も近い 2^n 秒の段に合わせ,平均輝度 30〜220 かつ飽和画素の割合 1% 以下になるまで露光を 1 段(ExposureLogStep.時間で 2 倍・半分)ずつ動かす.最大 12 段).露光は基準から 1 段下げ・上げ(比が下げ 0.8 以下・上げ 1.25 以上),ゲインは範囲の幅の ±10%(差が 3 階調以上.片側の向きだけ期待どおりでも合格)で判定.ImagingSource は絶対値(VCDAbsoluteValueProperty.秒・dB)で操作する.元の値に戻ったことを読み戻しで確認(相対誤差 1% 以内) |
light | 光源が点灯・消灯し,閉じた後に開き直せる | 照明ボタンでの点灯・消灯の平均輝度の差(100 階調以上),LightSource.Close → Open の成否,開き直した後の点灯の効き |
close-preview | プレビュー中に閉じる処理を呼んでもすぐ戻る | 閉じる処理(Form1_FormClosing)の所要時間(上限 1000 ms)・例外の有無・後始末の順序(closing → timer → camera → light)・閉じた後 1 秒間に届いたフレーム数(2 以下) |
reconnect | 切断した後に再接続できる | 2 回目の Connect() の成否・シリアル番号の一致・再接続後のフレームの到着(5 フレーム以上) |
cleanup | 後始末と書き込み禁止の確認 | 露光・ゲインを戻す → カメラ切断 → 光源のポートを閉じる(消灯はしない),の成否.実行ファイルのフォルダの *.xml(config.xml・デバイス状態ファイル)の内容が変わっていないこと,本番の保存先の今日のフォルダが変わっていないこと |
--with-chart)connect・cleanup は上表と同じ(cleanup ではホワイトバランスを戻さない.校正でカメラ側の値だけが変わり,次の接続でデバイス状態ファイルの値に戻る).しきい値は ImagingSource の実測(PLAN_06 フェーズ 2)から決めた.
| ID | 確認内容 | 測定値と判定 |
|---|---|---|
calibrate | 実物の舌診チャートで自動校正が完了し,校正後のフレームを変換した色票が参照値に近い | 校正の待ち時間(最初のフレーム → チャート検出 → 校正完了.上限 60 秒),校正中の表示の順,校正完了後に撮影ボタンが有効になること,校正データが一時フォルダに保存されること.校正後のフレームを校正の変換行列で変換し,24 色票の平均と参照値(tcc_srgb)の差を 8bit(保存画像と同じ切り詰め後)・チャネルごとの差の絶対値で判定する: 平均 5 以下,白色票を除いた最大 10 以下,白色票の最大 40 以下(暫定.下記「既知のノイズ」).白色票は参照値の BGR の和が最大の色票(13 番).ΔE76・白飛びの割合・当てはめの誤差(TCC_sRGB17.csv)は参考 |
shot | 単発・連続撮影で撮影画像・sRGB 変換画像・Info.csv が保存され,撮影時刻の間隔が設定どおり | 単発 1 枚・連続 3 枚(間隔 1000 ms)を撮影し,撮影直後は保存中で撮影ボタンが無効,保存の完了(上限 90 秒)後に再有効化されること,保存されたファイル(撮影画像・変換画像・Info.csv.大きさ 0 でない)と撮影ログの行数・備考,撮影時刻の間隔と設定値の差(100 ms 以下),エラー通知が無いこと |
close-saving | 保存中に閉じようとすると取り消され,保存の完了後は閉じられる | 連続 5 枚(間隔 0 ms.保存が先に終わったら 10 枚で再試行)の保存中に閉じる処理を呼び,取り消されること・表示「保存中です.保存完了後に閉じてください」・後始末が走っていないこと.保存の完了後に閉じる処理の所要時間(上限 1000 ms)・後始末の順序(closing → timer → camera → light)・閉じた後 1 秒間に届いたフレーム数(2 以下) |
close-calibrating | 再接続して校正中に閉じる処理を呼んでもすぐ戻る | 再接続(シリアル番号の一致)→ 校正中になる(上限 60 秒)→ 500 ms 後に閉じる処理を呼び,所要時間(上限 1000 ms)・後始末の順序・閉じた後に届いたフレーム数(2 以下)・例外の有無 |
hwtest-result.txt はセルフテストと同じ書式([PASS] <ID>: ... / [FAIL] <ID>: ... の見出し行,- 情報・WARN: 参考・FAIL: 失敗理由の詳細行,最終行 RESULT: PASS (7/7)(--with-chart は RESULT: PASS (6/6))または RESULT: FAIL (...)).冒頭に行う検査の一覧(checks:),暫定しきい値の一覧(thresholds (暫定)),全体の上限(overall timeout:),校正の扱い(校正: 停止(チャート不要の検査…) または 校正: 有効(チャートが必要な検査…))が出るFAIL: タイムアウト: ...(実行中のステップ: ...) が出る.どの SDK 呼び出しで止まったかはステップ名で特定する- UI スレッド(ManagedThreadId ...)のマネージドスタック ...: に続く at ... の行)と,自プロセスのダンプのパス・大きさ(- ミニダンプ: <work-*>\hang-<日時>.dmp(全メモリ,... MB ...).書けなければ WARN:)も出る.ダンプは作業フォルダに残るので,報告にパスを書き,.dmp を Visual Studio(「マネージドのみでデバッグ」→ 並列スタック)か WinDbg(.loadby sos clr → ~*e !clrstack)で開いて止まった場所を調べるRESULT: FAIL (camera not found: <機種>)(終了コード 2).機材の接続を人間に依頼する| 前提条件 | 確認方法 | 満たされない場合 |
|---|---|---|
| ユーザーの合図がある | オーケストレーターからの指示に「実機テストの合図: あり」がある | 実行せず「検証不能(合図なし)」と報告する |
| 撮影の本番中でない・TIASshot が起動していない | ランナーが tasklist で確認する(起動中なら終了コード 2) | 検証不能とし,人間に TIASshot の終了を依頼する(自分でプロセスを止めない) |
| 指定機種のカメラと光源が開発 PC に接続されている | connect の詳細行(列挙した台数)・light の詳細行(ポートの有無) | カメラが無ければ検証不能(終了コード 2).光源が無ければ light が FAIL になる.機材の接続を人間に依頼する |
カメラの前の穴にカラーチャート(または白板)がはめてある(穴が空だと暗く,明るさの変化を評価しにくい).チャート不要の検査では校正は止まる(結果ファイル冒頭に 校正: 停止(チャート不要の検査…)) | 人間に確認する.preview・light の詳細行 校正は止まっています | はめていなければ人間にはめてもらってから再実行する.preview・light が FAIL: 校正を止めているはずなのに校正が… なら校正の停止が効いていない不具合として報告する(露光・ゲイン・カメラ本体のホワイトバランスが乱れている可能性あり) |
セルフテストの前提(Visual Studio / Build Tools・packages/・IC Imaging Control 3.5) | 上記「前提条件と確認方法」と同じ | 同上 |
--with-chart の実測(同上.2026-10-08〜09 の 4 回): 校正の待ち時間 5.0〜7.9 秒(チャート検出まで 1.6〜3.0 秒+校正 3.4〜4.9 秒),色の誤差の平均 1.46〜1.57・白色票を除いた最大 3.47〜3.73・白色票 24.33〜27.35(ΔE76 の平均 1.17〜1.26),撮影間隔のずれ 4〜63 ms,保存は 1 枚あたり約 3.3〜11 秒,保存の完了後に閉じる 33〜76 ms,校正中に閉じる 53〜98 ms.重いアプリ(Fusion360・Docker・WSL・ブラウザ等)が動いていると,校正・保存が 1.5〜3 倍遅くなり,撮影間隔のずれも大きくなる(2026-10-09 の実測).保存の待ちの上限は 180 秒.これより大きく外れたら,しきい値より先にチャートのはまり方・照明・機材の状態を疑うexposure-gain の WARN: 元に戻した後の平均輝度が最初と離れています は参考(判定は設定値の読み戻しで行う)MEMMONITOR)は開かないcleanup 項目に結果が出る.光源は消灯しない(アプリの終了時と同じく点いたまま残るのが仕様.上流 v1.7 と同じ).light 項目は点灯・消灯・再点灯を検査し,最後は点灯した状態で終わるWARN: 緊急の後始末: 光源のポートのクローズが 5 秒以内に終わりません が出たら,ポートが開いたままの可能性を人間に報告する(光源が点いたままなのは仕様であり報告不要.light 項目の途中(消灯中)で止まった場合は消灯したまま残りうる)%TEMP%\TIASshot-hwtest\work-<日時>-<PID>\(一時設定ファイル config.hwtest.xml.チャート不要の検査では校正を止めるため校正データは書かれない.--with-chart では校正データ・撮影データ(data\<日付>\)と,--keep 指定時は証拠の画像(evidence\)が書かれる)と .verify/hwtest/run-<日時>/ だけ.合格時と前提を満たさずに終わった場合(終了コード 2)は work-* を自動削除し(--keep(--hwtest-keep)指定時は残す),不合格(1)・タイムアウト(3)時は残して結果ファイルの末尾に work dir kept: <パス> と出る.残った work-* の有無とパスを報告の「後始末」に書くconfig.xml・デバイス状態ファイル({DeviceName}.xml)・本番の保存先には書き込まない(cleanup で確認する)| 前提条件 | 確認方法 | 満たされない場合 |
|---|---|---|
| Visual Studio 2022 または Build Tools(MSBuild・vstest)が導入済み | ランナーが vswhere で自動検出する(見つからなければ終了コード 2) | 検証不能とし,docs/02_ENV/ENV_02_環境構築手順.md に従った導入を人間に案内する |
NuGet パッケージが復元済み(packages/) | ls packages | python scripts/verify/run_selftest.py --full を実行してよい(nuget.exe が無ければ検証不能とし setup.ps1 の実行を人間に案内する) |
| IC Imaging Control 3.5 .NET Library が導入済み(ビルドに必要.実機カメラは不要) | ビルドの成否(build.log に TIS.Imaging の参照エラーが無いこと) | 検証不能とし,ENV_02 の SDK 導入手順を人間に案内する |
TIASshot.exe やテストが実行中でない(Debug 出力を削除できる) | ランナーがクリーンするのは Debug 出力(TIASshot/ と TIASshot.Tests/ の bin/x64/Debug・obj/x64/Debug)のみで,bin/x64/Release 等ほかの構成の出力には触れない.削除に失敗すると終了コード 2 で止まる | 検証不能とし,人間にアプリ・Visual Studio のデバッグ実行の終了を依頼する(自分でプロセスを止めない) |
%TEMP%\TIASshot-selftest\work-<日時>-<PID>\(一時設定ファイル・校正データ・撮影画像).合格時は自動削除,不合格時は証拠として残し,結果ファイルの末尾に work dir kept: <パス> と出る.verify/selftest/run-<日時>/(ランナーのログと結果)config.xml は変更しない(セルフテストは複製して保存先・参照パス・効果音を差し替えた一時設定を使う).本番の保存先(C:\TIAS_Data 等)には書き込まないwork-* フォルダの有無とパスを,報告の「後始末」に書く(削除は人間の判断に任せてよい)--full はパッケージ取得で数分)Release 構成にはセルフテストが含まれない(SELFTEST フラグは Debug 系のみ).Release の exe に --selftest を渡すと通常起動(UI 表示・カメラ接続)になるため,実行しないdeps の リソース系の AssemblyResolve n 件(サテライトリソースの探索.判定対象外): 日本語カルチャのサテライトリソース(TIASshot.resources)を探して見つからないのは通常動作deps の redirect System.ValueTuple → 4.0.3.0: bin に DLL なし: .NET Framework 4.7.1 以降は mscorlib に統合されており bin に置かれないのが正常TIS.*・lumenera.*)のロード失敗は WARN:(判定対象外).SDK 未導入の環境では出うるpreview / calib-save の所要時間は環境で変わる(判定条件ではない)--selftest を付けない TIASshot.exe の起動(UI が開き,実機カメラ・光源(シリアルポート)へ接続を試みる)
python scripts/verify/run_hwtest.py --camera <lucam|iscam> [--with-chart] [--keep](上記「実機テスト」節).TIASshot.exe --hwtest の直接実行・合図なしの実行・Release の exe での実行はしないconfig.xml(リポジトリ内・bin 内とも)や本番の保存先フォルダ(C:\TIAS_Data 等)の編集・削除packages.bak-* 以外のリポジトリ内ディレクトリの手動削除・改名(packages の退避と復元はランナーの --full だけが行う)TIASshot.exe.config の改ざん等)や TIASshot.exe --selftest の直接実行.セルフテストが依存の問題を検出できるかの確認が必要な場合は,人間が docs/02_ENV/ENV_04_開発コマンド.md の手順で行う(verifier には許可しない)本プロジェクトでは verifier がシナリオを書く必要はない(確認項目は TIASshot.exe --selftest に組み込み済みで,引数で項目を選ぶ仕組みも無い).verifier の作業は次のとおり.
1. 変更内容に応じてコマンドを選ぶ - NuGet パッケージ・App.config(バインディングリダイレクト)・csproj の参照を変えた → --full - それ以外のコード変更 → 通常 2. python scripts/verify/run_selftest.py [--full] を実行する 3. 出力ディレクトリの summary.json と selftest-result.txt を Read で開き, - 各ステップ(clean / restore / build / tests / selftest)の成否 - 各項目(deps / preview / calib-save)の [PASS]/[FAIL] と,FAIL: 行・WARN: 行の内容 を確認する.PASS でも,今回の変更に関係する項目の詳細行(ロードされた DLL のバージョン等)を必ず見る 4. FAIL の場合は FAIL: 行(例外型・アセンブリ名・Fusion ログ)を証拠として報告する (build.log / test.log の該当箇所も併記する)
変更がセルフテストの 3 項目で観測できない領域(下記「自動で確認できない範囲」)にある場合は,その部分を「未確認」として人間に回す.
セルフテストが PASS でも,以下は確認していない.変更がこれらに関わる場合は「人間が確認すべき残り項目」に具体的に書く.
WHITEBOARD)MEMMONITOR)docs/06_TEST/TEST_03_メモリ修正効果計測.md の手順)Release 構成の実行(セルフテストを含まないため,起動確認は人間が行う)scripts/verify/run_selftest.py が行う.verifier は判断(結果の読み取り・報告)のみ行う.verify/selftest/run-<日時>/ へ出力し,前回の証拠を上書きしないTIASshot/SelfTest/ と TIASshot/UI/*.SelfTest.cs(#if SELFTEST),ビルドフラグは docs/02_ENV/ENV_06_ビルド構成とビルドフラグ.md を参照する