検査レシピ=処理/検査ステップの縦リスト(配線なし)。yfoxlib(yfoximg/yfoxbase)使用。 - ビジュアル・パイプライン(カード+適用後サムネイル+緑/赤 合否) - テンプレート/対話式ウィザードでレシピ生成(CTaskDialog) - パラメータのスライダー・ライブ調整 - レシピ保存/読込(*.itr) + 最近使ったファイル(MRU) - 検査範囲(ROI)を複数マウス指定(ドラッグ追加/右クリック削除) - カードのドラッグ並べ替え - 判定結果画像の保存 + 検査ログCSV(項目拡張) - 処理6種+検査3種(明るさ/白画素率/塊の数) - /selftest(実行+レシピ往復+結果画像+複数ROI塊カウント検証)、/demo Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
9.5 KiB
9.5 KiB
CLAUDE.md
This file provides guidance to Claude Code when working with code in this repository.
概要
ImgTestSystem は yfoxlib(yfoximg / yfoxbase)を使う ノーコード画像検査アプリ(純MFC)。
パラダイムは隣の C:\debug\ImgChkSystem(ブロックをワイヤで繋ぐノードエディタ)とは 意図的に別物:
検査レシピ = 上から下へ順に実行する「ステップ」の縦リスト(配線なし)。 料理のレシピ / 検査チェックリストのメタファ。ステップは2種:
- 処理(画像を加工): グレー化 / メディアン / 二値化(帯) / 大津 / ガンマ / コントラスト
- 検査(測って範囲判定→PASS/FAIL): 平均輝度 / 白画素率
UI: 左=ステップ縦リスト(追加/削除/↑↓)・右上=選択ステップのパラメータ入力・右下=作業画像プレビュー・ 上部=[画像を開く]/[実行]と総合判定バナー。ノーコード=ドロップダウンと数値入力のみ、コードもワイヤも書かない。
ビルド
VS2022 (v143 / MFC Dynamic / Release|x64 / /utf-8 / stdcpp17)。
$msb="C:\Program Files\Microsoft Visual Studio\2022\Professional\MSBuild\Current\Bin\amd64\MSBuild.exe"
& $msb ImgTestSystem.sln /p:Configuration=Release /p:Platform=x64
- リンク:
yfoximg.lib;yfoxbase.lib;gdiplus.lib(libdirC:\debug\yfoxlib\x64\$(Configuration))。 - include:
C:\debug\yfoxlib\yfoximg;...\yfoxbase;...\yfoxbase\include。 - PostBuild で
yfoximg.dll/yfoxbase.dllを出力先へコピー。出力=bin\x64\<Config>\。
アーキテクチャ
UI非依存の core/ と MFC UI層(ルート)に分離。
core/(ウィンドウ非依存)
Recipe.h—StepKind(処理/検査)、StepParam(数値パラメータ)、Step、Recipe(ステップの並び)。StepCatalog.h— 種別→表示名StepName/ 検査判定IsInspect/ 既定パラメータ生成MakeStep/ パレットAllStepKinds。 新ステップ追加はStepKindに足し、この2関数(StepName/MakeStep)とInspectEngineのRunStepに1ケース足すだけ。InspectEngine.h/.cpp— 唯一 yfoximg に依存する層。LoadImage→Run(recipe, upTo)で作業画像を原画像から作り直し、 各ステップをCImgProcessing(RGB2BW/Threshold/Threshold_Otsu/Avg/Gamma/Contrast/Median)で適用。upTo>=0でその番号までプレビュー実行、-1で全実行し総合 PASS/FAIL を返す。DrawWorkでプレビュー描画。
UI層(ルート)
App.h/.cpp—CImgTestApp:CWinApp。GDI+ 起動、/selftest分岐、CMainFrame生成。MainFrame.h/.cpp—CMainFrame:CFrameWnd。子コントロールは リソース不使用で OnCreate で動的生成(.rc なし=RC の cp932 罠を回避)。 リスト選択→パラメータ欄ロード+PreviewUpTo、[追加/削除/↑↓]でレシピ編集、[実行]で全実行+バナー更新。SelfTest.cpp—/selftest(ヘッドレス)。合成画像→レシピ実行→selftest_result.txt(UTF-8)。
yfoximg 作法(重要)
- アンブレラ
yfoximg.h(OpenGL 引き込み)は使わずImgProcessing.hを直接 include。 - yfoximg は NOMINMAX を定義しない(裸の
min/maxマクロ前提)。GDI+ も min/max マクロを要求するため、ImgProcessing.hを含む TU(InspectEngine.cpp/SelfTest.cpp)ではstd::min/std::maxを使わない(手書きクランプ)。 - 8bit グレー画像は
SetGrayPalette()してからDraw/Save。処理系は R1(入力不変)・R2(出力は新規CDiBitmap)。 - 画像は 8/24/32bit を受理。
Ensure8が 32→24(手動)→RGB2BWで 8bit へ正規化してから濃淡系処理を行う。
検証
ImgTestSystem.exe /selftest→ 合成画像(一様輝度128)で グレー化→平均輝度→白画素率 を実行し PASS を確認、selftest_result.txtを出力(終了コード 0=PASS)。
わかりやすさ強化(3方式を統合)
- ビジュアル・パイプライン(
PipelineView.*,CPipelineView:CWnd): 各ステップをカード化し、 「そのステップ適用後のサムネイル」を縦に並べる=画像が上から下へ変化する様子が見える。 検査カードは大きな緑✓/赤✗バッジ+測定値。左ストライプ 青=処理/橙=検査。ダブルバッファ描画・ホイール/スクロール対応。 罠:CDiBitmap::Draw(サムネ)は DC のBkModeを OPAQUE/暗色へ戻すので、直後の文字描画前にSetBkMode(TRANSPARENT)を必ず再設定する(でないと暗地に明字で反転)。 - テンプレート(
core/Templates.h+wizard::ChooseTemplate): 目的(キズ/欠け/明るさ/文字)を選ぶと完成レシピが入る。 - 対話式ウィザード(
Wizard.*+CTaskDialog): Q&A でレシピ生成。.rc 不要のためCTaskDialog(要 Common-Controls v6 マニフェスト=stdafx.h の pragma)。 - 右パネル: 選択ステップのパラメータを CSliderCtrl でライブ調整(
OnHScroll→即再実行→サムネ更新)。整数域は実値、 ガンマ等の実数域は 0..1000 マッピング。合否バナーはOnCtlColorで緑/赤/灰に色分け。 - 検査種別に 塊(キズ/穴)の数(
InspectBlobCount)を追加(LabelingInit/Labeling/m_nLabelCount)。
検証(追加)
ImgTestSystem.exe /demo→ デモ画像(明るい地に暗い欠陥3点)+ キズ検査テンプレを読み込み実行(画面確認用)。 スクリーンショットはPrintWindow(PW_RENDERFULLCONTENT=2)で捕捉可(Windows PowerShell 5.1 + System.Drawing)。
レシピ保存/ROI/並べ替え/検査ログ(追加実装)
- レシピ保存/読込(
core/RecipeStore.*): 人が読める UTF-8 テキスト*.itr(STEP <id>/PARAM <key> <val>/ROI ...)。StepKindId/StepKindFromId(StepCatalog.h)で enum を安定文字列 ID として永続化。読込はMakeStep既定へキー一致で上書き(前方互換)。メニュー ファイル。 - 検査範囲 ROI(
Recipe::roiEnabled/roi): 大プレビュー上をドラッグして矩形指定(CMainFrame::OnLButtonDown/MouseMove/Up)。 描画メソッドDrawShot/DrawSourceは実際に描いた矩形(アスペクト維持=AspectFit)を返し、client↔画像座標の相互変換に使う。 検査は ROI 内で計測: 明るさ=RectAvg(roi)/ 白画素率=Threshold(...,roi)÷ROI面積 / 塊数=Labeling(...,roi)。処理ステップは寸法不変なので全ステップ ROI 同座標系。ROI は大プレビュー+カードサムネに黄枠表示。メニュー 検査範囲。 - カードのドラッグ並べ替え(
CPipelineView): 押下→しきい値超でm_dragging、青い挿入インジケータ、離すとWM_PV_MOVESTEP(from,slot)→CMainFrame::OnPipeMoveStepが並べ替え+再実行。 - 判定結果画像の保存 / 検査ログ:
InspectEngine::SaveResultImage=最終画像を24bit化し ROI枠+PASS/FAIL バナー+検査要約(縁取り文字)を焼き込み保存(拡張子で png/bmp/jpg)。 検査ログ=記録フォルダ(SHBrowseForFolder)へresult_<ts>.png保存+inspect_log.csv(UTF-8 BOM, 日時/総合/画像/詳細)追記、フォルダを開く。メニュー 検査ログ。 - ⚠ 罠: Windows ヘッダの
#define small char(rpcndr.h)のため、ローカル変数名にsmallを使うと C2628。fSmall等にする。
複数ROI / MRU / CSV拡張(追加実装)
- 複数ROI(
Recipe::rois=vector<CRect>。空=画像全体): 大プレビューをドラッグで範囲追加、右クリックでその範囲を削除、 メニュー 検査範囲=「最後を取り消す」「すべてリセット」。検査は全ROIを合算(明るさ=面積重み付き平均 / 白画素率=合算/合計面積 / 塊数=全ROIマスクを結合→union bbox でラベリング)。 大プレビュー+カード+結果画像に黄枠+番号を描画。.itrはROI l t r bを範囲ごとに1行(旧ROI enabled l t r b5値も読める)。- ⚠ 重要バグ修正: yfoximg
CImgProcessing::Thresholdを同一バッファへ sub-rect で複数回呼ぶとマスクが壊れる(2個ROIで塊数0になった)。MakeBinaryは Threshold をやめ、画素を直接走査してROI内だけ白く塗る方式に変更(8bit前提=Ensure8済)。/selftestに複数ROI塊カウント検証(全体3/大ROI2/小2個ROI2)を常設。
- ⚠ 重要バグ修正: yfoximg
- 最近使ったレシピ(MRU): 最大5件を
HKCU\Software\YFox\ImgTestSystem\Recent\File1..5に保存(SetRegistryKey(L"YFox"))。 ファイルメニューの「最近使ったレシピ」サブメニュー(m_hRecentMenuを保持しUpdateRecentMenuで再構築、ON_COMMAND_RANGE)。開く/保存時にAddRecent。存在しない項目はクリック時に一覧から除去提案。 - 検査ログCSV 拡張: 列= 日時,総合判定,元画像,レシピ,ステップ数,検査数,合格数,不合格数,検査範囲数,結果画像,詳細(UTF-8 BOM)。記録フォルダも
HKCU\...\Log\Folderに永続化。
現状
処理6種+検査3種、ビジュアル・パイプライン、テンプレート、ウィザード、スライダー調整、
レシピ保存/読込(+MRU)、複数ROI 指定、カードのドラッグ並べ替え、判定結果画像保存/検査ログ(CSV拡張)、/selftest・/demo。
/selftest は 実行 + レシピ往復一致 + 結果画像保存 + 複数ROI塊カウント を検証(RESULT: PASS)。