Initial commit: ノーコード画像検査アプリ (MVP + 追加機能一式)

検査レシピ=処理/検査ステップの縦リスト(配線なし)。yfoxlib(yfoximg/yfoxbase)使用。

- ビジュアル・パイプライン(カード+適用後サムネイル+緑/赤 合否)
- テンプレート/対話式ウィザードでレシピ生成(CTaskDialog)
- パラメータのスライダー・ライブ調整
- レシピ保存/読込(*.itr) + 最近使ったファイル(MRU)
- 検査範囲(ROI)を複数マウス指定(ドラッグ追加/右クリック削除)
- カードのドラッグ並べ替え
- 判定結果画像の保存 + 検査ログCSV(項目拡張)
- 処理6種+検査3種(明るさ/白画素率/塊の数)
- /selftest(実行+レシピ往復+結果画像+複数ROI塊カウント検証)、/demo

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-23 09:26:10 +09:00
co-authored by Claude Opus 4.8
commit e4eca6b303
24 changed files with 3120 additions and 0 deletions
+128
View File
@@ -0,0 +1,128 @@
#pragma once
#include "stdafx.h"
#include "core/Recipe.h"
#include "core/InspectEngine.h"
#include "PipelineView.h"
#define IDC_BTN_OPEN 2001
#define IDC_BTN_RUN 2002
#define IDC_BTN_ADD 2003
#define IDC_BTN_DEL 2004
#define IDC_BTN_UP 2005
#define IDC_BTN_DOWN 2006
#define IDC_BTN_TMPL 2007
#define IDC_BTN_WIZ 2008
#define IDC_COMBO 2011
#define IDC_PIPE 2020
#define IDC_RESULT 2021
#define IDC_SLIDER0 3001 // パラメータ スライダー(4本)
#define PARAM_ROWS 4
// メニュー コマンド ID
#define ID_FILE_OPENIMAGE 40001
#define ID_RECIPE_OPEN 40002
#define ID_RECIPE_SAVE 40003
#define ID_APP_EXIT 40004
#define ID_RESULT_SAVE 40010
#define ID_ROI_CLEAR 40020
#define ID_ROI_UNDO 40021
#define ID_LOG_SETFOLDER 40030
#define ID_LOG_RECORD 40031
#define ID_LOG_OPENFOLDER 40032
#define ID_RECENT_BASE 41000
#define RECENT_MAX 5
// メインウィンドウ。左=ビジュアル・パイプライン / 右=選択ステップの調整(スライダー)+追加。
class CMainFrame : public CFrameWnd
{
public:
CMainFrame();
void LoadDemo(); // /demo: デモ画像 + キズ検査テンプレートを読み込み実行
protected:
afx_msg int OnCreate(LPCREATESTRUCT lpcs);
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnPaint();
afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pBar);
afx_msg void OnBtnOpen();
afx_msg void OnBtnRun();
afx_msg void OnBtnAdd();
afx_msg void OnBtnDel();
afx_msg void OnBtnUp();
afx_msg void OnBtnDown();
afx_msg void OnBtnTemplate();
afx_msg void OnBtnWizard();
afx_msg void OnRecipeOpen();
afx_msg void OnRecipeSave();
afx_msg void OnAppExit();
afx_msg void OnRoiClear();
afx_msg void OnRoiUndo();
afx_msg void OnResultSave();
afx_msg void OnLogSetFolder();
afx_msg void OnLogRecord();
afx_msg void OnLogOpenFolder();
afx_msg void OnLButtonDown(UINT nFlags, CPoint pt);
afx_msg void OnMouseMove(UINT nFlags, CPoint pt);
afx_msg void OnLButtonUp(UINT nFlags, CPoint pt);
afx_msg void OnRButtonDown(UINT nFlags, CPoint pt);
afx_msg LRESULT OnPipeSelChanged(WPARAM w, LPARAM l);
afx_msg LRESULT OnPipeMoveStep(WPARAM w, LPARAM l);
afx_msg void OnRecentFile(UINT id);
DECLARE_MESSAGE_MAP()
private:
void BuildMenu();
void LoadRecent();
void SaveRecent();
void AddRecent(const CString& path);
void UpdateRecentMenu();
void OpenRecipeFile(const CString& path);
void LayoutControls();
void RunAndRefresh(int selectAfter = -2); // -2=選択維持
void ConfigureSliders(int stepIdx); // 選択ステップ→スライダー構成
double ReadSlider(int i) const; // スライダー値→パラメータ値
void ShowResult(const core::RunResult& rr);
int Sel() const;
static CString FmtNum(double v);
// 上部
CButton m_btnOpen, m_btnTemplate, m_btnWizard, m_btnRun;
CStatic m_result;
// 左
CPipelineView m_pipe;
// 右: 設定スライダー
CStatic m_settingsTitle;
CStatic m_slabel[PARAM_ROWS];
CSliderCtrl m_slider[PARAM_ROWS];
CStatic m_sval[PARAM_ROWS];
// 右: 追加パレット
CStatic m_addTitle;
CComboBox m_combo;
CButton m_btnAdd, m_btnDel, m_btnUp, m_btnDown;
CFont m_bigFont, m_uiFont;
CBrush m_brPass, m_brFail, m_brNeutral;
CMenu m_menu;
CString m_recipePath;
CString m_logFolder;
CString m_imagePath; // 最後に開いた画像(CSV用)
std::vector<CString> m_recent; // 最近使ったレシピ
HMENU m_hRecentMenu = NULL; // 「最近使ったレシピ」サブメニュー
CRect m_bigPreviewRect;
CRect m_previewFitRect; // プレビューで実際に画像が描かれた矩形(ROI 座標変換用)
bool m_roiDragging = false;
CPoint m_roiStart, m_roiCur;
int m_resultState = 0; // 0=neutral 1=pass 2=fail
// スライダー ↔ パラメータ 変換情報
int m_pCount = 0;
double m_pLo[PARAM_ROWS] = {};
double m_pHi[PARAM_ROWS] = {};
bool m_pFloat[PARAM_ROWS] = {};
core::Recipe m_recipe;
core::InspectEngine m_engine;
};