#ifndef _TCSCHECK_H #define _TCSCHECK_H #include #include #include #include #include #include // 必需:mkdir 函数声明 #include // 可选:通常被 sys/stat.h 包含,但建议显式包含 #include "TcsConfig.h" #include struct CHECK_PARAM{ int nAreaLowFilter; // low filter of the product area int nDiscardTop; //Discard top edge width of the effective area int nDiscardBottom; //Discard bottom edge width of the effective area int nDiscardLeft; //Discard left edge width of the effective area int nDiscardRight; //Discard right edge width of the effective area float fZoomRatio; // scaling ratio of the source image int nFilterLow; // low threshold of the filter int nFilterHigh; // high threshold of the filter int nBlockSize; // the size of the block int nAreaFilter; // blob filter for drawing, only draw blob with area >= nAreaFilter int nCountFilter; // blob filter for counting, Only the first nCountFilters with areas arranged from largest to smallest }; /* 长宽比 >= 3 ? ├─ 是 → SCRATCH (划伤) └─ 否(紧凑形状): ├─ area < 大块阈值 → POINT (点型,不论黑白) └─ area >= 大块阈值: ├─ greyDiff < 0 → DIRTY (黑色大块脏污) └─ greyDiff > 0 → FADING_SPOTS (白色大块淡斑) */ enum DEFECT_TYPE_DEFINE{ DEFECT_TYPE_OK = 0, DEFECT_TYPE_POINT = 1, DEFECT_TYPE_SCRATCH = 2, // white line DEFECT_TYPE_DIRTY = 3, DEFECT_TYPE_FADING_SPOTS = 4 }; inline const std::string DEFECT_TYPE_CODE[5] = { "P0000", "MA505", "MA506", "MA504", "P0003" }; inline const std::string DEFECT_TYPE_DESC[5] = { "OK", "硬质颗粒", "划伤", "脏污", "淡斑" }; struct DEFECT_INFO{ int nDefectType; int nDefectArea; int nDefectX; int nDefectY; int nDefectWidth; int nDefectHeight; double dGreyDiff; // 灰阶差:blob均值 - 所属局部块均值 std::string strDefectCode; std::string strDefectDesc; }; class CTcsCheck{ public: int m_nInitStart; int m_bSystemExit; CHECK_PARAM m_cpCfg; int m_nInitEnd; pthread_mutex_t m_mutex; std::vector m_fileList; std::vector m_vecDefectInfo; CTcsCheck(); ~CTcsCheck(); void SetCheckDir(std::string dirIn,std::string dirOut); void SetChecConfig(CHECK_PARAM* cp); void ProcessImages(bool bDrawResult); // ========== 独立检测/分类接口 ========== // 传统检测:对单张图做完整预处理+自适应二值化,输出残点二值图 // 返回: 0=成功, -1=无产品/输入为空 int TraditionalDetect(const cv::Mat& img, cv::Mat& blobImg); // 传统分类:对残点二值图做连通域分析+缺陷分类,结果写入 m_vecDefectInfo // 前提: 已调用 TraditionalDetect(内部 m_matBlur 已就绪) // 返回: 分类到的缺陷数量,<0 表示异常 int TraditionalClassify(const cv::Mat& blobImg); private: std::string m_strDirIn; std::string m_strDirOut; cv::Mat m_matLoad; cv::Mat m_matBlob; cv::Mat m_matBlur; // 模糊图,供 TraditionalClassify 使用 cv::Mat m_matDraw; cv::Size m_sizeImage; std::string m_strCurFile; bool CreateDirectories(std::string path, mode_t mode = 0755) ; void LoadImages(); std::string GetFileName(const std::string& path) const; cv::Rect GetBoundingRect(cv::Mat matBinary); cv::Rect GetCropArea(cv::Rect rtValid); cv::Mat AdaptiveBinary(cv::Mat matBlur); void Process(bool bDraw = false); // 纯分类:对二值图做连通域分析+缺陷分类,结果写入 m_vecDefectInfo void ClassifyBlobs(const cv::Mat& blurCrop, const cv::Mat& imgBlob); // 纯绘制:基于 m_vecDefectInfo 绘制缺陷标注 cv::Mat DrawBlobInfoImage(const cv::Mat& imgCrop, const cv::Mat& imgBlob); void DetectWithAdaptiveBinary(bool bDraw = false); void DetectWithAdaptiveBinaryOptimized(bool bDraw = false); void DetectWithDoH(bool bDraw = false, double dSigma = 1.0 ,int nThreshold = 50); void DetectWithLoG(bool bDraw = false, double dSigma = 1.0, int nThreshold = 50); }; #endif