You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

387 lines
14 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* @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) -> 红色
Edge_Draw_()
{
fDist = 0.0f;
fStandard = 0.0f;
bExceed = false;
}
};
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个)的判定结果
bool m_bHandleDetSucc; // 本次是否完成把手检测
bool m_bHandleFound; // 所有非空把手区域是否都找到了把手
bool m_bHandleExpect; // 是否开启了把手缺失检测(且有非空把手区域)
// 支架偏移检测的绘制信息(CheckRun 支架块填充,DrawResult_Step_1 绘制)
Support_Draw_Info_ m_SupportDrawInfo;
};
#endif