|
|
/*
|
|
|
* @Author: your name
|
|
|
* @Date: 2022-04-20 15:49:50
|
|
|
* @LastEditTime: 2025-09-17 19:49:41
|
|
|
* @LastEditors: xiewenji 527774126@qq.com
|
|
|
* @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
|
|
* @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/include/CamDeal.h
|
|
|
*/
|
|
|
#ifndef ImgCheckAnalysisy_H_
|
|
|
#define ImgCheckAnalysisy_H_
|
|
|
|
|
|
#include <iostream>
|
|
|
#include <stdio.h>
|
|
|
#include <sys/time.h>
|
|
|
#include <opencv2/opencv.hpp>
|
|
|
#include <condition_variable>
|
|
|
#include <mutex>
|
|
|
#include <vector>
|
|
|
#include <thread>
|
|
|
#include <string>
|
|
|
#include <stdio.h>
|
|
|
#include <stdlib.h>
|
|
|
#include <unistd.h>
|
|
|
#include "BlobBase.h"
|
|
|
#include "ImgCheckBase.h"
|
|
|
#include "ImageDetBase.h"
|
|
|
#include "ImgCheckConfig.h"
|
|
|
#include "CheckErrorCodeDefine.hpp"
|
|
|
#include "CheckConfigDefine.h"
|
|
|
#include "ConfigBase.h"
|
|
|
#include "ImageDetConfig.h"
|
|
|
#include "OtherDetect.h"
|
|
|
#include "Define_Error.h"
|
|
|
#include "AI_Edge_Algin.h"
|
|
|
#include "AI_Factory.h"
|
|
|
#include "ImageAllResult.h"
|
|
|
#include "Task.h"
|
|
|
|
|
|
using namespace std;
|
|
|
using namespace cv;
|
|
|
|
|
|
enum AT_THRESHOLD_TYPE_
|
|
|
{
|
|
|
AT_THRESHOLD_TYPE_NULL,
|
|
|
AT_THRESHOLD_TYPE_READY,
|
|
|
AT_THRESHOLD_TYPE_BUSY,
|
|
|
AT_THRESHOLD_TYPE_COMPLETE,
|
|
|
};
|
|
|
|
|
|
// 全局静态变量, 记录图像灰度值异常累计数量
|
|
|
static int g_nImgBrightnessErrorCount = 0;
|
|
|
|
|
|
// 单个把手区域的判定结果
|
|
|
struct Handle_Region_Result_
|
|
|
{
|
|
|
int nIdx; // 区域序号(1开始)
|
|
|
cv::Rect boxRegion; // 区域外接矩形(检测图坐标),宽高用于卡控
|
|
|
bool bFound; // 该区域附近是否找到匹配的把手
|
|
|
cv::Rect roiHandle; // 匹配到的把手 roi(bFound=true 时有效)
|
|
|
Handle_Region_Result_()
|
|
|
{
|
|
|
nIdx = 0;
|
|
|
boxRegion = cv::Rect(0, 0, 0, 0);
|
|
|
bFound = false;
|
|
|
roiHandle = cv::Rect(0, 0, 0, 0);
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// 支架偏移检测的绘制信息(CheckRun 支架块计算 -> DrawResult_Step_1 绘制)
|
|
|
// 坐标均为原图坐标,绘制时经 m_matSrc2Det 映射到检测图后再缩放到结果图
|
|
|
struct Support_Draw_Info_
|
|
|
{
|
|
|
// 参与判定的单个方向:实测/标准距离 + 是否超标准(超标准画红色)
|
|
|
struct Edge_Draw_
|
|
|
{
|
|
|
std::string strEdge; // left/right/up/down
|
|
|
float fDist; // 实测距离(原图像素)
|
|
|
float fStandard; // 标准距离(原图像素)
|
|
|
bool bExceed; // |fDist-fStandard| 超限差(x_offset) -> 红色
|
|
|
cv::Point2f ptEdge; // 连线端点:所计算边缘上、支架中心行/列处的点(原图坐标)
|
|
|
cv::Point2f ptEdgeA; // 所计算边缘线段端点A(原图坐标)
|
|
|
cv::Point2f ptEdgeB; // 所计算边缘线段端点B(原图坐标)
|
|
|
Edge_Draw_()
|
|
|
{
|
|
|
fDist = 0.0f;
|
|
|
fStandard = 0.0f;
|
|
|
bExceed = false;
|
|
|
ptEdge = cv::Point2f(0.0f, 0.0f);
|
|
|
ptEdgeA = cv::Point2f(0.0f, 0.0f);
|
|
|
ptEdgeB = cv::Point2f(0.0f, 0.0f);
|
|
|
}
|
|
|
};
|
|
|
bool bValid; // 本次是否有效计算出支架偏移几何
|
|
|
bool bOffset; // 是否判偏移 NG(十字颜色:红=NG)
|
|
|
cv::Rect rpRect; // 产品区域外接矩形(原图坐标)
|
|
|
cv::Rect rsRect; // 支架区域外接矩形(原图坐标)
|
|
|
cv::Point2f ptCenter; // 支架中心(原图坐标)
|
|
|
std::vector<Edge_Draw_> edgeList; // 各参与判定方向的绘制信息
|
|
|
Support_Draw_Info_()
|
|
|
{
|
|
|
Reset();
|
|
|
}
|
|
|
void Reset()
|
|
|
{
|
|
|
bValid = false;
|
|
|
bOffset = false;
|
|
|
rpRect = cv::Rect(0, 0, 0, 0);
|
|
|
rsRect = cv::Rect(0, 0, 0, 0);
|
|
|
ptCenter = cv::Point2f(0.0f, 0.0f);
|
|
|
edgeList.clear();
|
|
|
}
|
|
|
};
|
|
|
|
|
|
class ImgCheckAnalysisy : public ImgCheckBase
|
|
|
{
|
|
|
|
|
|
public:
|
|
|
ImgCheckAnalysisy();
|
|
|
~ImgCheckAnalysisy();
|
|
|
|
|
|
// 初始化参数 pconfig 参数指针 返回:0 成功 其他异常
|
|
|
int RunStart(void *pconfig1);
|
|
|
|
|
|
// 设置检测数据,并开启检测 返回:0 成AT_THRESHOLD_TYPE_READY功 其他异常
|
|
|
int SetDataRun_SharePtr(std::shared_ptr<ImageAllResult> p);
|
|
|
|
|
|
// 获取结果信息 返回:0 成功 其他异常
|
|
|
int GetCheckReuslt(std::shared_ptr<ImageDetResult> &pResult);
|
|
|
|
|
|
int CheckImg(std::shared_ptr<ImageDetconfig> p, std::shared_ptr<ImageDetResult> &pResult);
|
|
|
int ReJsonResul(std::shared_ptr<ImageDetconfig> p, std::shared_ptr<ImageDetResult> &pResult);
|
|
|
// 获取检测库 状态信息 返回:CHECK_THREAD_RUN_STATUS
|
|
|
int GetStatus();
|
|
|
|
|
|
// 更新参数 pconfig 参数指针,nConfigType 需要更新的参数类型 返回:0 成功 其他异常
|
|
|
int UpdateConfig(void *pconfig, int nConfigType);
|
|
|
|
|
|
std::string GetVersion();
|
|
|
|
|
|
std::string GetErrorInfo();
|
|
|
|
|
|
int creatsavedir();
|
|
|
|
|
|
// 设置模板信息(模板外接矩形 + 模板 Tag blob 轮廓点集)
|
|
|
void SetTplInfo(const cv::RotatedRect &outerRect);
|
|
|
|
|
|
private:
|
|
|
// 加载运行参数
|
|
|
int LoadRunConfig(void *p);
|
|
|
|
|
|
// 加载分析参数
|
|
|
int LoadCheckConfig(void *p);
|
|
|
|
|
|
/// @brief 初始化并且启动程序
|
|
|
/// @return
|
|
|
int InitRun(int nId);
|
|
|
|
|
|
/// @brief 开启检测
|
|
|
/// @return
|
|
|
int StartCheck();
|
|
|
|
|
|
/// @brief 设置空闲
|
|
|
/// @return
|
|
|
int SetIDLE();
|
|
|
|
|
|
private:
|
|
|
// 开启线程
|
|
|
int StartThread(int nId);
|
|
|
// 停止线程
|
|
|
int StopThread();
|
|
|
|
|
|
// 退出系统
|
|
|
int ExitSystem();
|
|
|
|
|
|
// 初始化模型
|
|
|
int InitModel();
|
|
|
|
|
|
cv::Scalar calc_blob_info_withstats(cv::Mat &img, const cv::Mat &mask, cv::Rect &stats, cv::Size k_size = cv::Size(5, 5), int expand = 10, double threshold = 0.7);
|
|
|
// 检测
|
|
|
int CheckRun();
|
|
|
int AI_Edge(const cv::Mat &img, cv::RotatedRect &outerRoi, cv::RotatedRect &innerRoi, std::vector<cv::RotatedRect> &tagroiList);
|
|
|
// ===== 暗场复用明场定位结果(见 Define_Base.h 的 ALIGN_REUSE_* 配置) =====
|
|
|
// 取当前图的产品ID/相机名(优先 productBaseResult/cameraBaseResult,兕底送图信息)
|
|
|
void GetProductCameraStr(std::string &strProduct, std::string &strCamera);
|
|
|
// 判断并在需要时等待"源相机(明场)"的定位结果;成功返回 true(结果已装入成员变量)
|
|
|
// 注意:标签检测不在此复用,由 CheckTagByBigMask 独立执行
|
|
|
bool TryReuseAlignFromSource(std::string &strSrcCamera, std::string &strSrcChannel, int &nWaitMs);
|
|
|
// 发布本图定位结果/失败标记(供同产品其它相机复用)
|
|
|
void PublishAlignShare(bool bSucc);
|
|
|
// 用 outer 定位 mask(bigmask) 检测把手:拟合主体上/下/左/右四条边缘,
|
|
|
// 把边缘外的凸起按连通域分离为把手候选(见 CheckUtil::GetMaskProtrusions),
|
|
|
// 再与参数的把手区域匹配;某个区域附近找不到匹配凸起 → 该区域把手缺失
|
|
|
// -s(存过程图)时输出 {通道}_handle_det.jpg:绿色四边形=拟合主体、红框=凸起(带编号/角/深度)、
|
|
|
// 蓝框=参数把手区域、绿框=匹配到的把手,便于从图像排查
|
|
|
int CheckHandleByBigMask(const cv::Mat &bigmask);
|
|
|
// 标签检测(独立步骤):用 (图像 + bigmask) 跑 Tag_Loc 模型,检出结果存 m_tag_roiList
|
|
|
// 明场传自身 bigmask;暗场不做定位模型,传复用明场的 bigmask
|
|
|
int CheckTagByBigMask(const cv::Mat &img, const cv::Mat &bigmask);
|
|
|
// 在某个把手区域附近找宽高匹配的凸起:返回凸起在 candList 中的下标(-1=没找到)
|
|
|
// 匹配参数(搜索范围 handle_search_ratio、大小比区间 handle_size_min/handle_size_max)
|
|
|
// 可 JSON(Handle_Detect.form.handle_param)配置,未配置时用 cpp 顶部宏默认值,见 ImgCheckAnalysisy.cpp 参数注释
|
|
|
int MatchHandleRegion(const std::vector<Mask_Protrusion_> &candList, const std::vector<bool> &usedList,
|
|
|
const cv::Rect &boxRegion, cv::Rect &roiHandle);
|
|
|
// 计算产品尺寸
|
|
|
int CalProductSize();
|
|
|
// 图片预处理
|
|
|
int ImgPreDet();
|
|
|
|
|
|
// 设置新的检测参数
|
|
|
int SetNewConfig();
|
|
|
|
|
|
ChannelCheckFunction *GetChannelFuntion(std::string strChannelName); // 获得 通道的检测功能
|
|
|
|
|
|
private:
|
|
|
// 图片处理线程
|
|
|
std::shared_ptr<std::thread> ptr_thread_Run;
|
|
|
int Run(int nId); // 运行;
|
|
|
|
|
|
// 图片处理线程
|
|
|
std::shared_ptr<std::thread> ptr_thread_AI;
|
|
|
|
|
|
int set_cpu_id(const std::vector<int> &cpu_set_vec);
|
|
|
|
|
|
// 计算BLob 其他一些属性值。
|
|
|
int CalBlob_Other();
|
|
|
|
|
|
// 分类
|
|
|
int GetClassImg(const cv::Mat &img, cv::Mat &AIdetImg, cv::Rect qx_roi, int detwidth, int detheight);
|
|
|
|
|
|
// 计算缺陷长度
|
|
|
vector<float> Cal_QXLen(cv::Mat qx_maskImg, int qx_type, float fsc_x, float fsc_y);
|
|
|
|
|
|
// 获取检测结果blob,用于后续分析。
|
|
|
int GetCheckResultBLob();
|
|
|
|
|
|
// 获得所有blob
|
|
|
int GetALLBlob();
|
|
|
|
|
|
// 对AI mask图片进行 结果处理
|
|
|
int AIMaskDet();
|
|
|
|
|
|
// 轮廓处理
|
|
|
int Contours();
|
|
|
|
|
|
// 检测初始化
|
|
|
int CheckImgInit();
|
|
|
// 参数 核对
|
|
|
int ConfigCheck(cv::Mat img);
|
|
|
// 多线程方式处理
|
|
|
int AI_Detect_Thread(const cv::Mat &img, cv::Mat &ResultImg);
|
|
|
// 缺陷分类
|
|
|
int AI_QX_Class_Thread();
|
|
|
|
|
|
// 多线程 任务运行管理器
|
|
|
int ThreadTask(int nId); // 运行;
|
|
|
// resize 图片
|
|
|
int ResizeImg();
|
|
|
|
|
|
// AI 推理任务函数
|
|
|
void TaskFun_AIDet(std::shared_ptr<TaskInfo> task);
|
|
|
// 缺陷分类任务函数
|
|
|
void TaskFun_QxClass(std::shared_ptr<TaskInfo> task);
|
|
|
|
|
|
// 更新 检测区域
|
|
|
int Update_DetRoiList();
|
|
|
|
|
|
// 临时绘制结果
|
|
|
int DrawResult_Step_1();
|
|
|
|
|
|
// 参数缺陷类型转 结果参数类型
|
|
|
int AIClassTypeToConfigType(int nAIQXType);
|
|
|
|
|
|
// 更新成像精度
|
|
|
int UpdateImgageScale();
|
|
|
|
|
|
|
|
|
// 把blob 汇总成 检测结果。
|
|
|
int BLobToDetResult();
|
|
|
|
|
|
//自适应参数区域更新
|
|
|
int Adapt_Config(cv::RotatedRect tplOuterRect, cv::RotatedRect curOuterRect, cv::Mat& det_img);
|
|
|
|
|
|
std::shared_ptr<AIFactory> AI_Factory;
|
|
|
|
|
|
private:
|
|
|
int m_nErrorCode; // 错误代码
|
|
|
bool m_bInitSucc; // 初始化状态
|
|
|
bool m_bExit; // 是否退出检测
|
|
|
int m_nThreadIdx; // 线程序号 //相机处理的顺序号,该序号 程序运行就已经固定
|
|
|
|
|
|
std::shared_ptr<AIMulThreadRunBase> runner;
|
|
|
// 所有的检测结果
|
|
|
std::shared_ptr<ImageAllResult> m_pImageAllResult;
|
|
|
std::shared_ptr<DetLog> m_pdetlog;
|
|
|
std::shared_ptr<One_Image_CheckResult_> m_pDetResult; // 检测结果 后续主要对pDetResult 继续分析
|
|
|
std::shared_ptr<shareImage> DetImgInfo_shareP;
|
|
|
|
|
|
// 检测结果
|
|
|
std::shared_ptr<CheckResult> m_CheckResult_shareP;
|
|
|
|
|
|
// 检测参数模块
|
|
|
ConfigBase *m_pConfig;
|
|
|
bool m_bupdateconfig;
|
|
|
int m_nConfigIdx;
|
|
|
// 线程运行的一些参数
|
|
|
RunInfoST m_RunConfig;
|
|
|
|
|
|
float m_fImgage_Scale_X;
|
|
|
float m_fImgage_Scale_Y;
|
|
|
|
|
|
// 分析参数
|
|
|
AnalysisyConfigST m_AnalysisyConfig;
|
|
|
ChannelCheckFunction *m_pFuntion;
|
|
|
BaseCheckFunction *m_pbaseCheckFunction; // 基础检测
|
|
|
CommonConfigNodeST *m_pCommonAnalysisyConfig;
|
|
|
BasicConfig *m_pBasicConfig;
|
|
|
RegionConfigST *m_pRegionAnalysisyParam; // 分析参数
|
|
|
int m_QxInParamListIdx[CONFIG_QX_NAME_count];
|
|
|
|
|
|
cv::Rect m_outer_roi;
|
|
|
cv::Rect m_inner_roi;
|
|
|
cv::Rect m_Crop_Roi_paramImg; // 裁切在参数模板图上的 位置。
|
|
|
|
|
|
// 检测图裁剪坐标映射(不做旋转摆正):用 m_outer_rroi 外接区域裁剪,原图 -> 检测图为平移
|
|
|
cv::Mat m_matSrc2Det; // 原图 -> 检测图(裁剪) 2x3 仿射矩阵(纯平移)
|
|
|
cv::Mat m_matDet2Src; // 检测图(裁剪) -> 原图 2x3 仿射矩阵(纯平移)
|
|
|
cv::Mat m_matParam2Det; // 参数(模板)坐标 -> 检测图(裁剪) 2x3 仿射矩阵
|
|
|
cv::Rect m_deskewPadRoi; // 检测图在原图上的裁剪区域
|
|
|
|
|
|
std::string m_strCurDetChannel; // 当前处理的图片通道
|
|
|
|
|
|
// // 检测控制参数
|
|
|
// CheckControlConfigSt *m_pcheckControlConfig;
|
|
|
int m_nRun_Status; // 运行状态:空闲,运行中,异常,。。。。。
|
|
|
|
|
|
int m_nCheckResultErrorCode;
|
|
|
|
|
|
Detect_ROI_Config m_DetRoiList; // 检测区域roi List
|
|
|
|
|
|
ERROR_DOTS_BLOBS blobs;
|
|
|
|
|
|
OtherDet_Config m_OtherDet_Config;
|
|
|
|
|
|
AI_Edge_Algin m_pAI_Edge_Algin;
|
|
|
// 边缘定位结果
|
|
|
std::shared_ptr<AI_Edge_Algin::Edge_AI_Result> m_pEdge_Align_Result;
|
|
|
std::vector<QXImageResult> m_Draw_qxImageResult; // 缺陷小图结果
|
|
|
|
|
|
std::vector<cv::Rect> SmallRoiList;
|
|
|
|
|
|
std::string m_strRootPath_TA_cls;
|
|
|
std::string m_strRootPath_CA_cls;
|
|
|
std::string m_strSavePath_cls;
|
|
|
std::string m_strLastDate;
|
|
|
|
|
|
ImageStorage *m_pImageStorage;
|
|
|
|
|
|
// AI 推理的所有结果, 可能会返回去。需要临时存储。
|
|
|
std::queue<std::shared_ptr<AIMulThreadRunBase::AITask>> m_AIMaskImgBLobQueue;
|
|
|
std::mutex mtx_AIMaskImgBLobQueue;
|
|
|
|
|
|
Task m_task;
|
|
|
std::shared_ptr<TaskInfo> m_AItask;
|
|
|
std::shared_ptr<TaskInfo> m_Classtask; // 缺陷分类任务
|
|
|
|
|
|
// AI mask 在这一列是否有 缺陷残点,用以 加速 blob 分析。
|
|
|
unsigned char *m_ImgBlobHFlagData;
|
|
|
|
|
|
// 原始区域数据
|
|
|
Rect m_old_productROI = Rect(0, 0, 0, 0);
|
|
|
std::vector<cv::Point> m_old_cur_edgeDet_region;
|
|
|
std::vector<cv::Point> m_old_cur_markLine_region;
|
|
|
cv::Point m_old_cur_markLine_mark1;
|
|
|
cv::Point m_old_cur_markLine_mark2;
|
|
|
std::vector<RegionConfigST> m_old_cur_regionConfigArr;
|
|
|
|
|
|
// 模板信息
|
|
|
cv::RotatedRect m_tplOuterRect; // 模板外接矩形
|
|
|
cv::RotatedRect m_outer_rroi;
|
|
|
cv::RotatedRect m_inner_rroi;
|
|
|
std::vector<cv::RotatedRect> m_tag_roiList;
|
|
|
|
|
|
// 把手检测结果(从 outer 定位 mask 分离的凸起区域 + 各把手区域判定结果)
|
|
|
std::vector<Mask_Protrusion_> m_HandleProtrusionList; // 分离出的凸起区域(把手候选:roi/质心/深度/就近角等)
|
|
|
std::vector<Handle_Region_Result_> m_HandleRegionResultList; // 各把手区域(最多4个)的判定结果
|
|
|
std::vector<cv::Point2f> m_HandleBodyQuad; // 拟合出的主体四边形(TL/TR/BR/BL,原图坐标;支架偏移检测复用其四边抗凸起)
|
|
|
bool m_bHandleDetSucc; // 本次是否完成把手检测
|
|
|
bool m_bHandleFound; // 所有非空把手区域是否都找到了把手
|
|
|
bool m_bHandleExpect; // 是否开启了把手缺失检测(且有非空把手区域)
|
|
|
// 支架偏移检测的绘制信息(CheckRun 支架块填充,DrawResult_Step_1 绘制)
|
|
|
Support_Draw_Info_ m_SupportDrawInfo;
|
|
|
};
|
|
|
|
|
|
#endif |