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.

2653 lines
80 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:50:00
* @LastEditTime: 2025-09-23 11:34:53
* @LastEditors: xiewenji 527774126@qq.com
* @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
* @FilePath: /ZCXD_MonitorPlatform/src/CoreLogicModule/src/CamDeal.cpp
*/
#include "ImgCheckAnalysisy.hpp"
#include "CheckUtil.hpp"
#include "Define.h"
#include <omp.h>
#include "AICommonDefine.h"
// 用于排序轮廓的比较函数
static bool compareContourAreas(const vector<Point> &contour1, const vector<Point> &contour2)
{
double i = contourArea(contour1);
double j = contourArea(contour2);
return (i > j);
}
ImgCheckAnalysisy::ImgCheckAnalysisy()
: m_pAI_Edge_Algin(m_pdetlog)
{
m_nErrorCode = CHECK_OK;
m_nThreadIdx = -1;
m_bInitSucc = false;
m_bExit = false;
m_nRun_Status = CHECK_THREAD_STATUS_IDLE;
m_fImgage_Scale_X = 0.03f;
m_fImgage_Scale_Y = 0.03f;
m_pBasicConfig = NULL;
m_strCurDetChannel = "";
m_bupdateconfig = false;
m_pbaseCheckFunction = &m_AnalysisyConfig.baseFunction;
m_strLastDate = "";
m_strRootPath_TA_cls = "/home/aidlux/BOE/Cls/TA/";
m_strRootPath_CA_cls = "/home/aidlux/BOE/Cls/CA/";
creatsavedir();
m_pImageStorage = ImageStorage::getInstance();
m_nConfigIdx = -1;
m_ImgBlobHFlagData = NULL;
}
ImgCheckAnalysisy::~ImgCheckAnalysisy()
{
ExitSystem();
if (m_ImgBlobHFlagData)
{
delete[] m_ImgBlobHFlagData;
m_ImgBlobHFlagData = NULL;
}
}
int ImgCheckAnalysisy::UpdateConfig(void *pconfig, int nConfigType)
{
int re = 0;
switch (nConfigType)
{
case CHECK_CONFIG_Run:
re = LoadRunConfig(pconfig);
if (re == 0)
{
// printf("---> LoadRunConfig Succ\n");
}
else
{
printf("---> LoadRunConfig Fail\n");
}
break;
case CHECK_CONFIG_Module:
re = LoadCheckConfig(pconfig);
if (re == 0)
{
// printf("---> LoadAnalysisConfig Succ\n");
}
else
{
printf("---> LoadAnalysisConfig Fail\n");
}
break;
default:
break;
}
return re;
}
int ImgCheckAnalysisy::RunStart(void *pconfig1)
{
// 1 、更新参数 并判断参数是否合法
int re = CHECK_OK;
re = SetNewConfig();
if (CHECK_OK != re)
{
m_nErrorCode = re;
return m_nErrorCode;
}
// printf("---> RunStart Start m_RunConfig.nThreadIdx %d \n", m_RunConfig.nThreadIdx);
m_nThreadIdx = m_RunConfig.nThreadIdx;
re = InitRun(m_RunConfig.nCpu_start_Idx);
if (CHECK_OK != re)
{
m_nErrorCode = re;
return m_nErrorCode;
}
runner = std::make_shared<AIMulThreadRunBase>();
runner->Start();
m_nErrorCode = CHECK_OK;
// printf("ImgCheckAnalysisy >>>> ImgCheckThread %d Start Succ \n", m_nThreadIdx);
return m_nErrorCode;
}
int ImgCheckAnalysisy::SetDataRun_SharePtr(std::shared_ptr<ImageAllResult> p)
{
// 设置正在检测
m_pImageAllResult = p;
DetImgInfo_shareP = p->result->in_shareImage;
m_CheckResult_shareP = p->result;
m_pImageAllResult->setStep(ImageAllResult::DetStep_Deting);
m_pdetlog = p->detlog;
m_pDetResult = p->pDetResult;
StartCheck();
m_nErrorCode = CHECK_OK;
return m_nErrorCode;
}
int ImgCheckAnalysisy::GetCheckReuslt(std::shared_ptr<ImageDetResult> &pResult)
{
m_CheckResult_shareP.reset();
DetImgInfo_shareP.reset();
SetIDLE();
// m_nErrorCode = CHECK_OK;
// printf("4 DetImgInfo_shareP count %ld m_nCheckResultErrorCode %d \n", DetImgInfo_shareP.use_count(), m_nCheckResultErrorCode);
return m_nCheckResultErrorCode;
}
int ImgCheckAnalysisy::CheckImg(std::shared_ptr<ImageDetconfig> p, std::shared_ptr<ImageDetResult> &pResult)
{
return 0;
}
int ImgCheckAnalysisy::ReJsonResul(std::shared_ptr<ImageDetconfig> p, std::shared_ptr<ImageDetResult> &pResult)
{
return 0;
}
int ImgCheckAnalysisy::InitRun(int nId)
{
int re = CHECK_OK;
if (m_bInitSucc)
{
return CHECK_OK;
}
InitModel();
AI_Factory = AIFactory::GetInstance();
m_nRun_Status = CHECK_THREAD_STATUS_IDLE;
re = StartThread(nId);
if (CHECK_OK != re)
{
return re;
}
m_bInitSucc = true;
return re;
}
int ImgCheckAnalysisy::GetStatus()
{
return m_nRun_Status;
}
std::string ImgCheckAnalysisy::GetVersion()
{
return std::string("BOE_1.1.0");
}
std::string ImgCheckAnalysisy::GetErrorInfo()
{
std::string str = GetErrorCodeInfo(m_nErrorCode);
printf("%s\n", str.c_str());
return str;
}
int ImgCheckAnalysisy::creatsavedir()
{
std::string curDate = CheckUtil::getCurrentDate();
if (curDate == m_strLastDate)
{
return 0;
}
m_strLastDate = curDate;
m_strRootPath_TA_cls += m_strLastDate + "/";
m_strRootPath_CA_cls += m_strLastDate + "/";
for (int i = 0; i < AI_CLass_QX_NAME_count; i++)
{
CheckUtil::CreateDir(m_strRootPath_TA_cls + std::to_string(i) + "/");
CheckUtil::CreateDir(m_strRootPath_CA_cls + std::to_string(i) + "/");
}
return 0;
}
int ImgCheckAnalysisy::LoadRunConfig(void *p)
{
if (p == NULL)
{
m_nErrorCode = CHECK_ERROR_Config_Null;
return m_nErrorCode;
}
RunInfoST *pconfig = (RunInfoST *)p;
m_RunConfig.copy(*pconfig);
return CHECK_OK;
}
int ImgCheckAnalysisy::LoadCheckConfig(void *p)
{
if (p == NULL)
{
m_nErrorCode = CHECK_ERROR_Config_Null;
return m_nErrorCode;
}
m_pConfig = (ConfigBase *)p;
m_nConfigIdx = m_pConfig->GetConfigIdx();
m_nErrorCode = CHECK_OK;
return m_nErrorCode;
}
// 开启检测
int ImgCheckAnalysisy::StartCheck()
{
m_nRun_Status = CHECK_THREAD_STATUS_READY;
return 0;
}
int ImgCheckAnalysisy::SetIDLE()
{
// 更新参数
SetNewConfig();
m_nRun_Status = CHECK_THREAD_STATUS_IDLE;
return 0;
}
int ImgCheckAnalysisy::StartThread(int nId)
{
// 开启检测线程
ptr_thread_Run = std::make_shared<std::thread>(std::bind(&ImgCheckAnalysisy::Run, this, nId));
if (!m_RunConfig.bRetest)
{
ptr_thread_AI = std::make_shared<std::thread>(std::bind(&ImgCheckAnalysisy::ThreadTask, this, nId + 1));
}
return 0;
}
int ImgCheckAnalysisy::StopThread()
{
m_bExit = true;
if (ptr_thread_Run != nullptr)
{
if (ptr_thread_Run->joinable())
{
ptr_thread_Run->join();
}
}
if (ptr_thread_AI != nullptr)
{
if (ptr_thread_AI->joinable())
{
ptr_thread_AI->join();
}
}
return 0;
}
int ImgCheckAnalysisy::ExitSystem()
{
StopThread();
return 0;
}
int ImgCheckAnalysisy::InitModel()
{
// 获取当前gpu号确定的 AI处理线程
m_OtherDet_Config.nDeviceId = m_RunConfig.nDeviceId;
m_pAI_Edge_Algin.Init(&m_OtherDet_Config);
m_pAI_Edge_Algin.InitModel_ALL();
return 0;
}
cv::Scalar ImgCheckAnalysisy::calc_blob_info_withstats(cv::Mat &img, const cv::Mat &mask, cv::Rect &stats, cv::Size k_size, int expand, double threshold)
{
// 解包 statsx, y, w, h, area
int x = stats.x, y = stats.y, w = stats.width, h = stats.height;
// 将图像转换为灰度图像
// 计算感兴趣区域 (ROI)
cv::Rect roi(x - expand, y - expand, w + 2 * expand, h + 2 * expand);
roi &= cv::Rect(0, 0, img.cols, img.rows); // 确保ROI在图像内
roi &= cv::Rect(0, 0, mask.cols, mask.rows); // 确保ROI在mask内
// 检查 mask 是否有效
if (mask.empty() || roi.width <= 0 || roi.height <= 0)
{
return cv::Scalar(0, 0, 0);
}
cv::Mat cimg = img(roi);
// cv::cvtColor(cimg, cimg, cv::COLOR_BGR2GRAY);
// return cv::Scalar(0, 0, 0);
cv::Mat cmask = mask(roi);
// getchar();
// 扩张掩膜
cv::Scalar mean_bk = cv::mean(cimg, ~cmask);
double fbk = mean_bk[0];
cv::Scalar mean_det = cv::mean(cimg, cmask);
double fdet = mean_det[0];
// 计算差异图像
cv::Mat diff = cv::abs(cimg - fbk);
// cv::imwrite("cimg.png",cimg);
// cv::imwrite("cmask.png",cmask);
// printf("%f %f - %f \n",fbk,fdet,fbk-fdet);
// getchar();
// diff = diff.mul(cmask > 0);
cv::Mat masked_image;
diff.copyTo(masked_image, cmask);
// 计算能量
double energy = cv::sum(masked_image)[0];
// 计算 hj差异图像大于0的像素均值
// double hj = std::abs(fbk - fdet);
// double hj = CheckUtil::CalHj(cimg, cmask, mean_bk.val[0]);
double hj = CheckUtil::CalHjWeighted(cimg, cmask, mean_bk.val[0], 2.0f);
int worb = 0;
if (fdet >= fbk)
{
worb = 1;
}
// cv::imwrite("cimg.png", cimg);
// cv::imwrite("cmask.png", cmask);
// cv::imwrite("diff.png", diff);
// cv::imwrite("masked_image.png", masked_image);
// printf("fbk %f fdet %f energy %f\n", fbk, fdet, energy);
// getchar();
return cv::Scalar(worb, energy, hj);
}
Point2f GetCoorPoint(Point2f point, Mat img_mat)
{
// 越界判定
int coor_img_rect_x = point.x-400;
int coor_img_rect_y = point.y-400;
int coor_img_rect_w = 800;
int coor_img_rect_h = 800;
if (coor_img_rect_x < 0)
{
coor_img_rect_x = 0;
coor_img_rect_w = min(400, img_mat.cols);
}
if (coor_img_rect_y < 0)
{
coor_img_rect_y = 0;
coor_img_rect_h = min(400, img_mat.rows);
}
if (coor_img_rect_x + coor_img_rect_w > img_mat.cols)
{
coor_img_rect_w = img_mat.cols - coor_img_rect_x;
}
if (coor_img_rect_y + coor_img_rect_h > img_mat.rows)
{
coor_img_rect_h = img_mat.rows - coor_img_rect_y;
}
if (coor_img_rect_x < 0 || coor_img_rect_y < 0 || coor_img_rect_x + coor_img_rect_w > img_mat.cols || coor_img_rect_y + coor_img_rect_h > img_mat.rows)
{
return point;
}
Mat coor_img_mat = img_mat(Rect(coor_img_rect_x, coor_img_rect_y, coor_img_rect_w, coor_img_rect_h));
Mat coor_img_bin;
threshold(coor_img_mat, coor_img_bin, 50, 255, THRESH_BINARY);
// 6. 查找轮廓
std::vector<std::vector<cv::Point>> contours;
cv::findContours(coor_img_bin, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
if (contours.empty())
{
return point;
}
double maxArea = 0;
int maxAreaIdx = -1;
for (size_t i = 0; i < contours.size(); ++i)
{
double area = cv::contourArea(contours[i]);
if (area > maxArea)
{
maxArea = area;
maxAreaIdx = i;
}
}
if (maxAreaIdx < 0 || maxArea < 100)
{
return point;
}
cv::RotatedRect rect = cv::minAreaRect(contours[maxAreaIdx]);
Point2f vertices[4];
rect.points(vertices);
int cornerIdx = 0;
float minDist = FLT_MAX;
for (int i = 0; i < 4; i++)
{
float dist = std::pow(vertices[i].x - 400, 2) + std::pow(vertices[i].y - 400, 2);
if (dist < minDist)
{
minDist = dist;
cornerIdx = i;
}
}
Point2f new_point;
new_point.x = vertices[cornerIdx].x + coor_img_rect_x;
new_point.y = vertices[cornerIdx].y + coor_img_rect_y;
new_point.x = std::max(0.0f, std::min(new_point.x, static_cast<float>(img_mat.cols - 1)));
new_point.y = std::max(0.0f, std::min(new_point.y, static_cast<float>(img_mat.rows - 1)));
return new_point;
}
int GetEdgeRoi(Mat img, Rect &new_roi, cv::RotatedRect &rotated_roi, float scale_x, float scale_y){
if (img.empty())
{
return 1;
}
// ============ Stage 1: 粗定位(大尺度缩小,速度快)============
Mat r_img;
int resize_width = static_cast<int>(img.cols / scale_x);
int resize_height = static_cast<int>(img.rows / scale_y);
resize(img, r_img, Size(resize_width, resize_height), 0, 0, INTER_LINEAR);
// 二值化找最大连通域
Mat r_img_bin;
threshold(r_img, r_img_bin, 15, 255, THRESH_BINARY);
std::vector<std::vector<cv::Point>> contours;
cv::findContours(r_img_bin, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
if (contours.empty())
{
return 2;
}
double maxArea = 0;
int maxAreaIdx = -1;
for (size_t i = 0; i < contours.size(); ++i)
{
double area = cv::contourArea(contours[i]);
if (area > maxArea)
{
maxArea = area;
maxAreaIdx = i;
}
}
if (maxAreaIdx < 0)
{
return 3;
}
// 使用minAreaRect获取带旋转角度的最小外接矩形
cv::RotatedRect coarse_rotated_tmp = cv::minAreaRect(contours[maxAreaIdx]);
cv::RotatedRect coarse_rotated;
coarse_rotated.center.x = coarse_rotated_tmp.center.x * scale_x;
coarse_rotated.center.y = coarse_rotated_tmp.center.y * scale_y;
coarse_rotated.size.width = coarse_rotated_tmp.size.width * scale_x;
coarse_rotated.size.height = coarse_rotated_tmp.size.height * scale_y;
coarse_rotated.angle = coarse_rotated_tmp.angle;
cv::Rect coarse_roi = coarse_rotated.boundingRect();
coarse_roi.x = std::max(0, coarse_roi.x);
coarse_roi.y = std::max(0, coarse_roi.y);
coarse_roi.width = std::min(coarse_roi.width, img.cols - coarse_roi.x);
coarse_roi.height = std::min(coarse_roi.height, img.rows - coarse_roi.y);
// ============ Stage 2: 精修(小尺度,只处理裁剪后的局部区域)============
// 粗定位精度损失约 scale_x/scale_y 个像素,扩展 margin 确保包含真实边界
const float fine_scale = 4.0f; // 精修阶段缩放倍率,越小越精确
int margin_x = static_cast<int>(scale_x * 2); // 补偿粗定位误差
int margin_y = static_cast<int>(scale_y * 2);
Rect fine_roi;
fine_roi.x = std::max(0, coarse_roi.x - margin_x);
fine_roi.y = std::max(0, coarse_roi.y - margin_y);
fine_roi.width = std::min(coarse_roi.width + 2 * margin_x, img.cols - fine_roi.x);
fine_roi.height = std::min(coarse_roi.height + 2 * margin_y, img.rows - fine_roi.y);
Mat fine_region = img(fine_roi);
int fine_w = static_cast<int>(fine_region.cols / fine_scale);
int fine_h = static_cast<int>(fine_region.rows / fine_scale);
// 精修区域足够大时才做细化
if (fine_w > 50 && fine_h > 50)
{
Mat fine_resized;
resize(fine_region, fine_resized, Size(fine_w, fine_h), 0, 0, INTER_LINEAR);
Mat fine_bin;
threshold(fine_resized, fine_bin, 15, 255, THRESH_BINARY);
std::vector<std::vector<cv::Point>> fine_contours;
cv::findContours(fine_bin, fine_contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
if (!fine_contours.empty())
{
double fine_maxArea = 0;
int fine_maxIdx = -1;
for (size_t i = 0; i < fine_contours.size(); ++i)
{
double area = cv::contourArea(fine_contours[i]);
if (area > fine_maxArea)
{
fine_maxArea = area;
fine_maxIdx = i;
}
}
if (fine_maxIdx >= 0)
{
// 使用minAreaRect获取带旋转角度的最小外接矩形保留旋转信息
cv::RotatedRect fine_rotated = cv::minAreaRect(fine_contours[fine_maxIdx]);
// 映射回原图坐标center缩放+平移size按比例缩放角度不变
rotated_roi.center.x = fine_rotated.center.x * fine_scale + fine_roi.x;
rotated_roi.center.y = fine_rotated.center.y * fine_scale + fine_roi.y;
rotated_roi.size.width = fine_rotated.size.width * fine_scale;
rotated_roi.size.height = fine_rotated.size.height * fine_scale;
rotated_roi.angle = fine_rotated.angle;
// 取旋转矩形的轴对齐外接框作为new_roi用于ROI裁剪等场景
cv::Rect fine_small = rotated_roi.boundingRect();
Rect refined_roi;
refined_roi.x = fine_small.x;
refined_roi.y = fine_small.y;
refined_roi.width = fine_small.width;
refined_roi.height = fine_small.height;
refined_roi.x = std::max(0, refined_roi.x);
refined_roi.y = std::max(0, refined_roi.y);
refined_roi.width = std::min(refined_roi.width, img.cols - refined_roi.x);
refined_roi.height = std::min(refined_roi.height, img.rows - refined_roi.y);
new_roi = refined_roi;
return 0;
}
}
}
// 精修失败则回退到粗定位结果
new_roi = coarse_roi;
rotated_roi = coarse_rotated;
return 0;
}
std::vector<cv::Point2f> sort_vertices(cv::RotatedRect rrect) {
cv::Point2f pts[4];
rrect.points(pts);
std::vector<cv::Point2f> vertices(pts, pts + 4);
// 按 y 坐标升序排序
std::sort(vertices.begin(), vertices.end(),
[](const cv::Point2f& a, const cv::Point2f& b) {
return a.y < b.y;
});
if (vertices[0].x > vertices[1].x)
std::swap(vertices[0], vertices[1]);
if (vertices[2].x > vertices[3].x)
std::swap(vertices[2], vertices[3]);
return vertices;
}
int ImgCheckAnalysisy::Adapt_Config(Mat img, Rect cur_roi, bool b_update){
if (img.empty()) {
std::cerr << "Error: Input image 'img' is empty!" << std::endl;
return -1;
}
if(!b_update){
return 1;
}
cv::RotatedRect rot_cur_roi;
int get_edge_roi = GetEdgeRoi(img, cur_roi, rot_cur_roi, 20, 20);
if(get_edge_roi != 0){
return 2;
}
m_pdetlog->AddCheckstr(PrintLevel_0, "Adapt_Config", "-------------------start--------------");
/*计算xy偏移缩放比例*/
// 拷贝原始数据old_productROI 使用 markLine.region 的 minAreaRect保留旋转角度
if(m_old_productROI.size.width == 0 || m_old_productROI.size.height == 0){
m_old_productROI = cv::minAreaRect(m_AnalysisyConfig.baseFunction.markLine.region);
m_old_cur_edgeDet_region = m_AnalysisyConfig.baseFunction.edgeDet.region;
m_old_cur_markLine_region = m_AnalysisyConfig.baseFunction.markLine.region;
m_old_cur_markLine_mark1 = m_AnalysisyConfig.baseFunction.markLine.mark_local_1;
m_old_cur_markLine_mark2 = m_AnalysisyConfig.baseFunction.markLine.mark_local_2;
m_old_cur_regionConfigArr = m_AnalysisyConfig.commonCheckConfig.nodeConfigArr[0].regionConfigArr;
m_old_cur_traditional_region = m_AnalysisyConfig.baseFunction.traditionDet.detArea;
}
/*计算old_roi到new_roi的完整仿射变换矩阵(平移+缩放+旋转)*/
// old使用 minAreaRect(region) 的顶点new使用 GetEdgeRoi 检测到的旋转矩形顶点
vector<cv::Point2f> old_vertices = sort_vertices(m_old_productROI);
vector<cv::Point2f> new_vertices = sort_vertices(rot_cur_roi);
cv::Point2f src_pts[3] = {
old_vertices[0], // 左上
old_vertices[1], // 右上
old_vertices[2] // 左下
};
cv::Point2f dst_pts[3] = {
new_vertices[0], // 对应左上
new_vertices[1], // 对应右上
new_vertices[2] // 对应左下
};
cv::Mat affine_mat = cv::getAffineTransform(src_pts, dst_pts);
m_pdetlog->AddCheckstr(PrintLevel_0, "Adapt_Config", "affine_mat = [%f %f %f; %f %f %f]",
affine_mat.at<double>(0,0), affine_mat.at<double>(0,1), affine_mat.at<double>(0,2),
affine_mat.at<double>(1,0), affine_mat.at<double>(1,1), affine_mat.at<double>(1,2));
// 单点仿射变换的lambda (直接使用矩阵,涵盖平移+缩放+旋转)
auto affinePoint = [&](const cv::Point& p) -> cv::Point {
return cv::Point(
cvRound(affine_mat.at<double>(0,0) * p.x + affine_mat.at<double>(0,1) * p.y + affine_mat.at<double>(0,2)),
cvRound(affine_mat.at<double>(1,0) * p.x + affine_mat.at<double>(1,1) * p.y + affine_mat.at<double>(1,2))
);
};
/*获取待修改的region引用*/
std::vector<cv::Point>& cur_edgeDet_region = m_AnalysisyConfig.baseFunction.edgeDet.region;
std::vector<cv::Point>& cur_markLine_region = m_AnalysisyConfig.baseFunction.markLine.region;
cv::Point& cur_markLine_mark1 = m_AnalysisyConfig.baseFunction.markLine.mark_local_1;
cv::Point& cur_markLine_mark2 = m_AnalysisyConfig.baseFunction.markLine.mark_local_2;
std::vector<RegionConfigST>& cur_regionConfigArr = m_AnalysisyConfig.commonCheckConfig.nodeConfigArr[0].regionConfigArr;
std::vector<cv::Point>& cur_traditional_region = m_AnalysisyConfig.baseFunction.traditionDet.detArea;
// if (img.empty())
// {
// return 0;
// }
// Mat show_img = img.clone();
// cvtColor(show_img, show_img, COLOR_GRAY2BGR);
// // 确保 productROI 在图像范围内
// cv::Rect safe_roi = m_AnalysisyConfig.baseFunction.markLine.productROI;
// safe_roi &= cv::Rect(0, 0, show_img.cols, show_img.rows);
// if (safe_roi.width > 0 && safe_roi.height > 0)
// {
// cv::rectangle(show_img, safe_roi, Scalar(255,255,255), 5);
// }
// if (cur_edgeDet_region.size() >= 2)
// {
// for(size_t i = 0 ; i < cur_edgeDet_region.size() - 1; i++){
// cv::line(show_img, cur_edgeDet_region[i], cur_edgeDet_region[i+1], Scalar(0,255,0), 20);
// }
// cv::line(show_img, cur_edgeDet_region.back(), cur_edgeDet_region.front(), Scalar(0,255,0), 20);
// }
// if (cur_markLine_region.size() >= 2)
// {
// for(size_t i = 0 ; i < cur_markLine_region.size() - 1; i++){
// cv::line(show_img, cur_markLine_region[i], cur_markLine_region[i+1], Scalar(0,0,255), 20);
// }
// cv::line(show_img, cur_markLine_region.back(), cur_markLine_region.front(), Scalar(0,0,255), 20);
// }
// for(size_t i = 0 ; i < cur_regionConfigArr.size(); i++){
// if (cur_regionConfigArr[i].basicInfo.pointArry.size() >= 2)
// {
// for(size_t j = 0; j < cur_regionConfigArr[i].basicInfo.pointArry.size() - 1; j++){
// cv::line(show_img, cur_regionConfigArr[i].basicInfo.pointArry[j], cur_regionConfigArr[i].basicInfo.pointArry[j+1], Scalar(255,0,0), 10);
// }
// cv::line(show_img, cur_regionConfigArr[i].basicInfo.pointArry.back(), cur_regionConfigArr[i].basicInfo.pointArry.front(), Scalar(255,0,0), 10);
// }
// }
// imwrite(m_AnalysisyConfig.commonCheckConfig.baseConfig.strCamearName +"_org_img.tiff", show_img);
/*使用仿射矩阵进行修改*/
// rect
m_AnalysisyConfig.baseFunction.markLine.productROI = cur_roi;
// point
cur_markLine_mark1 = affinePoint(m_old_cur_markLine_mark1);
cur_markLine_mark2 = affinePoint(m_old_cur_markLine_mark2);
// region
for(int i = 0; i < cur_edgeDet_region.size(); i++){
cur_edgeDet_region[i] = affinePoint(m_old_cur_edgeDet_region[i]);
}
for(int i = 0; i < cur_markLine_region.size(); i++){
cur_markLine_region[i] = affinePoint(m_old_cur_markLine_region[i]);
}
for(int i = 0 ; i < cur_regionConfigArr.size(); i++){
for(int j = 0; j < cur_regionConfigArr[i].basicInfo.pointArry.size(); j++){
cur_regionConfigArr[i].basicInfo.pointArry[j] = affinePoint(m_old_cur_regionConfigArr[i].basicInfo.pointArry[j]);
}
}
for(int i = 0; i < cur_traditional_region.size(); i++){
cur_traditional_region[i] = affinePoint(m_old_cur_traditional_region[i]);
}
/*show*/
// if (img.empty())
// {
// return 0;
// }
// show_img = img.clone();
// cvtColor(show_img, show_img, COLOR_GRAY2BGR);
// // 确保 productROI 在图像范围内
// safe_roi = m_AnalysisyConfig.baseFunction.markLine.productROI;
// safe_roi &= cv::Rect(0, 0, show_img.cols, show_img.rows);
// if (safe_roi.width > 0 && safe_roi.height > 0)
// {
// cv::rectangle(show_img, safe_roi, Scalar(255,255,255), 5);
// }
// if (cur_edgeDet_region.size() >= 2)
// {
// for(size_t i = 0 ; i < cur_edgeDet_region.size() - 1; i++){
// cv::line(show_img, cur_edgeDet_region[i], cur_edgeDet_region[i+1], Scalar(0,255,0), 20);
// }
// cv::line(show_img, cur_edgeDet_region.back(), cur_edgeDet_region.front(), Scalar(0,255,0), 20);
// }
// if (cur_markLine_region.size() >= 2)
// {
// for(size_t i = 0 ; i < cur_markLine_region.size() - 1; i++){
// cv::line(show_img, cur_markLine_region[i], cur_markLine_region[i+1], Scalar(0,0,255), 20);
// }
// cv::line(show_img, cur_markLine_region.back(), cur_markLine_region.front(), Scalar(0,0,255), 20);
// }
// for(size_t i = 0 ; i < cur_regionConfigArr.size(); i++){
// if (cur_regionConfigArr[i].basicInfo.pointArry.size() >= 2)
// {
// for(size_t j = 0; j < cur_regionConfigArr[i].basicInfo.pointArry.size() - 1; j++){
// cv::line(show_img, cur_regionConfigArr[i].basicInfo.pointArry[j], cur_regionConfigArr[i].basicInfo.pointArry[j+1], Scalar(255,0,0), 10);
// }
// cv::line(show_img, cur_regionConfigArr[i].basicInfo.pointArry.back(), cur_regionConfigArr[i].basicInfo.pointArry.front(), Scalar(255,0,0), 10);
// }
// }
// imwrite(m_AnalysisyConfig.commonCheckConfig.baseConfig.strCamearName +"_show_img.tiff", show_img);
return 0;
}
int ImgCheckAnalysisy::CheckRun()
{
// printf(">>>%s ================start \n", m_pImageAllResult->strBaseInfo.c_str());
long t1, t2, t3, t4, t5, t6, t7;
SetNewConfig();
t1 = CheckUtil::getcurTime();
CheckImgInit();
if (DetImgInfo_shareP->bsaveProcessImg)
{
m_pdetlog->bPrintStr = true;
}
m_pdetlog->bPrintStr = true;
m_pdetlog->AddCheckstr(PrintLevel_0, "1、basic Info", "---------------------------1、basic Info---------------------------------");
m_pdetlog->AddCheckstr(PrintLevel_0, "Version", "%s", GetVersion().c_str());
m_pdetlog->AddCheckstr(PrintLevel_0, "Updateconfig", "%d", m_bupdateconfig);
m_pdetlog->AddCheckstr(PrintLevel_0, "Start", "%s", m_pImageAllResult->strBaseInfo.c_str());
m_pdetlog->AddCheckstr(PrintLevel_0, "ImgageScale", "Scale_X = %f Scale_Y = %f", m_fImgage_Scale_X, m_fImgage_Scale_Y);
m_bupdateconfig = false;
// 返回结果状态初始化
m_CheckResult_shareP->checkStatus = 1;
m_CheckResult_shareP->nresult = -1;
m_CheckResult_shareP->basicResult.img_id = m_CheckResult_shareP->in_shareImage->img_id;
m_CheckResult_shareP->basicResult.imgtype = m_CheckResult_shareP->in_shareImage->imgtype;
m_CheckResult_shareP->basicResult.imgstr = m_CheckResult_shareP->in_shareImage->imgstr;
m_CheckResult_shareP->basicResult.strChannel = m_CheckResult_shareP->in_shareImage->strChannel;
m_strCurDetChannel = m_CheckResult_shareP->basicResult.strChannel;
/*自适应更新参数*/
long time_adapt_s = CheckUtil::getcurTime();
cv::RotatedRect rot_cur_roi;
Adapt_Config(m_CheckResult_shareP->in_shareImage->img, m_CutRoi, m_pbaseCheckFunction->markLine.badapt_region);
long time_adapt_e = CheckUtil::getcurTime();
m_pdetlog->AddCheckstr(PrintLevel_0, "Adapt_Config", "time = %ld", time_adapt_e - time_adapt_s);
// 2、参数检查
int rec = ConfigCheck(DetImgInfo_shareP->img);
if (rec != CHECK_OK)
{
m_pdetlog->AddCheckstr(PrintLevel_0, "Error", "ConfigCheck is error type = %d", rec);
m_nErrorCode = rec;
m_nCheckResultErrorCode = m_nErrorCode;
return m_nErrorCode;
}
long time_edge_s = CheckUtil::getcurTime();
// 3、AI 边缘定位
if(m_CheckResult_shareP->basicResult.strChannel == "DCA" || m_CheckResult_shareP->basicResult.strChannel == "DTA")
{
m_pdetlog->AddCheckstr(PrintLevel_0, "Edge", "Not Use AI_Edge %s", m_CheckResult_shareP->basicResult.strChannel.c_str());
m_CutRoi = cv::Rect(rot_cur_roi.boundingRect().x - 50 , rot_cur_roi.boundingRect().y - 50, rot_cur_roi.boundingRect().width + 100, rot_cur_roi.boundingRect().height + 100)
& cv::Rect(0, 0, m_CheckResult_shareP->in_shareImage->img.cols, m_CheckResult_shareP->in_shareImage->img.rows);
}
else
{
m_pdetlog->AddCheckstr(PrintLevel_0, "Edge", "Use AI_Edge %s", m_CheckResult_shareP->basicResult.strChannel.c_str());
int reedge = AI_Edge(m_CheckResult_shareP->in_shareImage->img, m_CutRoi);
if (reedge != 0)
{
m_pdetlog->AddCheckstr(PrintLevel_0, "Error", "AI_Edge is error type = %d", reedge);
m_nErrorCode = reedge;
m_nCheckResultErrorCode = m_nErrorCode;
return m_nErrorCode;
}
}
long time_edge_e = CheckUtil::getcurTime();
m_pdetlog->AddCheckstr(PrintLevel_0, "2、pre detect", "-------------------------AI_Edge------------succ---time %ld----\n", time_edge_e - time_edge_s);
m_Crop_Roi_paramImg = m_CutRoi;
m_pImageAllResult->pDetResult->CutRoi = m_CutRoi;
m_pImageAllResult->pDetResult->Param_CropRoi = m_Crop_Roi_paramImg;
// 生成 检测的图片
cv::Mat image;
image = m_CheckResult_shareP->in_shareImage->img;
if (image.channels() == 3)
{
cv::cvtColor(image(m_CutRoi), m_pImageAllResult->detImg, cv::COLOR_RGB2GRAY);
}
else
{
m_pImageAllResult->detImg = image(m_CutRoi).clone();
}
// bDetect为true才进行推理输出残点图否则直接输出全黑残点图
long time_AI_s = CheckUtil::getcurTime();
if(m_pBasicConfig->bDetect)
{
// 多线程开启 传统/AI 推理检测
m_AItask = std::make_shared<TaskInfo>();
m_AItask->taskname = Task_AI;
m_task.sendTask(m_AItask);
}
else
{
// 不推理:直接输出全黑残点图
m_pdetlog->AddCheckstr(PrintLevel_0, "2.1、pre detect", "-------------------------NO AI_Edge--------------- \n");
m_pImageAllResult->AIMaskImg = cv::Mat::zeros(m_pImageAllResult->detImg.size(), CV_8UC1);
}
ImgPreDet();
// 更新检测区域
Update_DetRoiList();
m_pdetlog->AddCheckstr(PrintLevel_0, "3、pre detect", "-------------------------pre Det--------------- \n");
// 实现边缘崩溃缺陷检测
{
long t41 = CheckUtil::getcurTime();
int reedge1111 = Edge_Qx_Det(m_pImageAllResult->detImg);
long t42 = CheckUtil::getcurTime();
m_pdetlog->AddCheckstr(PrintLevel_0, "4、detect", "-------------------------1、Edge_Qx_Det--------%ld-------\n", t42 - t41);
}
m_CheckResult_shareP->nresult = 0;
// 把临时可以绘制的结果都绘制出来。
DrawResult_Step_1();
long time_AI_e;
// AI 推理生成
{
long t211 = CheckUtil::getcurTime();
// 对AI的结果进行 处理,等待 AI 推理全部完成。
rec = AIMaskDet();
if (rec != CHECK_OK)
{
m_nErrorCode = rec;
m_nCheckResultErrorCode = m_nErrorCode;
return m_nErrorCode;
}
time_AI_e = CheckUtil::getcurTime();
m_pdetlog->AddCheckstr(PrintLevel_0, "4、detect", "-------------------------2、AI Detect--------%ld wait AI complate %ld-------\n", time_AI_e - time_AI_s, time_AI_e - t211);
m_CheckResult_shareP->resultMaskImg = m_pImageAllResult->AIMaskImg;
}
{
t4 = CheckUtil::getcurTime();
rec = GetCheckResultBLob();
if (rec != CHECK_OK)
{
m_nErrorCode = rec;
m_nCheckResultErrorCode = m_nErrorCode;
return m_nErrorCode;
}
t5 = CheckUtil::getcurTime();
m_pdetlog->AddCheckstr(PrintLevel_0, "5、BLob ", "------------------------ --------%ld -------\n", t5 - t4);
}
// m_pdetlog->printLog(m_strCurDetChannel);
long te = CheckUtil::getcurTime();
m_pdetlog->bPrintStr = true;
m_pdetlog->AddCheckstr(PrintLevel_1, "result", " ALL use Time %ld edge %ld AI %ld blob %ld",
te - t1, time_edge_e - time_edge_s, time_AI_e - time_AI_s, t5 - t4);
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, "End", " Check Run");
return 0;
}
int ImgCheckAnalysisy::SetNewConfig()
{
if (m_nConfigIdx < 0)
{
return 1;
/* code */
}
if (m_pConfig->GetConfigUpdataStatus(ConfigType_Analysisy_Common_XL, m_nConfigIdx))
{
m_bupdateconfig = true;
// printf("************** ImgCheckAnalysisy::SetNewConfig m_nConfigIdx %d\n", m_nConfigIdx);
m_old_productROI = cv::RotatedRect();
m_pConfig->GetConfig(ConfigType_Analysisy_Common_XL, &m_AnalysisyConfig);
if (m_AnalysisyConfig.commonCheckConfig.nodeConfigArr.size() > 0)
{
m_pCommonAnalysisyConfig = &m_AnalysisyConfig.commonCheckConfig.nodeConfigArr.at(0);
m_pBasicConfig = &m_AnalysisyConfig.commonCheckConfig.baseConfig;
m_pRegionAnalysisyParam = &m_pCommonAnalysisyConfig->regionConfigArr.at(0);
UpdateImgageScale();
if (false)
{
printf("SetNewConfig m_nConfigIdx %d m_CheckConfig.strSkuName %s \n", m_nConfigIdx, m_AnalysisyConfig.strSkuName.c_str());
}
}
else
{
printf("m_AnalysisyConfig.commonCheckConfig.nodeConfigArr == 0 \n");
}
}
else
{
// printf("ConfigType_Analysisy_Common_XL no Update \n");
}
m_nErrorCode = CHECK_OK;
return CHECK_OK;
}
ChannelCheckFunction *ImgCheckAnalysisy::GetChannelFuntion(std::string strChannelName)
{
ChannelCheckFunction *p = NULL;
for (int i = 0; i < m_AnalysisyConfig.checkFunction.channelFunctionArr.size(); i++)
{
if (CheckUtil::compareIgnoreCase(m_AnalysisyConfig.checkFunction.channelFunctionArr[i].strChannelName, strChannelName))
{
p = &m_AnalysisyConfig.checkFunction.channelFunctionArr[i];
}
}
return p;
}
int ImgCheckAnalysisy::Run(int nId)
{
std::vector<int> vi;
vi.push_back(nId);
auto nRet = set_cpu_id(vi);
// printf("Check So %d bind cpu ret %d, %d\n", m_nThreadIdx, nRet, nId);
while (!m_bExit)
{
// 数据准备完成,开启检测
if (m_nRun_Status == CHECK_THREAD_STATUS_READY)
{
m_nRun_Status = CHECK_THREAD_STATUS_BUSY;
/* 检测 */
CheckRun();
m_nRun_Status = CHECK_THREAD_STATUS_COMPLETE;
m_pImageAllResult->setStep(ImageAllResult::DetStep_Complet);
m_nRun_Status = CHECK_THREAD_STATUS_IDLE;
// printf("*--------%d\n", m_nRun_Status);
}
else
{
usleep(1000);
}
// printf("*-");
usleep(1000);
}
return 0;
}
int ImgCheckAnalysisy::set_cpu_id(const std::vector<int> &cpu_set_vec)
{
// for cpu affinity
int nRet = 0;
#ifdef __linux
cpu_set_t _cur_cpu_set;
CPU_ZERO(&_cur_cpu_set);
for (auto _id : cpu_set_vec)
{
CPU_SET(_id, &_cur_cpu_set);
}
if (0 > pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &_cur_cpu_set))
{
perror("set cpu affinity failed: ");
printf("Warning: set cpu affinity failed ... ...\n");
nRet = -1;
}
#endif //__linux
return nRet;
}
int ImgCheckAnalysisy::CalBlob_Other()
{
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "CalBlob_Other", " Start");
// 检查 detImg 和 AIMaskImg 是否为空
if (m_pImageAllResult->detImg.empty())
{
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "CalBlob_Other", " detImg is empty, return");
return -1;
}
if (m_pImageAllResult->AIMaskImg.empty())
{
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "CalBlob_Other", " AIMaskImg is empty, return");
return -1;
}
float fs_x = m_fImgage_Scale_X;
float fs_y = m_fImgage_Scale_Y;
float fs_resize_x = m_pImageAllResult->fscale_detToresult_x;
float fs_resize_y = m_pImageAllResult->fscale_detToresult_y;
// 遍历每个检测blob
for (int i = 0; i < blobs.blobCount; i++)
{
// m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Blob", "%d/%d start", i, blobs.blobCount);
cv::Rect roi;
roi.x = blobs.blobTab[i].minx;
roi.y = blobs.blobTab[i].miny;
roi.width = blobs.blobTab[i].maxx - blobs.blobTab[i].minx + 1;
roi.height = blobs.blobTab[i].maxy - blobs.blobTab[i].miny + 1;
cv::Scalar result = calc_blob_info_withstats(m_pImageAllResult->detImg, m_pImageAllResult->AIMaskImg, roi);
int QX_whiteBLACK = CONFIG_QX_BLACK;
if (result[0] > 0)
{
QX_whiteBLACK = CONFIG_QX_WHITE;
}
double hj = result[2];
double energe = result[1];
blobs.blobTab[i].energy = energe;
blobs.blobTab[i].grayDis = hj;
float JudgArea = blobs.blobTab[i].area * fs_x * fs_y;
blobs.blobTab[i].JudgArea = JudgArea;
float flen = roi.width * fs_x;
float fwid = roi.height * fs_x;
if (roi.height * fs_y > flen)
{
flen = roi.height * fs_y;
fwid = roi.width * fs_y;
}
blobs.blobTab[i].len = flen;
blobs.blobTab[i].breadth = fwid;
int nerrortype = 0;
int checkFlage = 0;
float fmaxScore = 0;
int config_qx_type = 0;
if (blobs.blobTab[i].ErrType == ERR_TYPE_2)
{
QX_whiteBLACK = CONFIG_QX_BLACK; // 强制为 黑色
}
blobs.blobTab[i].whiteOrblack = QX_whiteBLACK;
// 精确计算长度
vector<float> re_len = Cal_QXLen(m_pImageAllResult->detImg(roi), config_qx_type, fs_x, fs_y);
if (re_len.size() > 2)
{
if(re_len[0] >= 0){
flen = re_len[0];
blobs.blobTab[i].len = flen;
}
if(re_len[1] >= 0){
fwid = re_len[1];
blobs.blobTab[i].breadth = fwid;
}
}
}
return 0;
}
int ImgCheckAnalysisy::GetClassImg(const cv::Mat &img, cv::Mat &AIdetImg, cv::Rect qx_roi, int detwidth, int detheight)
{
cv::Rect cutroi;
cv::Rect roi = qx_roi;
bool bresize = false;
{
int pc_x = roi.x + roi.width * 0.5;
int pc_y = roi.y + roi.height * 0.5;
if (roi.width < detwidth && roi.height < detheight)
{
cutroi.width = detwidth;
cutroi.x = pc_x - detwidth * 0.5;
cutroi.height = detheight;
cutroi.y = pc_y - detheight * 0.5;
}
else
{
// 宽 高
if (roi.width > roi.height)
{
cutroi.width = roi.width + 20;
cutroi.x = roi.x - 10;
float fsx = detheight * 1.0f / detwidth;
cutroi.height = cutroi.width * fsx;
cutroi.y = pc_y - cutroi.height * 0.5;
}
else
{
cutroi.height = roi.height + 20;
cutroi.y = roi.y - 10;
float fsy = detwidth * 1.0f / detheight;
cutroi.width = cutroi.height * fsy;
cutroi.x = pc_x - cutroi.width * 0.5;
}
bresize = true;
}
if (cutroi.x < 0)
{
cutroi.x = 0;
}
if (cutroi.y < 0)
{
cutroi.y = 0;
}
if (cutroi.x + cutroi.width >= img.cols)
{
cutroi.x = img.cols - cutroi.width;
if (cutroi.x < 0)
{
cutroi.x = 0;
if (cutroi.x + cutroi.width >= img.cols)
{
cutroi.width = img.cols;
}
}
}
if (cutroi.y + cutroi.height >= img.rows)
{
cutroi.y = img.rows - cutroi.height;
if (cutroi.y < 0)
{
cutroi.y = 0;
if (cutroi.y + cutroi.height >= img.rows)
{
cutroi.height = img.rows;
}
}
}
}
if (!CheckUtil::RoiInImg(cutroi, img))
{
return 1;
}
cv::Size sz;
sz.width = detwidth;
sz.height = detheight;
if (cutroi.width != sz.width || cutroi.height != sz.height)
{
cv::resize(img(cutroi), AIdetImg, sz);
}
else
{
AIdetImg = img(cutroi).clone();
}
if (1 != AIdetImg.channels())
{
cv::cvtColor(AIdetImg, AIdetImg, cv::COLOR_BGR2GRAY);
}
return 0;
}
vector<float> ImgCheckAnalysisy::Cal_QXLen(cv::Mat qx_maskImg, int qx_type, float fsc_x, float fsc_y)
{
vector<float> resLen(3);
float nlen = -1;
cv::Mat detimg = qx_maskImg;
resLen[0] = nlen;
// 寻找轮廓
vector<vector<Point>> contours;
cv::findContours(detimg, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
// 找到最大面积的轮廓
double maxArea = -1;
int maxAreaIdx = -1;
for (size_t i = 0; i < contours.size(); ++i)
{
double area = contourArea(contours[i]);
if (area > maxArea)
{
maxArea = area;
maxAreaIdx = i;
}
}
// 如果找到了最大面积的轮廓
if (maxAreaIdx >= 0)
{
// 使用minAreaRect找到最小外接矩形
cv::RotatedRect rect = cv::minAreaRect(contours[maxAreaIdx]);
// // 绘制最小外接矩形
// Point2f vertices[4];
// rect.points(vertices);
// for (int i = 0; i < 4; ++i)
// {
// line(detimg, vertices[i], vertices[(i + 1) % 4], Scalar(128, 255, 0), 2); // 绿色线
// }
// 输出结果
// 获取最小外接矩形的尺寸
float width = rect.size.width;
float height = rect.size.height;
// std::cout << "1 Width: " << width << ", Height: " << height << std::endl;
Point2f vertices[4];
rect.points(vertices);
vector<Point2f> newcont;
for (int i = 0; i < 4; ++i)
{
Point2f p;
p.x = vertices[i].x * fsc_x;
p.y = vertices[i].y * fsc_y;
newcont.push_back(p);
}
vector<vector<Point2f>> contours_New;
contours_New.push_back(newcont);
// Recreate the rotated rectangle with scaled vertices
RotatedRect scaledRect = minAreaRect(contours_New[0]);
// Calculate scaled width and height
width = scaledRect.size.width;
height = scaledRect.size.height;
// std::cout << "2 width: " << width << ", height: " << height << std::endl;
// float scale = 0.5; // 缩放比例
// rect.size.width *= fsc_x;
// rect.size.height *= fsc_y;
// std::cout << "fsc_x: " << fsc_x << ", fsc_y: " << fsc_y << std::endl;
// std::cout << "Width: " << width << ", Height: " << height << std::endl;
// 获取最小外接矩形的尺寸
// width = rect.size.width;
// height = rect.size.height;
if (width > height)
{
nlen = width;
resLen[0] = width;
resLen[1] = height;
/* code */
}
else
{
nlen = height;
resLen[0] = height;
resLen[1] = width;
}
}
// getchar();
return resLen;
}
int ImgCheckAnalysisy::GetCheckResultBLob()
{
long t1, t2, t3, t4, t5, t6, t7;
t1 = CheckUtil::getcurTime();
int re = GetALLBlob();
if (re != 0)
{
return re;
}
// 缺陷分类 多线程 实现。
long t11 = CheckUtil::getcurTime();
m_Classtask = std::make_shared<TaskInfo>();
m_Classtask->taskname = Task_Class;
m_task.sendTask(m_Classtask);
re = CalBlob_Other();
if (re != 0)
{
return re;
}
long t12 = CheckUtil::getcurTime();
// 等待分类 完成。
m_Classtask->waitComplate();
long t13 = CheckUtil::getcurTime();
// printf("=========== cls time %ld waite time %ld\n", t13 - t11, t13 - t12);
BLobToDetResult();
return 0;
}
void worker(const unsigned char *img, int w, int startRow, int endRow, unsigned char *rowFlags)
{
for (int y = startRow; y < endRow; y++)
{
const unsigned char *p = img + (size_t)y * w;
rowFlags[y] = 0;
for (int x = 0; x < w; x++)
{
if (p[x] != 0)
{
rowFlags[y] = 1;
break;
}
}
}
}
int ImgCheckAnalysisy::GetALLBlob()
{
std::string strBaseLog = "Blob";
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "image Blob Analysis Start");
if (m_pImageAllResult->AIMaskImg.empty())
{
return 1;
}
unsigned char *pGrayErrordata = (unsigned char *)m_pImageAllResult->AIMaskImg.data;
int width = m_pImageAllResult->AIMaskImg.cols;
int height = m_pImageAllResult->AIMaskImg.rows;
long t1 = CheckUtil::getcurTime();
memset(&blobs, 0x00, sizeof(ERROR_DOTS_BLOBS));
ERROR_DOTS_BLOBS blobs_v1;
memset(&blobs_v1, 0x00, sizeof(ERROR_DOTS_BLOBS));
ERROR_DOTS_BLOBS blobs_big;
memset(&blobs_big, 0x00, sizeof(ERROR_DOTS_BLOBS));
ERROR_DOTS_BLOBS blobs_big_2;
memset(&blobs_big_2, 0x00, sizeof(ERROR_DOTS_BLOBS));
printf("=====>>>> GetALLBlob m_strCurDetChannel %s \n", m_strCurDetChannel.c_str());
if (m_strCurDetChannel.find("CA") != std::string::npos)
{
printf("=====>>>>GetALLBlob USE CA %s \n", m_strCurDetChannel.c_str());
GetBlobs_ALL_New(&blobs_v1, pGrayErrordata, m_ImgBlobHFlagData, width, height, 15);
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "blob 1 num %d", blobs_v1.blobCount);
if (blobs_v1.srcBlobCount >= _MAX_ERROR_DOT_BLOB)
{
GetBlobs_ALL_New(&blobs_big, pGrayErrordata, m_ImgBlobHFlagData, width, height, 200);
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "blob 2 num %d", blobs_big.blobCount);
if (blobs_big.srcBlobCount >= _MAX_ERROR_DOT_BLOB)
{
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "blob 3 num %d", blobs_big_2.blobCount);
GetBlobs_ALL_New(&blobs_big_2, pGrayErrordata, m_ImgBlobHFlagData, width, height, 500);
}
}
}
else
{
GetBlobs_oneLabe(&blobs_v1, pGrayErrordata, m_ImgBlobHFlagData, width, height, 15);
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "blob 1 num %d", blobs_v1.blobCount);
if (blobs_v1.srcBlobCount >= _MAX_ERROR_DOT_BLOB)
{
GetBlobs_oneLabe(&blobs_big, pGrayErrordata, m_ImgBlobHFlagData, width, height, 200);
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "blob 2 num %d", blobs_big.blobCount);
if (blobs_big.srcBlobCount >= _MAX_ERROR_DOT_BLOB)
{
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "blob 3 num %d", blobs_big_2.blobCount);
GetBlobs_oneLabe(&blobs_big_2, pGrayErrordata, m_ImgBlobHFlagData, width, height, 500);
}
}
}
long t2 = CheckUtil::getcurTime();
PushBlob(&blobs, &blobs_big_2);
PushBlob(&blobs, &blobs_big);
PushBlob(&blobs, &blobs_v1);
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "blob ALL num %d", blobs.blobCount);
// long t2 = CheckUtil::getcurTime();
// printf(" BLob time %ld \n", t2 - t1);
if (false || DetImgInfo_shareP->bsaveProcessImg)
{
int font_face = cv::FONT_HERSHEY_SIMPLEX;
double font_scale = 0.5;
int thickness = 1;
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, strBaseLog, "Save Tem Img");
cv::Mat tm;
cv::cvtColor(m_pImageAllResult->AIMaskImg, tm, cv::COLOR_GRAY2RGB); // 彩色 可选项
for (int i = 0; i < blobs.blobCount; i++)
{
cv::Rect roi;
roi.x = blobs.blobTab[i].minx;
roi.y = blobs.blobTab[i].miny;
roi.width = blobs.blobTab[i].maxx - blobs.blobTab[i].minx + 1;
roi.height = blobs.blobTab[i].maxy - blobs.blobTab[i].miny + 1;
if (blobs.blobTab[i].ErrType == 0)
{
cv::rectangle(tm, roi, cv::Scalar(0, 0, 255));
}
else
{
cv::rectangle(tm, roi, cv::Scalar(0, 255, 255));
}
char buffer[128];
sprintf(buffer, "id:%d type:%d m %0.1f", i,blobs.blobTab[i].ErrType, blobs.blobTab[i].density);
std::string text = buffer;
cv::Point origin = cv::Point(roi.x, roi.y);
cv::putText(tm, text, origin, font_face, font_scale, cv::Scalar(0, 255, 0), thickness, 1, 0);
// printf("type: %d %d %d %d %d %d %d\n", blobs.blobTab[i].ErrType, blobs.blobTab[i].area, blobs.blobTab[i].energy, roi.x, roi.y, roi.width, roi.height);
}
cv::imwrite(m_CheckResult_shareP->in_shareImage->strChannel + "_image_resize_blob.png", tm);
}
long te = CheckUtil::getcurTime();
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "image Blob Analysis End use time %ld blob %ld ms", te - t1, t2 - t1);
// getchar();
return 0;
}
int ImgCheckAnalysisy::AIMaskDet()
{
// 计算 mask 图片的一行 是否有 残点,用以加速 Blob的计算。
if (m_ImgBlobHFlagData)
{
delete[] m_ImgBlobHFlagData;
m_ImgBlobHFlagData = NULL;
}
m_ImgBlobHFlagData = new unsigned char[m_pImageAllResult->detImg.rows];
memset(m_ImgBlobHFlagData, 0, sizeof(unsigned char) * m_pImageAllResult->detImg.rows);
// bDetect为false时不进行推理直接输出全黑残点图
if(!m_pBasicConfig->bDetect)
{
m_CheckResult_shareP->resultMaskImg = m_pImageAllResult->AIMaskImg;
return 0;
}
// 传统检测路径等待异步任务完成后计算HFlag
if(m_pbaseCheckFunction->traditionDet.bOpen)
{
m_AItask->waitComplate();
int rec = m_AItask->nresult;
if (rec != CHECK_OK)
{
return rec;
}
if (!m_pImageAllResult->AIMaskImg.empty())
{
unsigned char *pGrayErrordata = (unsigned char *)m_pImageAllResult->AIMaskImg.data;
int width = m_pImageAllResult->AIMaskImg.cols;
int height = m_pImageAllResult->AIMaskImg.rows;
for (int y = 0; y < height; y++)
{
if (m_ImgBlobHFlagData[y] == 0)
{
unsigned char *p = pGrayErrordata + y * width;
for (int x = 0; x < width; x++)
{
if (p[x] != 0)
{
m_ImgBlobHFlagData[y] = 1;
break;
}
}
}
}
}
m_CheckResult_shareP->resultMaskImg = m_pImageAllResult->AIMaskImg;
return 0;
}
while (true)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
std::shared_ptr<AIMulThreadRunBase::AITask> AImaskResult;
{
std::lock_guard<std::mutex> lock(mtx_AIMaskImgBLobQueue);
if (m_AIMaskImgBLobQueue.size() > 0)
{
AImaskResult = std::move(m_AIMaskImgBLobQueue.front());
m_AIMaskImgBLobQueue.pop();
// printf("size ============== %ld\n", m_AIMaskImgBLobQueue.size());
}
}
// 有AI mask 的结果
if (AImaskResult)
{
// static int ss = 0;
cv::Mat &outimg = *(AImaskResult->output);
// cv::imwrite(std::to_string(ss++) + ".png", outimg);
unsigned char *pGrayErrordata = (unsigned char *)outimg.data;
int width = outimg.cols;
int height = outimg.rows;
int start_Y = AImaskResult->roi.y;
if (cv::countNonZero(outimg != 0) != 0)
{
// #pragma omp parallel for
for (int y = 0; y < height; y++)
{
if (m_ImgBlobHFlagData[y + start_Y] == 0)
{
unsigned char *p = pGrayErrordata + y * width;
for (int x = 0; x < width; x++)
{
if (p[x] != 0)
{
m_ImgBlobHFlagData[y + start_Y] = 1;
break;
}
}
}
}
}
}
else
{
/* code */
if (m_AItask->isComplate())
{
break;
}
}
}
// printf("===========================================1 \n");
m_AItask->waitComplate();
int rec = m_AItask->nresult;
if (rec != CHECK_OK)
{
return rec;
}
// printf("===========================================2 \n");
return 0;
}
int ImgCheckAnalysisy::Contours()
{
// std::string strBaseLog = "Contours";
// // m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "Contours Start");
// cv::Mat detimg;
// {
// // 膨胀
// cv::Mat se = getStructuringElement(0, Size(5, 5)); // 构造矩形结构元素
// cv::dilate(m_pdetlog->temImgList[TEM_IMG_IDX_AImask], detimg, se);
// }
// std::vector<std::vector<cv::Point>> contours;
// std::vector<cv::Vec4i> hierarchy;
// cv::findContours(detimg, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); // 只找最外层轮廓
// // cv::cvtColor(m_pdetlog->temImgList[TEM_IMG_IDX_SrcCrop], m_pdetlog->temImgList[TEM_IMG_IDX_DrawSrc], cv::COLOR_GRAY2BGR);
// for (int i = 0; i < contours.size(); ++i)
// { // 绘制所有轮廓
// cv::drawContours(m_pdetlog->temImgList[TEM_IMG_IDX_DrawSrc], contours, i, cv::Scalar(255, 0, 255)); // thickness为-1时为填充整个轮廓
// }
// float fx = m_pdetlog->temImgList[TEM_IMG_IDX_Result].cols * 1.0f / m_pdetlog->temImgList[TEM_IMG_IDX_SrcCrop].cols;
// float fy = m_pdetlog->temImgList[TEM_IMG_IDX_Result].rows * 1.0f / m_pdetlog->temImgList[TEM_IMG_IDX_SrcCrop].rows;
// for (int i = 0; i < contours.size(); ++i)
// {
// for (int j = 0; j < contours.at(i).size(); ++j)
// {
// contours.at(i).at(j).x *= fx;
// contours.at(i).at(j).y *= fy;
// }
// }
// // cv::cvtColor(m_pdetlog->temImgList[TEM_IMG_IDX_Result], m_pdetlog->temImgList[TEM_IMG_IDX_Result], cv::COLOR_GRAY2BGR);
// for (int i = 0; i < contours.size(); ++i)
// { // 绘制所有轮廓
// cv::drawContours(m_pdetlog->temImgList[TEM_IMG_IDX_Result], contours, i, cv::Scalar(255, 0, 255)); // thickness为-1时为填充整个轮廓
// }
// cv::imwrite("TEM_IMG_IDX_Result.png", m_pdetlog->temImgList[TEM_IMG_IDX_Result]);
// cv::imwrite("deeeee.png", m_pdetlog->temImgList[TEM_IMG_IDX_Drawmask]);
// getchar();
// m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "Contours End");
return 0;
}
int ImgCheckAnalysisy::CheckImgInit()
{
// 1、初始化
m_pDetResult->pQx_ErrorList = std::make_shared<std::vector<QX_ERROR_INFO_>>();
m_pdetlog->Init();
m_pdetlog->addLogLevel = DET_LOG_LEVEL_3;
memset(&blobs, 0, sizeof(ERROR_DOTS_BLOBS));
m_nCheckResultErrorCode = 0;
m_Draw_qxImageResult.erase(m_Draw_qxImageResult.begin(), m_Draw_qxImageResult.end());
m_DetRoiList.Init();
return 0;
}
int ImgCheckAnalysisy::ConfigCheck(cv::Mat img)
{
m_pdetlog->AddCheckstr(PrintLevel_0, "start", "Config Check");
int re = CHECK_OK;
if (img.empty())
{
m_nErrorCode = CHECK_ERROR_CheckImg_Empty;
m_pdetlog->AddCheckstr(PrintLevel_1, "Error", "check Img empty");
return m_nErrorCode;
}
// if (m_pCommonAnalysisyConfig->regionConfigArr.size() <= 0)
// {
// m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Error", "regionConfig Num = 0");
// m_nErrorCode = CHECK_ERROR_Config_Value;
// return m_nErrorCode;
// }
m_pdetlog->AddCheckstr(PrintLevel_0, "Succ", "Config Check Succ");
return re;
}
int ImgCheckAnalysisy::AI_Detect_Thread(const cv::Mat &img, cv::Mat &ResultImg)
{
std::shared_ptr<AIModel_Base> pAIDet;
// printf("=====>>>>AI_Detect_Thread m_strCurDetChannel %s \n", m_strCurDetChannel.c_str());
if (m_strCurDetChannel.find("BCA") != std::string::npos)
{
// printf("=====>>>>AI_Detect_Thread USE CA %s \n", m_strCurDetChannel.c_str());
pAIDet = AI_Factory->CELL_BCA_Det;
}
else if (m_strCurDetChannel.find("BTA") != std::string::npos)
{
pAIDet = AI_Factory->CELL_BTA_Det;
}
else if (m_strCurDetChannel.find("DCA") != std::string::npos)
{
pAIDet = AI_Factory->CELL_DCA_Det;
}
else if (m_strCurDetChannel.find("DTA") != std::string::npos)
{
pAIDet = AI_Factory->CELL_DTA_Det;
}
else
{
pAIDet = AI_Factory->CELL_BTA_Det;
}
std::string strBaseLog = "AI_Detect";
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "AI_Detect Start");
long t1, t2, t3;
t1 = CheckUtil::getcurTime();
SmallRoiList.clear();
SmallRoiList.erase(SmallRoiList.begin(), SmallRoiList.end());
cv::Rect cutRoi;
cutRoi.x = 0;
cutRoi.y = 0;
cutRoi.width = img.cols - 0;
cutRoi.height = img.rows - 0;
int deal_image_width = pAIDet->input_0.width;
int deal_image_height = pAIDet->input_0.height;
int re = CheckUtil::cutSmallImg(img, SmallRoiList, cutRoi, deal_image_width, deal_image_height, 0, 0);
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, strBaseLog, " cutSmallImg Num %d", SmallRoiList.size());
if (re != 0 || SmallRoiList.size() <= 0)
{
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, strBaseLog, " cutSmallImg error %d", re);
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "AI_Detect End");
return re;
/* code */
}
// 临时存图
if (DetImgInfo_shareP->bsaveProcessImg)
{
cv::Mat imshow;
if (img.channels() == 1)
{
cv::cvtColor(img, imshow, cv::COLOR_GRAY2RGB); // 彩色 可选项
}
else
{
imshow = img.clone();
}
for (int i = 0; i < SmallRoiList.size(); i++)
{
cv::rectangle(imshow, SmallRoiList.at(i), cv::Scalar(0, 0, 255), 3);
}
cv::imwrite(DetImgInfo_shareP->strChannel + "_AI_Det_ROI.jpg", imshow);
}
ResultImg = cv::Mat::zeros(img.size(), CV_8UC1);
const int totalTasks = SmallRoiList.size();
int submitted = 0;
int completed = 0;
// std::string str_Root = m_strRootPath + pDetConfig->strProductID + "_" + pDetConfig->strchannel + "_";
t2 = CheckUtil::getcurTime();
while (completed < totalTasks)
{
// 如果任务还没提交完,且当前处理任务数 < 2提交新任务
if (submitted < totalTasks && runner->GetProcessingCount() < 10)
{
std::shared_ptr<AIMulThreadRunBase::AITask> task = std::make_shared<AIMulThreadRunBase::AITask>();
task->id = completed;
task->roi = SmallRoiList.at(submitted);
task->input = img(SmallRoiList.at(submitted)).clone();
task->output = std::make_shared<cv::Mat>();
task->engine = pAIDet;
runner->SubmitTask(task);
submitted++;
}
// 尝试取结果
std::shared_ptr<AIMulThreadRunBase::AITask> result;
if (runner->PopResult(result))
{
{
std::lock_guard<std::mutex> lock(mtx_AIMaskImgBLobQueue);
m_AIMaskImgBLobQueue.push(result);
}
cv::Mat &outimg = *(result->output);
if (!outimg.empty())
{
outimg.copyTo(ResultImg(result->roi), outimg);
}
{
std::shared_ptr<ImageAllResult::AI_Det_MaskImg> temAIresult = std::make_shared<ImageAllResult::AI_Det_MaskImg>();
temAIresult->roi = result->roi;
temAIresult->AI_inImg = result->input;
temAIresult->AI_mask = outimg;
m_pImageAllResult->AI_Qx_MaskList.push_back(temAIresult);
// AI检测残点图存图
if (m_pbaseCheckFunction->saveImg.bSaveAIDetImg)
{
std::string roi_ext = "[" + std::to_string(result->roi.x) + "," + std::to_string(result->roi.y) + "]";
std::string strSaveDir = "/home/aidlux/BOE/FOG/AI_Detect/" + DetImgInfo_shareP->strImgProductID + "/";
CheckUtil::CreateDir(strSaveDir);
std::string strSavePath_in = strSaveDir + m_strCurDetChannel +"_"+ roi_ext + "_"+ "in" + ".png";
std::string strSavePath_out = strSaveDir + m_strCurDetChannel +"_"+ roi_ext + "_"+ "out" + ".png";
cv::imwrite(strSavePath_in, result->input);
cv::imwrite(strSavePath_out, outimg);
}
}
completed++;
}
else
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
t3 = CheckUtil::getcurTime();
float mean_AI = (t3 - t2) / SmallRoiList.size();
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, strBaseLog, " AI Run Time: sum %ld pre %ld Run %ld mean One Small Img %f", t3 - t1, t2 - t1, t3 - t2, mean_AI);
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "AI_Detect End");
// 临时存图
if (DetImgInfo_shareP->bsaveProcessImg)
{
cv::imwrite(DetImgInfo_shareP->strChannel + "_AI_mask.png", ResultImg);
}
// getchar();
return 0;
}
// ======================== 传统检测 ========================
int ImgCheckAnalysisy::Traditional_Detect_Thread(const cv::Mat &img, cv::Mat &ResultImg)
{
std::string strBaseLog = "Traditional_Detect";
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "Traditional_Detect Start");
// 输入校验
if (img.empty())
{
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "Traditional_Detect FAILED (empty image)");
ResultImg = cv::Mat();
return -1;
}
Base_Function_TraditionDet traditionParam = m_pbaseCheckFunction->traditionDet; // 首次调用时初始化传统检测参数(从 m_AnalysisyConfig 映射)
{
CHECK_PARAM cp;
cp.nAreaLowFilter = 80;
cp.nBlockSize = traditionParam.nBlockSize;
cp.fZoomRatio = traditionParam.fZoomRatio;
cp.nFilterLow = traditionParam.nFilterLow;
cp.nFilterHigh = traditionParam.nFilterHigh;
cp.nAreaFilter = traditionParam.nAreaFilter;
cp.nCountFilter = traditionParam.nCountFilter;
cp.productId = DetImgInfo_shareP->strImgProductID;
cp.productChannel = m_strCurDetChannel;
cp.bDebugsaveImg = m_pbaseCheckFunction->saveImg.bSaveAIDetImg;
m_tcsCheck.SetChecConfig(&cp);
}
cv::Rect detroi = cv::boundingRect(traditionParam.detArea);
detroi.x -= m_Crop_Roi_paramImg.x;
detroi.y -= m_Crop_Roi_paramImg.y;
detroi = detroi & cv::Rect(0, 0, img.cols, img.rows);
if(!traditionParam.bdetArea)
{
detroi = cv::Rect(0, 0, img.cols, img.rows);
}
// 调用传统检测:输出残点二值图
int ret = m_tcsCheck.TraditionalDetect(img, detroi, ResultImg);
if (ret != 0)
{
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "Traditional_Detect FAILED (no product)");
return -1;
}
if (DetImgInfo_shareP->bsaveProcessImg)
{
cv::imwrite(DetImgInfo_shareP->strChannel + "_AI_mask.png", ResultImg);
}
m_pdetlog->AddCheckstr(PrintLevel_0, DET_LOG_LEVEL_3, strBaseLog, "Traditional_Detect End");
return 0;
}
int ImgCheckAnalysisy::AI_QX_Class_Thread()
{
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "QX_Class", " Start");
std::shared_ptr<AIModel_Base> pAIDet;
// printf("=====>>>>AI_QX_Class_Thread m_strCurDetChannel %s \n", m_strCurDetChannel.c_str());
if (m_strCurDetChannel.find("CA") != std::string::npos)
{
// printf("=====>>>>AI_QX_Class_Thread USE CA %s \n", m_strCurDetChannel.c_str());
pAIDet = AI_Factory->CELL_CA_Cls;
}
else
{
pAIDet = AI_Factory->CELL_TA_Cls;
}
int deal_image_width = pAIDet->input_0.width;
int deal_image_height = pAIDet->input_0.height;
const int totalTasks = blobs.blobCount;
int submitted = 0;
int completed = 0;
int detblobIdx = 0;
int clsnum = 0;
// std::string str_Root = m_strRootPath + pDetConfig->strProductID + "_" + pDetConfig->strchannel + "_";
long t2 = CheckUtil::getcurTime();
while (completed < totalTasks)
{
// std::this_thread::sleep_for(std::chrono::milliseconds(1));
if (submitted < totalTasks)
{
ERROR_DOTS_BLOB_DATA *pblob = &blobs.blobTab[submitted];
if (pblob->ErrType == ERR_TYPE_2)
{
pblob->AIclasstype = CONFIG_QX_NAME_cell_ymhs;
submitted++;
completed++;
continue;
}
else
{
// 如果任务还没提交完,且当前处理任务数 < 2提交新任务
if (runner->GetProcessingCount() < 10)
{
clsnum++;
cv::Rect roi;
roi.x = pblob->minx;
roi.y = pblob->miny;
roi.width = pblob->maxx - pblob->minx + 1;
roi.height = pblob->maxy - pblob->miny + 1;
std::shared_ptr<AIMulThreadRunBase::AITask> task = std::make_shared<AIMulThreadRunBase::AITask>();
task->id = submitted;
int re = GetClassImg(m_pImageAllResult->detImg, task->input, roi, deal_image_width, deal_image_height);
if (re == 0)
{
task->bclass = true;
task->engine = pAIDet;
runner->SubmitTask(task);
}
else
{
completed++;
}
submitted++;
}
}
}
// 尝试取结果
std::shared_ptr<AIMulThreadRunBase::AITask> result;
if (runner->PopResult(result))
{
int temClass = result->cls_label;
int cls_num = 0;
switch (temClass)
{
case 0:
cls_num = AI_CLass_QX_NAME_aotudian;
break;
case 1:
cls_num = AI_CLass_QX_NAME_other;
break;
case 2:
cls_num = AI_CLass_QX_NAME_line;
break;
case 3:
cls_num = AI_CLass_QX_NAME_zangwu;
break;
case 4:
cls_num = AI_CLass_QX_NAME_dianzhuang;
break;
case 5:
cls_num = AI_CLass_QX_NAME_posun;
break;
case 6:
cls_num = AI_CLass_QX_NAME_xianwei;
break;
case 7:
cls_num = AI_CLass_QX_NAME_shuizi;
break;
case 8:
cls_num = AI_CLass_QX_NAME_danban;
break;
case 9:
cls_num = AI_CLass_QX_NAME_fuchen;
break;
default:
cls_num = AI_CLass_QX_NAME_zangwu;
break;
}
// std::string strclassName = AI_CLass_QX_NAME_Names[cls_num];
// printf("AI Class num %d = %s %f\n", cls_num, strclassName.c_str(), result->cls_score);
// 分类存图 开启。
if (m_pbaseCheckFunction->saveImg.bSaveAlginImg)
{
std::string saveimgpaht = "";
if (m_strCurDetChannel.find("TA") != std::string::npos)
{
saveimgpaht = m_strRootPath_TA_cls + std::to_string(cls_num) + "/" + std::to_string(CheckUtil::getcurTime()) + "_" + std::to_string(result->cls_score) + ".png";
}
else
{
saveimgpaht = m_strRootPath_CA_cls + std::to_string(cls_num) + "/" + std::to_string(CheckUtil::getcurTime()) + "_" + std::to_string(result->cls_score) + ".png";
}
{
m_pImageStorage->addImage(saveimgpaht, result->input);
}
}
int configqx = AIClassTypeToConfigType(cls_num);
ERROR_DOTS_BLOB_DATA *pblob = &blobs.blobTab[result->id];
pblob->AIclasstype = configqx;
completed++;
}
else
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
// printf("=====>>>>AI_QX_Class_Thread clsnum %d \n", clsnum);
return 0;
}
// ======================== 传统分类 ========================
int ImgCheckAnalysisy::Traditional_QX_Class_Thread()
{
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Traditional_Class", " Start");
// 1. 调用传统分类
if (m_pImageAllResult == nullptr || m_pImageAllResult->AIMaskImg.empty())
{
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Traditional_Class", " No mask image");
return -1;
}
int nDefectCount = m_tcsCheck.TraditionalClassify(m_pImageAllResult->AIMaskImg);
if (nDefectCount < 0)
{
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Traditional_Class", " Classify failed");
return -1;
}
// 2. TcsCheck 缺陷类型 → CONFIG_QX_NAME 映射表
static const int TcsDefectToConfigQX[] = {
CONFIG_QX_NAME_cell_other, // DEFECT_TYPE_OK = 0
CONFIG_QX_NAME_cell_dianzhuang, // DEFECT_TYPE_POINT = 1 (硬质颗粒 → 点状)
CONFIG_QX_NAME_cell_line, // DEFECT_TYPE_SCRATCH = 2 (划伤 → 线状)
CONFIG_QX_NAME_cell_zangwu, // DEFECT_TYPE_DIRTY = 3 (脏污)
CONFIG_QX_NAME_cell_danban, // DEFECT_TYPE_FADING_SPOTS = 4 (淡斑)
};
// 3. 将分类结果匹配到 blobs.blobTab基于位置/面积最近邻匹配)
int totalTasks = blobs.blobCount;
for (int i = 0; i < totalTasks; i++)
{
ERROR_DOTS_BLOB_DATA *pblob = &blobs.blobTab[i];
if (pblob->ErrType == ERR_TYPE_2)
{
pblob->AIclasstype = CONFIG_QX_NAME_cell_ymhs;
continue;
}
// 在 TcsCheck 结果中找最佳匹配(中心距离最近)
int bestIdx = -1;
int bestDist2 = INT_MAX;
int blobCenterX = (pblob->minx + pblob->maxx) / 2;
int blobCenterY = (pblob->miny + pblob->maxy) / 2;
for (int j = 0; j < nDefectCount; j++)
{
const DEFECT_INFO& info = m_tcsCheck.m_vecDefectInfo[j];
int defCenterX = info.nDefectX + info.nDefectWidth / 2;
int defCenterY = info.nDefectY + info.nDefectHeight / 2;
int dx = blobCenterX - defCenterX;
int dy = blobCenterY - defCenterY;
int dist2 = dx * dx + dy * dy;
// 面积接近的优先(容差 50% 内)
int areaDiff = std::abs(pblob->area - info.nDefectArea);
if (areaDiff < info.nDefectArea / 2 && dist2 < bestDist2)
{
bestDist2 = dist2;
bestIdx = j;
}
}
if (bestIdx >= 0)
{
int defectType = m_tcsCheck.m_vecDefectInfo[bestIdx].nDefectType;
pblob->AIclasstype = TcsDefectToConfigQX[defectType];
}
else
{
pblob->AIclasstype = CONFIG_QX_NAME_cell_other;
}
}
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Traditional_Class", " End, classified %d/%d blobs", nDefectCount, totalTasks);
return 0;
}
int ImgCheckAnalysisy::ThreadTask(int nId)
{
while (!m_bExit)
{
std::this_thread::sleep_for(std::chrono::milliseconds(20));
// 等待是否有任务
std::shared_ptr<TaskInfo> task = m_task.GetTask();
// 把任务发送给对应的任务处理函数进行处理
switch (task->taskname)
{
case Task_AI:
TaskFun_AIDet(task);
break;
case Task_Class:
TaskFun_QxClass(task);
break;
default:
break;
}
}
return 0;
}
int ImgCheckAnalysisy::ResizeImg()
{
cv::Size sz;
sz.width = RESIZE_IMAGE_WIDTH;
float fw = RESIZE_IMAGE_WIDTH * 1.0f / m_pImageAllResult->detImg.cols;
sz.height = int(m_pImageAllResult->detImg.rows * fw);
cv::resize(m_pImageAllResult->detImg, m_pImageAllResult->resultImg, sz);
if (m_pImageAllResult->resultImg.channels() == 1)
{
cv::cvtColor(m_pImageAllResult->resultImg, m_pImageAllResult->resultImg, cv::COLOR_GRAY2BGR);
}
m_CheckResult_shareP->resultimg = m_pImageAllResult->resultImg;
m_pdetlog->AddCheckstr(PrintLevel_1, "showImg size", " [w %d,h %d]-> show img [w %d,h %d] ",
m_CutRoi.width, m_CutRoi.height, sz.width, sz.height);
return 0;
}
void ImgCheckAnalysisy::TaskFun_AIDet(std::shared_ptr<TaskInfo> task)
{
task->SetStatus(TaskStep_run);
long t1, t2;
// 检测:传统检测 / AI推理
{
t1 = CheckUtil::getcurTime();
int rec;
if(m_pbaseCheckFunction->traditionDet.bOpen)
{
rec = Traditional_Detect_Thread(m_pImageAllResult->detImg, m_pImageAllResult->AIMaskImg);
}
else
{
rec = AI_Detect_Thread(m_pImageAllResult->detImg, m_pImageAllResult->AIMaskImg);
}
t2 = CheckUtil::getcurTime();
task->nresult = rec;
}
task->SetStatus(TaskStep_compate);
}
void ImgCheckAnalysisy::TaskFun_QxClass(std::shared_ptr<TaskInfo> task)
{
task->SetStatus(TaskStep_run);
long t1, t2;
// 缺陷分类:传统检测 / AI推理
{
t1 = CheckUtil::getcurTime();
int rec;
if(m_pbaseCheckFunction->traditionDet.bOpen)
{
rec = Traditional_QX_Class_Thread();
}
else
{
rec = AI_QX_Class_Thread();
}
t2 = CheckUtil::getcurTime();
task->nresult = rec;
}
task->SetStatus(TaskStep_compate);
}
int ImgCheckAnalysisy::Update_DetRoiList()
{
float fx = m_pImageAllResult->fscale_detToresult_x;
float fy = m_pImageAllResult->fscale_detToresult_y;
// Adapt_Config 已通过仿射变换将配置区域适配到当前产品位置,
// 此处仅做坐标映射减去裁剪ROI偏移 + 缩放),不再叠加边缘对齐的二次偏移
for (const auto &region : m_pCommonAnalysisyConfig->regionConfigArr)
{
m_DetRoiList.Update(region.basicInfo.pointArry, m_Crop_Roi_paramImg, fx, fy);
}
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "info", "roiList_Src roi num %ld", m_DetRoiList.roiList_Src.size());
// m_DetRoiList.print("m_DetRoiList");
return 0;
}
int ImgCheckAnalysisy::DrawResult_Step_1()
{
// std::cout << m_pBasicConfig->bDrawPreRoi << std::endl;
if (m_pBasicConfig->bDrawPreRoi)
{
int n = 0;
// std::cout << m_DetRoiList.roiList_Show.size() << std::endl;
for(int i = 0; i < m_DetRoiList.roiList_Show.size(); i++)
{
cv::polylines(m_CheckResult_shareP->resultimg, m_DetRoiList.roiList_Show[i], true, cv::Scalar(32, 128, (i*64+64)%255), 1);
}
// for (const auto &polygon : m_DetRoiList.roiList_Show)
// {
// // n++;
// // if (n == 1)
// // {
// // continue;
// // }
// // std::cout << polygon << std::endl;
// // 绘制多边形的边界不填充使用绿色线条线宽为2
// cv::polylines(m_CheckResult_shareP->resultimg, polygon, true, cv::Scalar(128, 128, 255), 1); // true表示闭合多边形
// }
// cv::imwrite(DetImgInfo_shareP->strChannel + "roi_src.png", m_pdetlog->temImgList[TEM_IMG_IDX_DrawSrc]);
// cv::imwrite(DetImgInfo_shareP->strChannel + "roi_ss.png", m_pdetlog->temImgList[TEM_IMG_IDX_Result]);
// getchar();
}
float fs_resize_x = m_pImageAllResult->resultImg.cols * 1.0f / m_pImageAllResult->detImg.cols;
float fs_resize_y = m_pImageAllResult->resultImg.rows * 1.0f / m_pImageAllResult->detImg.rows;
// 要绘制结果
if (m_pbaseCheckFunction && m_pbaseCheckFunction->edgeDet.bDrawResult)
{
for (const auto &r : m_Edge_DetConfig.edge_det_roi)
{
cv::Point2f vertices[4];
r.rrect.points(vertices);
for (int j = 0; j < 4; j++)
{
cv::Point p1, p2;
p1.x = (int)(vertices[j].x * fs_resize_x);
p1.y = (int)(vertices[j].y * fs_resize_y);
p2.x = (int)(vertices[(j+1)%4].x * fs_resize_x);
p2.y = (int)(vertices[(j+1)%4].y * fs_resize_y);
cv::line(m_CheckResult_shareP->resultimg, p1, p2, cv::Scalar(255, 0, 255), 1);
}
}
if (m_Edge_DetConfig.Det_region.size() > 2)
{
for (int i = 0; i < m_Edge_DetConfig.Det_region.size() - 1; i++)
{
cv::Point p1;
p1.x = m_Edge_DetConfig.Det_region[i].x * fs_resize_x;
p1.y = m_Edge_DetConfig.Det_region[i].y * fs_resize_y;
cv::Point p2;
p2.x = m_Edge_DetConfig.Det_region[i + 1].x * fs_resize_x;
p2.y = m_Edge_DetConfig.Det_region[i + 1].y * fs_resize_y;
cv::line(m_CheckResult_shareP->resultimg, p1, p2, cv::Scalar(0, 255, 255));
}
{
cv::Point p1;
p1.x = m_Edge_DetConfig.Det_region[0].x * fs_resize_x;
p1.y = m_Edge_DetConfig.Det_region[0].y * fs_resize_y;
cv::Point p2;
p2.x = m_Edge_DetConfig.Det_region[m_Edge_DetConfig.Det_region.size() - 1].x * fs_resize_x;
p2.y = m_Edge_DetConfig.Det_region[m_Edge_DetConfig.Det_region.size() - 1].y * fs_resize_y;
cv::line(m_CheckResult_shareP->resultimg, p1, p2, cv::Scalar(0, 255, 255));
}
}
}
if (m_pEdge_Align_Result.get() != NULL)
{
if (m_pbaseCheckFunction->markLine.bDraw)
{
for (size_t i = 0; i < m_pEdge_Align_Result->markresulList.size(); i++)
{
// if (m_pEdge_Align_Result->markresulList[i].status == Mark_Result_Status_OK)
{
cv::Point p;
p.x = m_pEdge_Align_Result->markresulList[i].det_Local_DetImg.x * fs_resize_x;
p.y = m_pEdge_Align_Result->markresulList[i].det_Local_DetImg.y * fs_resize_y;
cv::circle(m_CheckResult_shareP->resultimg, p, 5, cv::Scalar(0, 255, 0));
}
}
}
}
// cv::imwrite("sss.png", m_CheckResult_shareP->resultimg);
return 0;
}
int ImgCheckAnalysisy::AIClassTypeToConfigType(int nAIQXType)
{
int resultError_type = CONFIG_QX_NAME_cell_aotudian;
switch (nAIQXType)
{
case AI_CLass_QX_NAME_aotudian:
resultError_type = CONFIG_QX_NAME_cell_aotudian;
break;
case AI_CLass_QX_NAME_other:
resultError_type = CONFIG_QX_NAME_cell_other;
break;
case AI_CLass_QX_NAME_line:
resultError_type = CONFIG_QX_NAME_cell_line;
break;
case AI_CLass_QX_NAME_zangwu:
resultError_type = CONFIG_QX_NAME_cell_zangwu;
break;
case AI_CLass_QX_NAME_dianzhuang:
resultError_type = CONFIG_QX_NAME_cell_dianzhuang;
break;
case AI_CLass_QX_NAME_posun:
resultError_type = CONFIG_QX_NAME_cell_posun;
break;
case AI_CLass_QX_NAME_xianwei:
resultError_type = CONFIG_QX_NAME_cell_xianwei;
break;
case AI_CLass_QX_NAME_shuizi:
resultError_type = CONFIG_QX_NAME_cell_shuizi;
break;
case AI_CLass_QX_NAME_danban:
resultError_type = CONFIG_QX_NAME_cell_danban;
break;
case AI_CLass_QX_NAME_fuchen:
resultError_type = CONFIG_QX_NAME_cell_fuchen;
break;
default:
break;
}
return resultError_type;
}
int ImgCheckAnalysisy::UpdateImgageScale()
{
if (m_pBasicConfig->fImage_Scale_x > 0 && m_pBasicConfig->fImage_Scale_x < 1 &&
m_pBasicConfig->fImage_Scale_y > 0 && m_pBasicConfig->fImage_Scale_y < 1)
{
m_fImgage_Scale_X = m_pBasicConfig->fImage_Scale_x;
m_fImgage_Scale_Y = m_pBasicConfig->fImage_Scale_y;
}
return 0;
}
int ImgCheckAnalysisy::Edge_Qx_Det(const cv::Mat &img)
{
m_Edge_DetConfig.Init();
m_Edge_DetConfig.detlog = m_pdetlog;
m_Edge_DetConfig.strChannel = m_strCurDetChannel;
m_Edge_DetConfig.pBaseCheckFunction = m_pbaseCheckFunction;
m_Edge_DetConfig.alginResult.corpRoi = m_Crop_Roi_paramImg;
m_Edge_DetConfig.pBaseCheckFunction->edgeDet.Align_region = m_AnalysisyConfig.baseFunction.markLine.region;
for(int i = 0; i < m_Edge_DetConfig.pBaseCheckFunction->edgeDet.Align_region.size(); i++)
{
m_Edge_DetConfig.pBaseCheckFunction->edgeDet.Align_region[i].x -= m_Crop_Roi_paramImg.x;
m_Edge_DetConfig.pBaseCheckFunction->edgeDet.Align_region[i].y -= m_Crop_Roi_paramImg.y;
}
if (m_pEdge_Align_Result && m_pEdge_Align_Result->buseOfft)
{
m_Edge_DetConfig.alginResult.offtx = m_pEdge_Align_Result->offt_x;
m_Edge_DetConfig.alginResult.offty = m_pEdge_Align_Result->offt_y;
m_Edge_DetConfig.alginResult.H = m_pEdge_Align_Result->H.clone();
}
m_Edge_DetConfig.bSaveResultImg = false;
if (DetImgInfo_shareP->bsaveProcessImg)
{
m_Edge_DetConfig.bSaveResultImg = true;
}
// m_pbaseCheckFunction->print("Edge_Qx_Det");
int re = m_Edge_QX_Det.Detect(img, &m_Edge_DetConfig);
if (re == 0)
{
for (const auto r : m_Edge_DetConfig.qx_result)
{
QX_ERROR_INFO_ temerror;
temerror.roi = r.roi_src;
temerror.Idx = m_pDetResult->pQx_ErrorList->size();
temerror.area = r.area_pixel;
temerror.JudgArea = r.area_pixel * m_fImgage_Scale_X * m_fImgage_Scale_Y;
temerror.JudgArea_second = temerror.JudgArea;
temerror.energy = 99999999;
temerror.flen = std::max(r.roi_src.width, r.roi_src.height);
temerror.fbreadth = std::min(r.roi_src.width, r.roi_src.height);
temerror.nconfig_qx_type = CONFIG_QX_NAME_cell_edge;
temerror.qx_name = CONFIG_QX_NAME_Names[CONFIG_QX_NAME_cell_edge];
temerror.maxValue = 0;
temerror.grayDis = 255;
temerror.density = 0;
temerror.fUpIou = 0;
{
cv::Point pCenter;
pCenter.x = temerror.roi.x + temerror.roi.width * 0.5;
pCenter.y = temerror.roi.y + temerror.roi.height * 0.5;
int nmaxregionIdx = -1;
for (int iregion = 0; iregion < m_DetRoiList.roiList_Src.size(); iregion++)
{
const std::vector<cv::Point> &polygon = m_DetRoiList.roiList_Src[iregion];
double result = cv::pointPolygonTest(polygon, pCenter, false);
if (result < 0)
{
continue;
}
nmaxregionIdx = iregion;
}
if (nmaxregionIdx >= 0)
{
temerror.detRegionidxList.push_back(nmaxregionIdx);
}
}
// {
// cv::Point pCenter;
// pCenter.x = temerror.roi.x + temerror.roi.width * 0.5;
// pCenter.y = temerror.roi.y + temerror.roi.height * 0.5;
// int nmaxregionIdx = 0;
// for (int iregion = 0; iregion < m_DetRoiList.roiList_Src.size(); iregion++)
// {
// const std::vector<cv::Point> &polygon = m_DetRoiList.roiList_Src[iregion];
// double result = cv::pointPolygonTest(polygon, pCenter, false);
// if (result < 0)
// {
// continue;
// }
// temerror.detRegionidxList.push_back(iregion);
// }
// if (temerror.detRegionidxList.size() <= 0)
// {
// temerror.detRegionidxList.push_back(0);
// }
// }
m_pDetResult->pQx_ErrorList->push_back(temerror);
}
m_pdetlog->AddCheckstr(PrintLevel_1, "Edge_Qx_Det", " succ qx num %ld", m_Edge_DetConfig.qx_result.size());
// printf("- %s idx %d a %f v %d h %f l %f\n", DetImgInfo_shareP->strChannel.c_str(), i, JudgArea, blobs.blobTab[i].maxValue, blobs.blobTab[i].grayDis, flen);
}
else
{
m_pdetlog->AddCheckstr(PrintLevel_1, "Edge_Qx_Det", " error %d", re);
}
return 0;
}
int ImgCheckAnalysisy::BLobToDetResult()
{
long t1 = CheckUtil::getcurTime();
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "BLobToDetResult", " Start old qx num %ld", m_pDetResult->pQx_ErrorList->size());
// 遍历每个检测blob
for (int i = 0; i < blobs.blobCount; i++)
{
cv::Rect roi;
roi.x = blobs.blobTab[i].minx;
roi.y = blobs.blobTab[i].miny;
roi.width = blobs.blobTab[i].maxx - blobs.blobTab[i].minx + 1;
roi.height = blobs.blobTab[i].maxy - blobs.blobTab[i].miny + 1;
int config_qx_type = blobs.blobTab[i].AIclasstype;
float JudgArea = blobs.blobTab[i].JudgArea;
float fsecondArea = JudgArea;
std::string qx_name = CONFIG_QX_NAME_Names[config_qx_type];
if (true)
{
QX_ERROR_INFO_ temerror;
temerror.roi = roi;
temerror.Idx = m_pDetResult->pQx_ErrorList->size();
temerror.area = blobs.blobTab[i].area;
temerror.JudgArea = JudgArea;
temerror.JudgArea_second = fsecondArea;
temerror.energy = blobs.blobTab[i].energy;
temerror.flen = blobs.blobTab[i].len;
temerror.fbreadth = blobs.blobTab[i].breadth;
temerror.nconfig_qx_type = config_qx_type;
temerror.qx_name = qx_name;
temerror.maxValue = blobs.blobTab[i].maxValue;
temerror.grayDis = blobs.blobTab[i].grayDis;
temerror.density = blobs.blobTab[i].density;
temerror.fUpIou = 0;
temerror.whiteOrBlack = blobs.blobTab[i].whiteOrblack;
{
cv::Point pCenter;
pCenter.x = roi.x + roi.width * 0.5;
pCenter.y = roi.y + roi.height * 0.5;
int nmaxregionIdx = -1;
for (int iregion = 0; iregion < m_DetRoiList.roiList_Src.size(); iregion++)
{
const std::vector<cv::Point> &polygon = m_DetRoiList.roiList_Src[iregion];
double result = cv::pointPolygonTest(polygon, pCenter, false);
if (result < 0)
{
continue;
}
nmaxregionIdx = iregion;
}
if (nmaxregionIdx >= 0)
{
temerror.detRegionidxList.push_back(nmaxregionIdx);
}
}
// {
// cv::Point pCenter;
// pCenter.x = roi.x + roi.width * 0.5;
// pCenter.y = roi.y + roi.height * 0.5;
// for (int iregion = 0; iregion < m_DetRoiList.roiList_Src.size(); iregion++)
// {
// const std::vector<cv::Point> &polygon = m_DetRoiList.roiList_Src[iregion];
// double result = cv::pointPolygonTest(polygon, pCenter, false);
// if (result < 0)
// {
// continue;
// }
// temerror.detRegionidxList.push_back(iregion);
// }
// if (temerror.detRegionidxList.size() <= 0)
// {
// temerror.detRegionidxList.push_back(0);
// }
// }
m_pDetResult->pQx_ErrorList->push_back(temerror);
// printf("- %s idx %d a %f v %d h %f l %f\n", DetImgInfo_shareP->strChannel.c_str(), i, JudgArea, blobs.blobTab[i].maxValue, blobs.blobTab[i].grayDis, flen);
}
}
long t2 = CheckUtil::getcurTime();
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "BLobToDetResult", " end qx num %ld use time %ld", m_pDetResult->pQx_ErrorList->size(), t2 - t1);
return 0;
}
int ImgCheckAnalysisy::AI_Edge(const cv::Mat &img, cv::Rect &cutRoi)
{
m_pdetlog->AddCheckstr(PrintLevel_0, "AI_Edge", "-------------------start--------------");
AI_Edge_Algin::DetConfig config;
if (DetImgInfo_shareP->bsaveProcessImg)
{
config.bSaveResultImg = true;
}
config.strChannel = DetImgInfo_shareP->strChannel;
config.pBaseCheckFunction = m_pbaseCheckFunction;
int re = m_pAI_Edge_Algin.Detect(img, &config, m_pEdge_Align_Result);
if (re != 0)
{
printf("AI_Edge Is Error = %d \n", re);
}
cutRoi = m_pEdge_Align_Result->roi;
// getchar();
return re;
}
int ImgCheckAnalysisy::CalProductSize()
{
float fw = m_CutRoi.width * m_fImgage_Scale_X;
float fh = m_CutRoi.height * m_fImgage_Scale_Y;
fw = std::ceil(fw * 10) / 10;
fh = std::ceil(fh * 10) / 10;
m_CheckResult_shareP->productWidht_mm = fw;
m_CheckResult_shareP->productHeight_mm = fh;
m_pdetlog->AddCheckstr(PrintLevel_1, "Det ROI", " [x%d, y%d, w %d,h %d] (piexl) -> [w %f h %f](mm),scale %f %f",
m_CutRoi.x, m_CutRoi.y, m_CutRoi.width, m_CutRoi.height, fw, fh, m_fImgage_Scale_X, m_fImgage_Scale_Y);
return 0;
}
int ImgCheckAnalysisy::ImgPreDet()
{
// 计算产品尺寸
CalProductSize();
if (m_pbaseCheckFunction->saveImg.bSaveClsImg)
{
creatsavedir();
}
m_CheckResult_shareP->cutSrcimg = m_pImageAllResult->detImg;
ResizeImg();
m_pImageAllResult->fscale_detToresult_x = m_pImageAllResult->resultImg.cols * 1.0f / m_pImageAllResult->detImg.cols;
m_pImageAllResult->fscale_detToresult_y = m_pImageAllResult->resultImg.rows * 1.0f / m_pImageAllResult->detImg.rows;
return 0;
}