Newer
Older
TIASjudge / docs / 04_SPEC / SPEC_02_診断ロジック仕様.md

診断ロジック仕様 (Diagnosis Logic Specification)

診断結果は現行実装と一致させる.本仕様は現行コード(org/src)の解析結果を正とする.

処理パイプライン (Pipeline)

ROI 平均 RGB → (1) 多項式変換で XYZ → (2) Lab 変換 → (3) SVM 分類 → 5 色スコア・上位 2 色

(0) ROI 平均色

  • クリック点ごとに 51×51 px の矩形 ROI の平均 BGR を算出
  • 複数点クリック時は各 ROI 平均の平均(全クリックの合算 ÷ クリック数)を診断に使用

(1) RGB → XYZ(多項式回帰)

変換行列 CSV の係数 a[0..16], b[0..16], c[0..16] を用い,R, G, B の 3 次までの多項式(17 項: 1 次 3 項 + 2 次クロス 3 項 + 2 乗 3 項 + 3 次 7 項 + 定数項)で X, Y, Z を計算する.負値は 0 にクリップする.

X = a0*R + a1*G + a2*B
  + a3*R*G + a4*R*B + a5*G*B
  + a6*R^2 + a7*G^2 + a8*B^2
  + a9*R^2*B + a10*R^2*G + a11*G^2*R + a12*G^2*B + a13*B^2*R + a14*B^2*G
  + a15*R*G*B
  + a16
(Y, Z も係数 b, c で同形)

(2) XYZ → L*a*b*

白色点 Xn=102.07, Yn=100.0, Zn=79.41(固定)とし,立方根で算出する:

  • L* = 116 (Y/Yn)^(1/3) − 16
  • a* = 500 ((X/Xn)(1/3) − (Y/Yn)(1/3))
  • b* = 200 ((Y/Yn)(1/3) − (Z/Zn)(1/3))

※ CIE 標準の低輝度側条件分岐(t ≤ (6/29)³ のときの線形近似)は現行実装に無いため意図的に実装しない(結果同一性優先).

※ 精度の踏襲: 旧実装は変換係数を単精度(float a[17] 等)で保持し,X, Y, Z の計算は倍精度,出力 L*a*b* は単精度(float)に丸めて保持する.新実装(core/color.py)もこれを再現する(係数を float32 に丸めてから float64 で演算し,Lab 出力を float32 に丸める).

(3) SVM 分類

  • 学習データ: data.csv の 84 サンプル(入力: L*a*b* 3 次元,出力: 190 列 = 医師 38 名 × 5 色の 0/1 評価)
  • 出力 190 列それぞれについて 2 クラス SVM を診断のたびに学習し,入力 Lab を予測する(正例が 2 未満の列は学習せずスコア 0)
  • SVM パラメータ: C_SVC / RBF カーネル,γ=0.011,C=12.0,終了条件 EPS 1000 回・FLT_EPSILON
  • 色ごとに 38 医師分の予測値を平均 → 5 色の一致率(0〜1)を百分率で表示する
  • スコア降順で上位 2 色を主要ラベルとする

診断失敗の判定 (Failure Detection)

5 色スコア(% 整数)が特定の組(淡紅 11・紅 5・暗赤 0・紫 42・淡白 3)と完全一致した場合,現行実装は「Diagnosis failed」と表示する.

このパターンの正体は「入力が学習データ域から大きく外れ,RBF カーネル値がほぼ 0 になり各列の判定がバイアス項のみで決まるときの SVM の既定応答」である(ステップ 4 で実測確認.L* が正でも発生する).

新実装は以下の両方を失敗条件とする(表示仕様は現行と同じ.失敗時もスコアは算出値を表示する):

  1. 原因の直接検出: 入力の NaN/inf(INVALID_INPUT),L* ≤ 0(DEGENERATE_INPUT),全列学習不能(NO_TRAINABLE_COLUMN),学習・予測の内部失敗(TRAINING_FAILED / PREDICTION_FAILED)
  2. 現行パターン判定の踏襲: スコア組が上記の値と完全一致した場合(OUT_OF_DOMAIN).現行実装の失敗表示と完全一致させるために残す(直接検出のみでは L* が小さい正値の域外入力を取りこぼすことが実測で判明したため)

データファイル形式 (Data File Formats)

変換行列 CSV(ユーザーが診断時に選択)

  • 17 行 × 3 列(ヘッダなし).各行が a[i], b[i], c[i](X, Y, Z 用係数)
  • 撮影環境(カメラ・照明)ごとのキャリブレーション結果として作成されるファイル

data.csv(学習データ.リポジトリの data/ に同梱予定)

  • 1 行目: ヘッダ(L,a,b,紫,暗赤,紅,淡紅,淡白,… の繰り返し)
  • 2 行目以降: 84 サンプル.列 1〜3 が L*a*b*,列 4〜193 が医師 38 名 × 5 色の 0/1(各医師 5 列の one-hot)
  • ※ 実ファイルは 198 列(医師ブロック 39 個分)あるが,末尾の 39 番目のブロック 5 列は全サンプルで全 0 の未使用列である(有効な評価データは上記の 38 名分=193 列)
  • ※ 旧実装の読込列数は 193 列で確定(ステップ 2 で org/src を確認済み: EXP_OUTPUT_DIM = 190 = 38 名 × 5 色で,CsvRead は cols=193 で読み 194 列目以降にアクセスしない.ヘッダの「医師の数39」コメントは誤記).新実装(core/csv_io.py)も先頭 193 列のみを読む