|
|
/*
|
|
|
* @Author: your name
|
|
|
* @Date: 2022-04-20 15:50:00
|
|
|
* @LastEditTime: 2025-09-23 10:29:01
|
|
|
* @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 "CameraCheckAnalysisy.hpp"
|
|
|
#include "ImgCheckAnalysisy.hpp"
|
|
|
#include "CheckUtil.hpp"
|
|
|
#include "Define.h"
|
|
|
#include <atomic>
|
|
|
|
|
|
CameraCheckAnalysisy::CameraCheckAnalysisy()
|
|
|
{
|
|
|
|
|
|
m_nErrorCode = 0; // 错误代码
|
|
|
m_bInitSucc = false; // 初始化状态
|
|
|
m_bExit = false; // 是否退出检测
|
|
|
m_bHaveImgeDet = false;
|
|
|
m_strcameraName = "";
|
|
|
nLastCheckAnalysisyThreadIdx = 0;
|
|
|
m_pChannelFuntion = &m_AnalysisyConfig.checkFunction;
|
|
|
m_pbaseCheckFunction = &m_AnalysisyConfig.baseFunction;
|
|
|
m_nConfigIdx = -1;
|
|
|
m_pdetlog = std::make_shared<DetLog>();
|
|
|
m_pCommonAnalysisyConfig = NULL;
|
|
|
m_imageResultJudge.SetAnalysisyConfig(&m_AnalysisyConfig);
|
|
|
|
|
|
bshowimg = false;
|
|
|
}
|
|
|
|
|
|
CameraCheckAnalysisy::~CameraCheckAnalysisy()
|
|
|
{
|
|
|
}
|
|
|
|
|
|
int CameraCheckAnalysisy::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 CameraCheckAnalysisy::WaitDetImg()
|
|
|
{
|
|
|
std::unique_lock<std::mutex> lk(mtx_WaiteImg);
|
|
|
cond_WaiteImg.wait(lk, [this]()
|
|
|
{ return m_bHaveImgeDet; });
|
|
|
|
|
|
lk.unlock();
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
// 判断物料在左还是在右
|
|
|
string JudgeMaterialPosition(Mat img) {
|
|
|
if (img.empty()) {
|
|
|
cerr << "Error: Input image is empty!" << endl;
|
|
|
return "Unknown";
|
|
|
}
|
|
|
// 原图可能是彩色,内部统一转灰度计算(形参为副本,不会改动调用方图像)
|
|
|
if (img.channels() != 1) {
|
|
|
cv::Mat grayImg;
|
|
|
if (img.channels() == 4) {
|
|
|
cv::cvtColor(img, grayImg, cv::COLOR_BGRA2GRAY);
|
|
|
} else {
|
|
|
cv::cvtColor(img, grayImg, cv::COLOR_BGR2GRAY);
|
|
|
}
|
|
|
img = grayImg;
|
|
|
}
|
|
|
resize(img, img, Size(img.cols, img.rows * 0.001), 0, 0);
|
|
|
int rows = img.rows;
|
|
|
int cols = img.cols;
|
|
|
// 统计灰度值 < bg_val 的像素数量
|
|
|
int left_black_count = 0;
|
|
|
int right_black_count = 0;
|
|
|
int bg_val = 25;
|
|
|
for (int row = 0; row < rows; ++row) {
|
|
|
for (int col = 0; col < 3; ++col) {
|
|
|
if (img.at<uchar>(row, col) < 25) {
|
|
|
left_black_count++;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
for (int col = cols - 3; col < cols; ++col) {
|
|
|
if (img.at<uchar>(row, col) < 25) {
|
|
|
right_black_count++;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
// 判断物料位置
|
|
|
if (left_black_count <= right_black_count) {
|
|
|
return "Left";
|
|
|
} else if (left_black_count > right_black_count) {
|
|
|
return "Right";
|
|
|
}
|
|
|
else{
|
|
|
return "Unknown";
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//正常情况CA(img物料在左,img_B物料在右),TA(img物料在右,img_B物料在左)
|
|
|
bool ifExchange(cv::Mat &img, const cv::Mat &img_B, std::string strcam ){
|
|
|
string img_position = JudgeMaterialPosition(img);
|
|
|
string img_B_position = JudgeMaterialPosition(img_B);
|
|
|
if (strcam == "TA"){
|
|
|
if (img_position == "Left" && img_B_position == "Right"){
|
|
|
return true;
|
|
|
}
|
|
|
else{
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
else{
|
|
|
if (img_position == "Right" && img_B_position == "Left"){
|
|
|
return true;
|
|
|
}
|
|
|
else{
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
int CameraCheckAnalysisy::Detect_Pre()
|
|
|
{
|
|
|
|
|
|
std::string strlog;
|
|
|
std::string strSN;
|
|
|
std::string strBasic;
|
|
|
|
|
|
strSN = m_pCheck_Result->productBaseResult->strproductName;
|
|
|
strBasic = ">>" + strSN + " cam:" + m_strcameraName;
|
|
|
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_1, "Detect_Pre", "Cam %s ==================start", strBasic.c_str());
|
|
|
std::shared_ptr<ImageAllResult> pImageResult = m_pCheck_Result->GetNoDetImg();
|
|
|
|
|
|
if (!pImageResult)
|
|
|
{
|
|
|
return 1;
|
|
|
}
|
|
|
if (!pImageResult->result->in_shareImage->bCam_AB)
|
|
|
{
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_1, "Detect_Pre", "Cam %s ==================bCam_AB = false", strBasic.c_str());
|
|
|
return 0;
|
|
|
}
|
|
|
if (pImageResult->result->in_shareImage->img.empty() ||
|
|
|
pImageResult->result->in_shareImage->img_B.empty())
|
|
|
{
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_1, "Detect_Pre", "Cam %s ==================img.empty() || img_B.empty() ", strBasic.c_str());
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
//判断图片左右,0为左,1为右
|
|
|
bool exchange_img = ifExchange(pImageResult->result->in_shareImage->img, pImageResult->result->in_shareImage->img_B, pImageResult->result->in_shareImage->strCameraName);
|
|
|
if(exchange_img){
|
|
|
std::swap(pImageResult->result->in_shareImage->img, pImageResult->result->in_shareImage->img_B);
|
|
|
}
|
|
|
|
|
|
// printf("===66666666666666666\n");
|
|
|
int re = Mergimg(pImageResult->result->in_shareImage->img, pImageResult->result->in_shareImage->img_B,
|
|
|
pImageResult->result->in_shareImage->strCameraName, pImageResult->result->in_shareImage->strChannel);
|
|
|
|
|
|
if (pImageResult->result->in_shareImage->Det_Mode == DET_MODE_MergeImg)
|
|
|
{
|
|
|
cv::imwrite(pImageResult->result->in_shareImage->strCameraName + "_MergeImg.png", pImageResult->result->in_shareImage->img);
|
|
|
return 2;
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int CameraCheckAnalysisy::Mergimg(cv::Mat &img, const cv::Mat &img_B, std::string strcam, std::string strchannel)
|
|
|
{
|
|
|
// std::cout << img.size() << std::endl;
|
|
|
// std::cout << img_B.size() << std::endl;
|
|
|
if (img.size() != img_B.size())
|
|
|
{
|
|
|
return -1;
|
|
|
}
|
|
|
long t1, t2;
|
|
|
t1 = CheckUtil::getcurTime();
|
|
|
int re = 0;
|
|
|
cv::Rect Left_Roi;
|
|
|
cv::Rect Right_Roi;
|
|
|
cv::Mat AllImg = cv::Mat::zeros(img.rows, img.cols * 2, img.type());
|
|
|
// cv::imwrite(strcam + strchannel + "_img.png", img);
|
|
|
// cv::imwrite(strcam + strchannel + "img_B.png", img_B);
|
|
|
if (strcam == "TA")
|
|
|
{
|
|
|
cv::Rect Left_Tem_Roi;
|
|
|
cv::Point Left_Tem_Point_Up;
|
|
|
cv::Point Left_Tem_Point_Donw;
|
|
|
cv::Rect Right_Tem_Roi;
|
|
|
cv::Point Right_Tem_Point_Up;
|
|
|
cv::Point Right_Tem_Point_Donw;
|
|
|
// left Img
|
|
|
|
|
|
{
|
|
|
re = GetRectAndPoint(img, Left_Tem_Roi, Left_Tem_Point_Up, Left_Tem_Point_Donw, false, strcam, strchannel);
|
|
|
if (re != 0)
|
|
|
{
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_1, "Detect_Pre", "Cam %s Mergimg GetRectAndPoint TAA error %d", strcam.c_str(), re);
|
|
|
return 1;
|
|
|
}
|
|
|
re = GetRectAndPoint(img_B, Right_Tem_Roi, Right_Tem_Point_Up, Right_Tem_Point_Donw, true, strcam, strchannel);
|
|
|
if (re != 0)
|
|
|
{
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_1, "Detect_Pre", "Cam %s Mergimg GetRectAndPoint TAB error %d", strcam.c_str(), re);
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
img(Left_Tem_Roi).copyTo(AllImg(Left_Tem_Roi));
|
|
|
|
|
|
int hlen_left = Left_Tem_Point_Donw.y - Left_Tem_Point_Up.y;
|
|
|
int hlen_right = Right_Tem_Point_Donw.y - Right_Tem_Point_Up.y;
|
|
|
float fhscle = hlen_left * 1.0f / hlen_right;
|
|
|
int dy = Left_Tem_Point_Up.y - Right_Tem_Point_Up.y;
|
|
|
cv::Rect allroi = Right_Tem_Roi;
|
|
|
allroi.height *= fhscle;
|
|
|
allroi.x = Left_Tem_Roi.x + Left_Tem_Roi.width;
|
|
|
allroi.y += dy;
|
|
|
|
|
|
cv::Size sz;
|
|
|
sz.width = allroi.width;
|
|
|
sz.height = allroi.height;
|
|
|
|
|
|
cv::resize(img_B(Right_Tem_Roi), AllImg(allroi), sz);
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
cv::Rect Left_Tem_Roi;
|
|
|
cv::Point Left_Tem_Point_Up;
|
|
|
cv::Point Left_Tem_Point_Donw;
|
|
|
cv::Rect Right_Tem_Roi;
|
|
|
cv::Point Right_Tem_Point_Up;
|
|
|
cv::Point Right_Tem_Point_Donw;
|
|
|
// left Img
|
|
|
|
|
|
{
|
|
|
re = GetRectAndPoint(img_B, Left_Tem_Roi, Left_Tem_Point_Up, Left_Tem_Point_Donw, false, strcam, strchannel);
|
|
|
if (re != 0)
|
|
|
{
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_1, "Detect_Pre", "Cam %s Mergimg GetRectAndPoint CAA error %d", strcam.c_str(), re);
|
|
|
return 1;
|
|
|
}
|
|
|
re = GetRectAndPoint(img, Right_Tem_Roi, Right_Tem_Point_Up, Right_Tem_Point_Donw, true, strcam, strchannel);
|
|
|
if (re != 0)
|
|
|
{
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_1, "Detect_Pre", "Cam %s Mergimg GetRectAndPoint CAB error %d", strcam.c_str(), re);
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
img_B(Left_Tem_Roi).copyTo(AllImg(Left_Tem_Roi));
|
|
|
int hlen_left = Left_Tem_Point_Donw.y - Left_Tem_Point_Up.y;
|
|
|
int hlen_right = Right_Tem_Point_Donw.y - Right_Tem_Point_Up.y;
|
|
|
float fhscle = hlen_left * 1.0f / hlen_right;
|
|
|
int dy = Left_Tem_Point_Up.y - Right_Tem_Point_Up.y;
|
|
|
cv::Rect allroi = Right_Tem_Roi;
|
|
|
allroi.height *= fhscle;
|
|
|
allroi.x = Left_Tem_Roi.x + Left_Tem_Roi.width;
|
|
|
allroi.y += dy;
|
|
|
|
|
|
cv::Size sz;
|
|
|
sz.width = allroi.width;
|
|
|
sz.height = allroi.height;
|
|
|
|
|
|
cv::resize(img(Right_Tem_Roi), AllImg(allroi), sz);
|
|
|
}
|
|
|
}
|
|
|
img = AllImg;
|
|
|
t2 = CheckUtil::getcurTime();
|
|
|
// cv::imwrite(strcam + strchannel + "_merg.png", AllImg);
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_1, "Detect_Pre", "Cam %s Mergimg use time %ld ms", strcam.c_str(), t2 - t1);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int CameraCheckAnalysisy::GetRectAndPoint(const cv::Mat &img, cv::Rect &roi, cv::Point &merg_p_up, cv::Point &merg_p_down, bool bleft, std::string strcam, std::string strchannel)
|
|
|
{
|
|
|
|
|
|
bshowimg = false;
|
|
|
|
|
|
int A_line_up = 0;
|
|
|
int A_line_down = 0;
|
|
|
|
|
|
Edge_Search_Config config;
|
|
|
|
|
|
if (bshowimg)
|
|
|
{
|
|
|
if (img.channels() != 1)
|
|
|
{
|
|
|
showimg = img.clone();
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
cv::cvtColor(img, showimg, cv::COLOR_GRAY2BGR);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
config.nSearchCount = 10;
|
|
|
config.strchannel = strchannel;
|
|
|
config.directSign = DirectSign_UP;
|
|
|
if (bleft)
|
|
|
{
|
|
|
config.roi = cv::Rect(0, 0, 200, img.rows * 0.8);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
config.roi = cv::Rect(img.cols - 200, 0, 200, img.rows * 0.8);
|
|
|
}
|
|
|
|
|
|
int re123 = GetEdgePoint(img, &config, A_line_up);
|
|
|
if (re123 != 0)
|
|
|
{
|
|
|
printf("DirectSign_UP::111111111111GetEdgePoint111111 A_line_up %d\n", re123);
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
config.directSign = DirectSign_DOWN;
|
|
|
config.strchannel = strchannel + "ccc";
|
|
|
config.roi = cv::Rect(0, img.rows * 0.2, 200, img.rows * 0.8 - 1);
|
|
|
|
|
|
if (bleft)
|
|
|
{
|
|
|
config.roi = cv::Rect(0, img.rows * 0.2, 200, img.rows * 0.8 - 1);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
config.roi = cv::Rect(img.cols - 200, img.rows * 0.2, 200, img.rows * 0.8 - 1);
|
|
|
}
|
|
|
|
|
|
re123 = GetEdgePoint(img, &config, A_line_down);
|
|
|
if (re123 != 0)
|
|
|
{
|
|
|
printf("DirectSign_UP::111111111111GetEdgePoint111111 A_line_down %d\n", re123);
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
{
|
|
|
if (bshowimg)
|
|
|
{
|
|
|
cv::line(showimg, cv::Point(0, A_line_down), cv::Point(img.cols, A_line_down), cv::Scalar(0, 255, 0), 2);
|
|
|
cv::line(showimg, cv::Point(0, A_line_up), cv::Point(img.cols, A_line_up), cv::Scalar(0, 255, 0), 2);
|
|
|
|
|
|
cv::imwrite(strcam + strchannel + "_line.png", showimg);
|
|
|
}
|
|
|
}
|
|
|
// printf("DirectSign_UP::111111111111111111 re123 %d\n", re123);
|
|
|
// getchar();
|
|
|
|
|
|
// 阈值化 + 轮廓提取只支持单通道,彩色原图内部转灰度(不改动调用方图像)
|
|
|
cv::Mat grayImg;
|
|
|
if (img.channels() != 1)
|
|
|
{
|
|
|
if (img.channels() == 4)
|
|
|
{
|
|
|
cv::cvtColor(img, grayImg, cv::COLOR_BGRA2GRAY);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
cv::cvtColor(img, grayImg, cv::COLOR_BGR2GRAY);
|
|
|
}
|
|
|
}
|
|
|
const cv::Mat &workImg = (img.channels() == 1) ? img : grayImg;
|
|
|
|
|
|
cv::Mat small, smallbin;
|
|
|
cv::resize(workImg, small, cv::Size(600, 1500));
|
|
|
|
|
|
cv::threshold(small, smallbin, 15, 255,
|
|
|
cv::THRESH_BINARY);
|
|
|
|
|
|
/* 3. contours */
|
|
|
std::vector<std::vector<cv::Point>> contours;
|
|
|
cv::findContours(smallbin, contours,
|
|
|
cv::RETR_EXTERNAL,
|
|
|
cv::CHAIN_APPROX_SIMPLE);
|
|
|
|
|
|
if (contours.empty())
|
|
|
return 1;
|
|
|
|
|
|
/* 4. max contour */
|
|
|
double maxArea = 0;
|
|
|
int idx = -1;
|
|
|
for (int i = 0; i < contours.size(); i++)
|
|
|
{
|
|
|
double area = cv::contourArea(contours[i]);
|
|
|
if (area > maxArea)
|
|
|
{
|
|
|
maxArea = area;
|
|
|
idx = i;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (idx < 0)
|
|
|
return 1;
|
|
|
|
|
|
cv::Rect rSmall = cv::boundingRect(contours[idx]);
|
|
|
|
|
|
/* 5. map to original */
|
|
|
float sx = (float)workImg.cols / smallbin.cols;
|
|
|
float sy = (float)workImg.rows / smallbin.rows;
|
|
|
cv::Rect rectInSrc;
|
|
|
|
|
|
rectInSrc.x = int(rSmall.x * sx) - 50;
|
|
|
rectInSrc.y = int(rSmall.y * sy) - 50;
|
|
|
rectInSrc.width = int(rSmall.width * sx) + 100;
|
|
|
rectInSrc.height = int(rSmall.height * sy) + 100;
|
|
|
|
|
|
if (rectInSrc.y >= A_line_up)
|
|
|
{
|
|
|
rectInSrc.y = A_line_up - 5;
|
|
|
}
|
|
|
if (rectInSrc.y + rectInSrc.height <= A_line_down)
|
|
|
{
|
|
|
rectInSrc.height = A_line_down + 5 - rectInSrc.y;
|
|
|
}
|
|
|
|
|
|
if (rectInSrc.x < 0)
|
|
|
rectInSrc.x = 0;
|
|
|
if (rectInSrc.y < 0)
|
|
|
rectInSrc.y = 0;
|
|
|
if (rectInSrc.x + rectInSrc.width > workImg.cols)
|
|
|
rectInSrc.width = workImg.cols - rectInSrc.x;
|
|
|
if (rectInSrc.y + rectInSrc.height > workImg.rows)
|
|
|
{
|
|
|
rectInSrc.height = workImg.rows - rectInSrc.y;
|
|
|
}
|
|
|
|
|
|
merg_p_up.y = A_line_up;
|
|
|
merg_p_up.x = workImg.cols;
|
|
|
merg_p_down.y = A_line_down;
|
|
|
merg_p_down.x = workImg.cols;
|
|
|
roi = rectInSrc;
|
|
|
|
|
|
if (bshowimg)
|
|
|
{
|
|
|
cv::rectangle(showimg, rectInSrc, cv::Scalar(0, 0, 255), 2);
|
|
|
cv::imwrite(strcam + strchannel + "_rect.png", showimg);
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
// 对该相机下的每一张图片进行处理
|
|
|
int CameraCheckAnalysisy::Detect_Images()
|
|
|
{
|
|
|
|
|
|
std::string strlog;
|
|
|
std::string strSN;
|
|
|
std::string strBasic;
|
|
|
|
|
|
strSN = m_pCheck_Result->productBaseResult->strproductName;
|
|
|
strBasic = ">>" + strSN + " cam:" + m_strcameraName;
|
|
|
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_1, "Detect_Images", "Cam %s ==================start", strBasic.c_str());
|
|
|
// // 循环处理每个图片
|
|
|
bool bcomplete = false;
|
|
|
long time_No_CheckAnalysisy = 30 * 1000;
|
|
|
long ts = CheckUtil::getcurTime();
|
|
|
while (!bcomplete)
|
|
|
{
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
|
|
ImgCheckBase *pImgCheckAnalysisy = NULL;
|
|
|
long t1 = CheckUtil::getcurTime();
|
|
|
|
|
|
// 拿到计算资源
|
|
|
while (true)
|
|
|
{
|
|
|
|
|
|
pImgCheckAnalysisy = GetDealResult(-1);
|
|
|
if (pImgCheckAnalysisy != NULL)
|
|
|
{
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(20)); //
|
|
|
long t2 = CheckUtil::getcurTime();
|
|
|
// 如果 超过秒XX都没有拿到处理资源,则直接退出
|
|
|
if (t2 - t1 > time_No_CheckAnalysisy)
|
|
|
{
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_2, "Detect_Images", "Error %ld ms No pImgCheckAnalysisy", time_No_CheckAnalysisy);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 没有分析检测资源,直接退出
|
|
|
if (pImgCheckAnalysisy == NULL)
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
// 1、把每张图都进行AI 推理 获得 blob 结果
|
|
|
std::shared_ptr<ImageAllResult> pImageResult = m_pCheck_Result->GetNoDetImg();
|
|
|
bool bHaveNotdetImg = false;
|
|
|
// 没有未检测的图片了。
|
|
|
if (pImageResult)
|
|
|
{
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_2, "Detect_Images", "channel %s send det ", pImageResult->strChannel.c_str());
|
|
|
bHaveNotdetImg = true;
|
|
|
pImgCheckAnalysisy->SetDataRun_SharePtr(pImageResult);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
// 图片都已经送完了。
|
|
|
if (m_pCheck_Result->getImgPushComplate())
|
|
|
{
|
|
|
// printf("Cam Detect_Images %s ==================send end \n", strBasic.c_str());
|
|
|
// 没有图在进行 检测了。
|
|
|
bool bhavedet = false;
|
|
|
for (int i = 0; i < IMGCHECKANALYSISY_NUM; i++)
|
|
|
{
|
|
|
if (CHECK_THREAD_STATUS_IDLE != m_pImgCheckAnalysisy[i]->GetStatus())
|
|
|
{
|
|
|
bhavedet = true;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
// printf("Cam Detect_Images %s ==================bhavedet %d\n", strBasic.c_str(), bhavedet);
|
|
|
if (!bhavedet)
|
|
|
{
|
|
|
bcomplete = true;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
// printf("Cam Detect_Images %s ==================No send end\n", strBasic.c_str() );
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
long te = CheckUtil::getcurTime();
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_1, "Detect_Images", "Cam %s =====ALL image det complate time %ld ms=============End", strBasic.c_str(), te - ts);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int CameraCheckAnalysisy::ResultParamJudge()
|
|
|
{
|
|
|
//==================================================
|
|
|
//======= 适用于 单相机或多相机,每个相机之间的图相互没关系。
|
|
|
//=======
|
|
|
//=======
|
|
|
//=======
|
|
|
//==================================================
|
|
|
|
|
|
std::string strlog;
|
|
|
std::string strSN;
|
|
|
std::string strBasic;
|
|
|
long ts = CheckUtil::getcurTime();
|
|
|
|
|
|
int ImageNum = m_pCheck_Result->ImageALLDetResultList.size();
|
|
|
if (ImageNum <= 0)
|
|
|
{
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_1, "ResultParamJudge", "Error ImageNum <=0");
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
// 如果 参数是空,直接返回。
|
|
|
if (m_pCommonAnalysisyConfig == NULL)
|
|
|
{
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_1, "ResultParamJudge", "Error m_pCommonAnalysisyConfig == NULL");
|
|
|
return 1;
|
|
|
}
|
|
|
int regionNum = m_pCommonAnalysisyConfig->regionConfigArr.size();
|
|
|
if (regionNum <= 0)
|
|
|
{
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_1, "ResultParamJudge", "Error Config region num = 0");
|
|
|
}
|
|
|
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_1, "ResultParamJudge", "==================start image Num %d region num %d", ImageNum, regionNum);
|
|
|
|
|
|
// 对每个图片通道进行单独分析
|
|
|
for (int imgidx = 0; imgidx < ImageNum; imgidx++)
|
|
|
{
|
|
|
long t1 = CheckUtil::getcurTime();
|
|
|
int re = m_imageResultJudge.ResultJudge(m_pCheck_Result->ImageALLDetResultList.at(imgidx));
|
|
|
long t2 = CheckUtil::getcurTime();
|
|
|
m_imageResultJudge.DrawResult(m_pCheck_Result->ImageALLDetResultList.at(imgidx));
|
|
|
long t3 = CheckUtil::getcurTime();
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_1, "ResultParamJudge", " det time %ld ms judge %ld draw %ld", t3 - t1, t2 - t1, t3 - t2);
|
|
|
|
|
|
// 把结果转成 json 保存。 用以复测
|
|
|
std::shared_ptr<CheckResult> m_CheckResult_shareP = m_pCheck_Result->ImageALLDetResultList.at(imgidx)->result;
|
|
|
m_CheckResult_shareP->strResultJson = m_CheckResultJson.GetResultString(m_pCheck_Result->ImageALLDetResultList.at(imgidx)->pDetResult);
|
|
|
}
|
|
|
long te = CheckUtil::getcurTime();
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_1, "ResultParamJudge", "==================End time %ld ms ", te - ts);
|
|
|
|
|
|
// m_pdetlog->printLog(m_strcameraName);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
int CameraCheckAnalysisy::Init(std::string strcameraName)
|
|
|
{
|
|
|
m_strcameraName = strcameraName;
|
|
|
printf("CameraCheckAnalysisy::Init start \n");
|
|
|
SetNewConfig();
|
|
|
|
|
|
int re = 0;
|
|
|
re = InitCheckAnalysisy();
|
|
|
if (CHECK_OK != re)
|
|
|
{
|
|
|
printf("InitCheckAnalysisy error\n");
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
re = InitRun();
|
|
|
if (CHECK_OK != re)
|
|
|
{
|
|
|
printf("InitRun error\n");
|
|
|
m_nErrorCode = re;
|
|
|
return m_nErrorCode;
|
|
|
}
|
|
|
|
|
|
printf("CameraCheckAnalysisy::Init end \n");
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
void CameraCheckAnalysisy::SetTplInfo(const cv::RotatedRect &outerRect)
|
|
|
{
|
|
|
for (int i = 0; i < IMGCHECKANALYSISY_NUM; i++)
|
|
|
{
|
|
|
auto *p = static_cast<ImgCheckAnalysisy *>(m_pImgCheckAnalysisy[i]);
|
|
|
if (p)
|
|
|
{
|
|
|
p->SetTplInfo(outerRect);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
int CameraCheckAnalysisy::StartCheck(std::shared_ptr<CameraResult> pCamera_Check_Result)
|
|
|
{
|
|
|
if (m_bHaveImgeDet)
|
|
|
{
|
|
|
return -1;
|
|
|
}
|
|
|
{
|
|
|
std::lock_guard<std::mutex> lock(mtx_WaiteImg);
|
|
|
m_pCheck_Result = pCamera_Check_Result;
|
|
|
if (m_pCheck_Result->bJson)
|
|
|
{
|
|
|
// 如果是 复测 直接进入 参数判断阶段。
|
|
|
m_pCheck_Result->SetCheckStep(Check_Step_ResultParamJudg); // 进入预处理阶段
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
m_pCheck_Result->SetCheckStep(Check_Step_PreDet); // 进入预处理阶段
|
|
|
}
|
|
|
|
|
|
m_bHaveImgeDet = true;
|
|
|
m_pdetlog = m_pCheck_Result->detlog;
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_0, "StartCheck", "==================start %s", m_pCheck_Result->cameraBaseResult->strCameraName.c_str());
|
|
|
}
|
|
|
cond_WaiteImg.notify_all();
|
|
|
return 0;
|
|
|
}
|
|
|
int CameraCheckAnalysisy::StartThread()
|
|
|
{
|
|
|
m_bExit = false;
|
|
|
// 开启检测线程
|
|
|
ptr_thread_Run = std::make_shared<std::thread>(std::bind(&CameraCheckAnalysisy::Run, this));
|
|
|
return 0;
|
|
|
}
|
|
|
int CameraCheckAnalysisy::StopThread()
|
|
|
{
|
|
|
m_bExit = true;
|
|
|
if (ptr_thread_Run != nullptr)
|
|
|
{
|
|
|
if (ptr_thread_Run->joinable())
|
|
|
{
|
|
|
ptr_thread_Run->join();
|
|
|
}
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
int CameraCheckAnalysisy::InitRun()
|
|
|
{
|
|
|
int re;
|
|
|
re = StartThread();
|
|
|
if (CHECK_OK != re)
|
|
|
{
|
|
|
return re;
|
|
|
}
|
|
|
m_bInitSucc = true;
|
|
|
// 检测前更新参数
|
|
|
SetNewConfig();
|
|
|
return 0;
|
|
|
}
|
|
|
int CameraCheckAnalysisy::InitCheckAnalysisy()
|
|
|
{
|
|
|
int re = 0;
|
|
|
// 全局递增的 CPU 核偏移:
|
|
|
static std::atomic<int> s_cpuOffset{0};
|
|
|
for (int i = 0; i < IMGCHECKANALYSISY_NUM; i++)
|
|
|
{
|
|
|
RunInfoST RunConfig;
|
|
|
RunConfig.nThreadIdx = i;
|
|
|
{
|
|
|
// 核带下沉到库内部:不再依赖调用方传入的 nCpu_start_Idx / nCpu_num
|
|
|
int offset = s_cpuOffset.fetch_add(1) % CHECK_CPU_BAND_NUM;
|
|
|
RunConfig.nCpu_start_Idx = CHECK_CPU_BAND_START + offset;
|
|
|
}
|
|
|
RunConfig.nCpu_num = 1;
|
|
|
|
|
|
m_pImgCheckAnalysisy[i] = ImgCheckBase::GetInstance();
|
|
|
re = m_pImgCheckAnalysisy[i]->UpdateConfig((void *)&RunConfig, CHECK_CONFIG_Run);
|
|
|
if (re != 0)
|
|
|
{
|
|
|
printf("UpdateConfig %d Fail %s\n", CHECK_CONFIG_Run, m_pImgCheckAnalysisy[i]->GetErrorInfo().c_str());
|
|
|
return re;
|
|
|
}
|
|
|
re = m_pImgCheckAnalysisy[i]->UpdateConfig((void *)m_pConfig.get(), CHECK_CONFIG_Module);
|
|
|
if (re != 0)
|
|
|
{
|
|
|
printf("UpdateConfig %d Fail %s\n", CHECK_CONFIG_Module, m_pImgCheckAnalysisy[i]->GetErrorInfo().c_str());
|
|
|
return re;
|
|
|
}
|
|
|
|
|
|
re = m_pImgCheckAnalysisy[i]->RunStart();
|
|
|
if (re != 0)
|
|
|
{
|
|
|
printf("cami %s RunStart Fail ==%d\n", m_strcameraName.c_str(), re);
|
|
|
return re;
|
|
|
}
|
|
|
// printf(">>>>cami %s InitCheckAnalysisy: ImgCheckThread %d / %d Start Succ \n", m_strcameraName.c_str(), i+1, IMGCHECKANALYSISY_NUM);
|
|
|
|
|
|
if (re != 0)
|
|
|
{
|
|
|
return re;
|
|
|
}
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
int CameraCheckAnalysisy::CheckImgRun()
|
|
|
{
|
|
|
|
|
|
int re = 0;
|
|
|
Check_Step curcheckStep = m_pCheck_Result->GetCheckStep();
|
|
|
m_pdetlog->bPrintStr = false;
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_0, "CheckImgRun", "------------curcheckStep:%d ", curcheckStep);
|
|
|
// 如果是未检测状态,则开始预处理
|
|
|
if (curcheckStep == Check_Step_NODet)
|
|
|
{
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_0, "CheckImgRun", "Error curcheckStep = NODet ");
|
|
|
return 1;
|
|
|
}
|
|
|
// 检测前更新参数
|
|
|
SetNewConfig();
|
|
|
// 预处理
|
|
|
if (curcheckStep == Check_Step_PreDet)
|
|
|
{
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_0, "CheckImgRun", "cam %s : Check_Step_PreDet", m_pCheck_Result->cameraBaseResult->strCameraName.c_str());
|
|
|
re = Detect_Pre();
|
|
|
if (re != 0)
|
|
|
{
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_0, "CheckImgRun", "cam %s : Check_Step_PreDet error = %d", m_pCheck_Result->cameraBaseResult->strCameraName.c_str(), re);
|
|
|
curcheckStep = Check_Step_ImgeDet_End; // 进入到预图片检测阶段
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
curcheckStep = Check_Step_ImgeDet; // 进入到预图片检测阶段
|
|
|
}
|
|
|
|
|
|
m_pCheck_Result->SetCheckStep(curcheckStep);
|
|
|
}
|
|
|
|
|
|
// 检测每张图片
|
|
|
if (curcheckStep == Check_Step_ImgeDet)
|
|
|
{
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_0, "CheckImgRun", "cam %s : Check_Step_ImgeDet", m_pCheck_Result->cameraBaseResult->strCameraName.c_str());
|
|
|
// 检测每张图片
|
|
|
re = Detect_Images();
|
|
|
curcheckStep = Check_Step_ResultParamJudg; // 进入到预图片检测阶段
|
|
|
m_pCheck_Result->SetCheckStep(curcheckStep);
|
|
|
}
|
|
|
|
|
|
// 对检测结果进行参数判断,判断是否NG.
|
|
|
if (curcheckStep == Check_Step_ResultParamJudg)
|
|
|
{
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_0, "CheckImgRun", "cam %s : Check_Step_ResultParamJudg", m_pCheck_Result->cameraBaseResult->strCameraName.c_str());
|
|
|
// 检测每张图片
|
|
|
re = ResultParamJudge();
|
|
|
// 如果有异常
|
|
|
if (re != 0)
|
|
|
{
|
|
|
// 图片 送图没有完成,则继续等待。
|
|
|
if (!m_pCheck_Result->getImgPushComplate())
|
|
|
{
|
|
|
return 1;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
curcheckStep = Check_Step_ImgeDet_End; // 进入到预图片检测阶段
|
|
|
m_pCheck_Result->SetCheckStep(curcheckStep);
|
|
|
}
|
|
|
|
|
|
if (curcheckStep == Check_Step_ImgeDet_End)
|
|
|
{
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_0, "CheckImgRun", "cam %s : Check_Step_ImgeDet_End", m_pCheck_Result->cameraBaseResult->strCameraName.c_str());
|
|
|
|
|
|
// 所有图片都送完了。
|
|
|
if (m_pCheck_Result->getImgPushComplate())
|
|
|
{
|
|
|
curcheckStep = Check_Step_Complete; // 进入到预图片检测阶段
|
|
|
// 注意:这里先不发布 Check_Step_Complete。
|
|
|
// 若提前发布,ALLImgCheckAnalysisy 线程会立刻把结果塞给 deal,
|
|
|
// 而本线程还在 InsertCameraLog() 里写 result->det_LogList,两边并发(读/写)竞争。
|
|
|
// 因此把 SetCheckStep(Check_Step_Complete) 挪到 InsertCameraLog() 之后。
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
printf("========came %s wait img send end \n", m_strcameraName.c_str());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 检测完成,
|
|
|
if (curcheckStep == Check_Step_Complete)
|
|
|
{
|
|
|
long tend = CheckUtil::getcurTime();
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_0, "CheckImgRun", "cam %s : Check_Step_Complete", m_pCheck_Result->cameraBaseResult->strCameraName.c_str());
|
|
|
std::string strTimg = CheckUtil::getCurTimeHMS();
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_0, "CheckImgRun", "========came %s Check ALL end time %ld ms %s",
|
|
|
m_pCheck_Result->cameraBaseResult->strCameraName.c_str(), tend - m_pCheck_Result->time_start, strTimg.c_str());
|
|
|
InsertCameraLog();
|
|
|
// 日志拼接完成后再发布“检测完成”,避免 deal 提前读到正在写入的 det_LogList
|
|
|
m_pCheck_Result->SetCheckStep(Check_Step_Complete);
|
|
|
std::lock_guard<std::mutex> lock(mtx_WaiteImg);
|
|
|
m_bHaveImgeDet = false;
|
|
|
|
|
|
m_pCheck_Result.reset();
|
|
|
}
|
|
|
// m_pdetlog->printLog(m_strcameraName);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int CameraCheckAnalysisy::Run()
|
|
|
{
|
|
|
|
|
|
while (!m_bExit)
|
|
|
{
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
|
|
WaitDetImg();
|
|
|
int re = CheckImgRun();
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int CameraCheckAnalysisy::ImgEdge(cv::Mat img, cv::Mat &detMaskImg, cv::Rect &roi, int productIdx)
|
|
|
{
|
|
|
int re = 0;
|
|
|
|
|
|
return re;
|
|
|
}
|
|
|
|
|
|
int CameraCheckAnalysisy::InsertCameraLog()
|
|
|
{
|
|
|
|
|
|
int ImageNum = m_pCheck_Result->ImageALLDetResultList.size();
|
|
|
for (int imgidx = 0; imgidx < ImageNum; imgidx++)
|
|
|
{
|
|
|
|
|
|
std::shared_ptr<ImageAllResult> pImageResult = m_pCheck_Result->ImageALLDetResultList.at(imgidx);
|
|
|
std::shared_ptr<CheckResult> m_CheckResult_shareP = pImageResult->result; // 返回结果
|
|
|
if (!m_CheckResult_shareP || !pImageResult)
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
// 1、把图片的相关日志 写到 返回 日志中。
|
|
|
// 注意:DetLog 可能仍被实例线程写入,使用 GetLogs() 做加锁快照,避免并发遍历。
|
|
|
{
|
|
|
std::vector<std::string> imgLogs = pImageResult->detlog->GetLogs();
|
|
|
m_CheckResult_shareP->det_LogList.insert(m_CheckResult_shareP->det_LogList.end(),
|
|
|
imgLogs.begin(), imgLogs.end());
|
|
|
}
|
|
|
std::string str = "";
|
|
|
char buffer[256];
|
|
|
// 2、把缺陷信息 写的 返回日志中。
|
|
|
{
|
|
|
|
|
|
std::shared_ptr<One_Image_CheckResult_> pDetResult = pImageResult->pDetResult; // 检测结果
|
|
|
if (!pDetResult)
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
if (!pDetResult->pQx_ErrorList)
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
int qxNum = pDetResult->pQx_ErrorList->size();
|
|
|
|
|
|
// Add NG log
|
|
|
|
|
|
{
|
|
|
sprintf(buffer, " =====================NG num %d=============================", pImageResult->NG_num);
|
|
|
str = buffer;
|
|
|
m_CheckResult_shareP->det_LogList.push_back(str);
|
|
|
}
|
|
|
for (int qxidx = 0; qxidx < qxNum; qxidx++)
|
|
|
{
|
|
|
QX_ERROR_INFO_ *QX_info = &pDetResult->pQx_ErrorList->at(qxidx);
|
|
|
|
|
|
if (QX_info->result == QX_RESULT_TYPE_NG)
|
|
|
{
|
|
|
std::shared_ptr<DetLog> pQxLog = pDetResult->pQx_ErrorList->at(qxidx).detlog;
|
|
|
std::vector<std::string> qxLogs = pQxLog->GetLogs();
|
|
|
m_CheckResult_shareP->det_LogList.insert(m_CheckResult_shareP->det_LogList.end(),
|
|
|
qxLogs.begin(), qxLogs.end());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
{
|
|
|
sprintf(buffer, " =====================YS num %d=============================", pImageResult->YS_num);
|
|
|
str = buffer;
|
|
|
m_CheckResult_shareP->det_LogList.push_back(str);
|
|
|
}
|
|
|
for (int qxidx = 0; qxidx < qxNum; qxidx++)
|
|
|
{
|
|
|
QX_ERROR_INFO_ *QX_info = &pDetResult->pQx_ErrorList->at(qxidx);
|
|
|
|
|
|
if (QX_info->result == QX_RESULT_TYPE_YS)
|
|
|
{
|
|
|
std::shared_ptr<DetLog> pQxLog = pDetResult->pQx_ErrorList->at(qxidx).detlog;
|
|
|
std::vector<std::string> qxLogs = pQxLog->GetLogs();
|
|
|
m_CheckResult_shareP->det_LogList.insert(m_CheckResult_shareP->det_LogList.end(),
|
|
|
qxLogs.begin(), qxLogs.end());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
{
|
|
|
sprintf(buffer, " =====================OK num %d=============================", pImageResult->Ok_num);
|
|
|
str = buffer;
|
|
|
m_CheckResult_shareP->det_LogList.push_back(str);
|
|
|
}
|
|
|
for (int qxidx = 0; qxidx < qxNum; qxidx++)
|
|
|
{
|
|
|
QX_ERROR_INFO_ *QX_info = &pDetResult->pQx_ErrorList->at(qxidx);
|
|
|
|
|
|
if (QX_info->result == QX_RESULT_TYPE_OK)
|
|
|
{
|
|
|
std::shared_ptr<DetLog> pQxLog = pDetResult->pQx_ErrorList->at(qxidx).detlog;
|
|
|
std::vector<std::string> qxLogs = pQxLog->GetLogs();
|
|
|
m_CheckResult_shareP->det_LogList.insert(m_CheckResult_shareP->det_LogList.end(),
|
|
|
qxLogs.begin(), qxLogs.end());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
{
|
|
|
sprintf(buffer, " =====================NO Judge num %d=============================", pImageResult->NoJudge_num);
|
|
|
str = buffer;
|
|
|
m_CheckResult_shareP->det_LogList.push_back(str);
|
|
|
}
|
|
|
for (int qxidx = 0; qxidx < qxNum; qxidx++)
|
|
|
{
|
|
|
QX_ERROR_INFO_ *QX_info = &pDetResult->pQx_ErrorList->at(qxidx);
|
|
|
|
|
|
if (QX_info->result == QX_RESULT_TYPE_NoJduge)
|
|
|
{
|
|
|
std::shared_ptr<DetLog> pQxLog = pDetResult->pQx_ErrorList->at(qxidx).detlog;
|
|
|
std::vector<std::string> qxLogs = pQxLog->GetLogs();
|
|
|
m_CheckResult_shareP->det_LogList.insert(m_CheckResult_shareP->det_LogList.end(),
|
|
|
qxLogs.begin(), qxLogs.end());
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
{
|
|
|
sprintf(buffer, " =====================Cam Log =============================");
|
|
|
str = buffer;
|
|
|
m_CheckResult_shareP->det_LogList.push_back(str);
|
|
|
}
|
|
|
|
|
|
// 3、把相机的日志 写到 返回日志中。
|
|
|
{
|
|
|
std::vector<std::string> camLogs = m_pCheck_Result->detlog->GetLogs();
|
|
|
m_CheckResult_shareP->det_LogList.insert(m_CheckResult_shareP->det_LogList.end(),
|
|
|
camLogs.begin(), camLogs.end());
|
|
|
}
|
|
|
|
|
|
{
|
|
|
sprintf(buffer, " =====================Product Log =============================");
|
|
|
str = buffer;
|
|
|
m_CheckResult_shareP->det_LogList.push_back(str);
|
|
|
}
|
|
|
// 4、把产品相关日志 写到 返回日志中。
|
|
|
{
|
|
|
std::vector<std::string> productLogs = m_pCheck_Result->productBaseResult->detlog->GetLogs();
|
|
|
m_CheckResult_shareP->det_LogList.insert(m_CheckResult_shareP->det_LogList.end(),
|
|
|
productLogs.begin(), productLogs.end());
|
|
|
}
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
ChannelCheckFunction *CameraCheckAnalysisy::GetChannelFuntion(std::string strChannelName)
|
|
|
{
|
|
|
ChannelCheckFunction *p = NULL;
|
|
|
// printf("m_pChannelFuntion->channelFunctionArr.size() %zu\n", m_pChannelFuntion->channelFunctionArr.size());
|
|
|
for (int i = 0; i < m_pChannelFuntion->channelFunctionArr.size(); i++)
|
|
|
{
|
|
|
if (CheckUtil::compareIgnoreCase(m_pChannelFuntion->channelFunctionArr[i].strChannelName, strChannelName))
|
|
|
{
|
|
|
p = &m_pChannelFuntion->channelFunctionArr[i];
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return p;
|
|
|
}
|
|
|
int CameraCheckAnalysisy::SetNewConfig()
|
|
|
{
|
|
|
|
|
|
if (m_pConfig.get() == nullptr)
|
|
|
{
|
|
|
return 1;
|
|
|
}
|
|
|
if (m_nConfigIdx < 0)
|
|
|
{
|
|
|
m_nConfigIdx = m_pConfig->GetConfigIdx();
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_1, "update config", "CameraCheckAnalysisy:%s m_nConfigIdx %d", m_strcameraName.c_str(), m_nConfigIdx);
|
|
|
}
|
|
|
|
|
|
if (m_pConfig->GetConfigUpdataStatus(ConfigType_Analysisy_Common_XL, m_nConfigIdx))
|
|
|
{
|
|
|
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_imageResultJudge.UpdateConfig();
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
m_pCommonAnalysisyConfig = NULL;
|
|
|
printf("m_AnalysisyConfig.commonCheckConfig.nodeConfigArr == 0 \n");
|
|
|
}
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_1, "update config", "Get New analysisy config");
|
|
|
// printf("*******ALLImgCheckAnalysisy m_pConfig*********************** Update GetConfig \n");
|
|
|
// m_AnalysisyConfig.checkFunction.print("Update GetConfig");
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int CameraCheckAnalysisy::preDet_ZF(std::shared_ptr<ImageDetconfig> p, std::shared_ptr<ImageDetResult> &pResult)
|
|
|
{
|
|
|
ImgCheckBase *pImgCheckAnalysisy = NULL;
|
|
|
long t1 = CheckUtil::getcurTime();
|
|
|
int outTime = 1000 * 5;
|
|
|
while (true)
|
|
|
{
|
|
|
|
|
|
pImgCheckAnalysisy = GetDealResult(-1);
|
|
|
if (pImgCheckAnalysisy != NULL)
|
|
|
{
|
|
|
break;
|
|
|
}
|
|
|
long t2 = CheckUtil::getcurTime();
|
|
|
// 超时
|
|
|
if (t2 - t1 > outTime)
|
|
|
{
|
|
|
return 1;
|
|
|
}
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(20)); // 模拟消费过程
|
|
|
}
|
|
|
p->pBaseImgCheckConfig->imgtype = 1;
|
|
|
pImgCheckAnalysisy->CheckImg(p, pResult);
|
|
|
p->pBaseImgCheckConfig->imgtype = 0;
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
ImgCheckBase *CameraCheckAnalysisy::GetDealResult(int idx)
|
|
|
{
|
|
|
|
|
|
// 特殊情况
|
|
|
if (idx >= 0 && idx < IMGCHECKANALYSISY_NUM)
|
|
|
{
|
|
|
|
|
|
if (CHECK_THREAD_STATUS_IDLE == m_pImgCheckAnalysisy[idx]->GetStatus())
|
|
|
{
|
|
|
// printf("*-*-*-*-*-*-*-*- use m_pImgCheckAnalysisy %d \n", idx);
|
|
|
return m_pImgCheckAnalysisy[idx];
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
return NULL;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
int re = 0;
|
|
|
|
|
|
int nidx = nLastCheckAnalysisyThreadIdx;
|
|
|
|
|
|
for (int i = 0; i < IMGCHECKANALYSISY_NUM; i++)
|
|
|
{
|
|
|
if (nidx >= IMGCHECKANALYSISY_NUM)
|
|
|
{
|
|
|
nidx = 0;
|
|
|
}
|
|
|
if (CHECK_THREAD_STATUS_IDLE == m_pImgCheckAnalysisy[nidx]->GetStatus())
|
|
|
{
|
|
|
nLastCheckAnalysisyThreadIdx = nidx + 1;
|
|
|
// printf("*-*-*-*-*-*-*-*- use m_pImgCheckAnalysisy %d \n", nidx);
|
|
|
return m_pImgCheckAnalysisy[nidx];
|
|
|
}
|
|
|
nidx++;
|
|
|
}
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
int CameraCheckAnalysisy::GetEdgePoint(const cv::Mat &imgSrc, Edge_Search_Config *pEdge_Search_Config, int &outP)
|
|
|
{
|
|
|
bool bdbuge = false;
|
|
|
bdbuge = bshowimg;
|
|
|
if (imgSrc.empty())
|
|
|
{
|
|
|
return -11;
|
|
|
}
|
|
|
// 边缘搜索仅支持单通道;彩色/BGRA 原图在此内部转灰度(不改动调用方图像)
|
|
|
cv::Mat grayImg;
|
|
|
if (imgSrc.channels() != 1)
|
|
|
{
|
|
|
if (imgSrc.channels() == 4)
|
|
|
{
|
|
|
cv::cvtColor(imgSrc, grayImg, cv::COLOR_BGRA2GRAY);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
cv::cvtColor(imgSrc, grayImg, cv::COLOR_BGR2GRAY);
|
|
|
}
|
|
|
}
|
|
|
const cv::Mat &img = (imgSrc.channels() == 1) ? imgSrc : grayImg;
|
|
|
// 检查roi;
|
|
|
if (!CheckUtil::RoiInImg(pEdge_Search_Config->roi, img))
|
|
|
{
|
|
|
return -13;
|
|
|
}
|
|
|
if (!pEdge_Search_Config->CheckConfigValid())
|
|
|
{
|
|
|
return -14;
|
|
|
}
|
|
|
std::vector<cv::Point> pointList;
|
|
|
bool search_UP_DOWN = false;
|
|
|
cv::Rect roi = pEdge_Search_Config->roi;
|
|
|
int sx = roi.x;
|
|
|
int ex = roi.x + roi.width;
|
|
|
int sy = roi.y;
|
|
|
int ey = roi.y + roi.height;
|
|
|
|
|
|
int nSearchLen = roi.width; // 搜索区域的长度
|
|
|
int nCurPoint_Step = pEdge_Search_Config->stepCount; // 当前点搜索的步长
|
|
|
|
|
|
// 搜索小范围确认
|
|
|
int nhalfrang = (int)pEdge_Search_Config->nSearchrange / 2;
|
|
|
int nrange_start = 0 - nhalfrang;
|
|
|
int nrange_end = 0 - nhalfrang;
|
|
|
int num = 0;
|
|
|
while (true)
|
|
|
{
|
|
|
num++;
|
|
|
nrange_end++;
|
|
|
if (num >= pEdge_Search_Config->nSearchrange)
|
|
|
{
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
// 判断方向
|
|
|
switch (pEdge_Search_Config->directSign)
|
|
|
{
|
|
|
case DirectSign_UP:
|
|
|
search_UP_DOWN = true;
|
|
|
nSearchLen = roi.width;
|
|
|
sx = roi.x;
|
|
|
ex = roi.x + roi.width;
|
|
|
sy = roi.y;
|
|
|
ey = roi.y + roi.height;
|
|
|
nCurPoint_Step = pEdge_Search_Config->stepCount;
|
|
|
break;
|
|
|
case DirectSign_DOWN:
|
|
|
search_UP_DOWN = true;
|
|
|
nSearchLen = roi.width;
|
|
|
nCurPoint_Step = -pEdge_Search_Config->stepCount;
|
|
|
|
|
|
sx = roi.x;
|
|
|
ex = roi.x + roi.width;
|
|
|
sy = roi.y + roi.height - 1;
|
|
|
ey = roi.y;
|
|
|
break;
|
|
|
case DirectSign_Left:
|
|
|
nSearchLen = roi.height;
|
|
|
search_UP_DOWN = false;
|
|
|
nCurPoint_Step = pEdge_Search_Config->stepCount;
|
|
|
|
|
|
sx = roi.x;
|
|
|
ex = roi.x + roi.width;
|
|
|
sy = roi.y;
|
|
|
ey = roi.y + roi.height;
|
|
|
break;
|
|
|
case DirectSign_Right:
|
|
|
nSearchLen = roi.height;
|
|
|
search_UP_DOWN = false;
|
|
|
nCurPoint_Step = -pEdge_Search_Config->stepCount;
|
|
|
|
|
|
sx = roi.x + roi.width - 1;
|
|
|
ex = roi.x;
|
|
|
sy = roi.y;
|
|
|
ey = roi.y + roi.height;
|
|
|
break;
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
// 搜索 点数
|
|
|
int nSearchPointNum = pEdge_Search_Config->nSearchCount;
|
|
|
// 搜素点的间隔
|
|
|
int nSearchPointStep = 1;
|
|
|
if (nSearchPointNum > 1)
|
|
|
{
|
|
|
nSearchPointStep = int(nSearchLen * 1.0f / (nSearchPointNum - 1));
|
|
|
}
|
|
|
|
|
|
if (bdbuge)
|
|
|
{
|
|
|
cv::rectangle(showimg, roi, cv::Scalar(255, 0, 0), 2);
|
|
|
printf("nSearchPointStep %d nCurPoint_Step %d,nrange_start %d %d\n", nSearchPointStep, nCurPoint_Step, nrange_start, nrange_end);
|
|
|
}
|
|
|
|
|
|
uchar *pdata = (uchar *)img.data;
|
|
|
int offt = 0;
|
|
|
// 搜索 上下边
|
|
|
if (search_UP_DOWN)
|
|
|
{
|
|
|
// 每个搜索点 分布在X方向。
|
|
|
for (int x = sx; x < ex; x = x + nSearchPointStep)
|
|
|
{
|
|
|
int bOKNum = 0;
|
|
|
int cur_x = x;
|
|
|
int cur_y = sy;
|
|
|
bool bSucc = false;
|
|
|
int succ_y = 0;
|
|
|
|
|
|
// 对每个搜索点进行 y方向搜索
|
|
|
for (int y = sy;; y = y + nCurPoint_Step)
|
|
|
{
|
|
|
|
|
|
if (y < 0 || y >= img.rows)
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
//
|
|
|
if (nCurPoint_Step > 0 && y > ey)
|
|
|
{
|
|
|
break;
|
|
|
}
|
|
|
if (nCurPoint_Step < 0 && y < ey)
|
|
|
{
|
|
|
break;
|
|
|
}
|
|
|
offt = y * img.cols;
|
|
|
int range_okNum = 0;
|
|
|
// 对一定范围的点进行判断
|
|
|
for (int k = nrange_start; k < nrange_end; k++)
|
|
|
{
|
|
|
int rangeX = x + k;
|
|
|
if (rangeX < 0 || rangeX >= img.cols)
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
offt += rangeX;
|
|
|
if (offt < 0 || offt >= img.cols * img.rows)
|
|
|
{
|
|
|
printf("rangeX %d nCurPoint_Step %d off %d x %d y %d sy %d ey %d %d %d\n", rangeX, nCurPoint_Step, offt, x, y, sy, ey, img.cols, img.rows);
|
|
|
}
|
|
|
|
|
|
if (pdata[offt] >= pEdge_Search_Config->nValueThreshold) // 找到
|
|
|
{
|
|
|
range_okNum++;
|
|
|
}
|
|
|
}
|
|
|
if (range_okNum >= pEdge_Search_Config->nSearchrange)
|
|
|
{
|
|
|
if (bdbuge)
|
|
|
{
|
|
|
cv::circle(showimg, cv::Point(x, y), 1, cv::Scalar(0, 0, 255));
|
|
|
}
|
|
|
if (bOKNum == 0)
|
|
|
{
|
|
|
cur_y = y;
|
|
|
}
|
|
|
|
|
|
bOKNum++;
|
|
|
|
|
|
// 连续搜索到 满足要求的点。
|
|
|
if (bOKNum >= pEdge_Search_Config->nLimit)
|
|
|
{
|
|
|
bSucc = true;
|
|
|
succ_y = y;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
// 如果有间断,需要重新计算连续情况。
|
|
|
bOKNum = 0;
|
|
|
if (bdbuge)
|
|
|
{
|
|
|
cv::circle(showimg, cv::Point(x, y), 1, cv::Scalar(0, 255, 0));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
if (bSucc)
|
|
|
{
|
|
|
cv::Point p(cur_x, cur_y);
|
|
|
if (bdbuge)
|
|
|
{
|
|
|
cv::circle(showimg, p, 3, cv::Scalar(255, 0, 0));
|
|
|
}
|
|
|
pointList.push_back(p);
|
|
|
|
|
|
if (pointList.size() > 5)
|
|
|
{
|
|
|
// printf("=============feeeee\n");
|
|
|
sy = succ_y - 100;
|
|
|
ey = succ_y + 100;
|
|
|
if (sy < 0)
|
|
|
{
|
|
|
sy = 0;
|
|
|
}
|
|
|
if (ey >= img.rows)
|
|
|
{
|
|
|
ey = img.rows - 1;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
else // 搜索 左右边
|
|
|
{
|
|
|
// 每个搜索点 分布在X方向。
|
|
|
for (int y = sy; y < ey; y = y + nSearchPointStep)
|
|
|
{
|
|
|
int bOKNum = 0;
|
|
|
int cur_x = sx;
|
|
|
int cur_y = y;
|
|
|
bool bSucc = false;
|
|
|
int succ_x = 0;
|
|
|
|
|
|
// 对每个搜索点进行 y方向搜索
|
|
|
for (int x = sx;; x = x + nCurPoint_Step)
|
|
|
{
|
|
|
if (x < 0 || x >= img.cols)
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
//
|
|
|
if (nCurPoint_Step > 0 && x > ex)
|
|
|
{
|
|
|
break;
|
|
|
}
|
|
|
if (nCurPoint_Step < 0 && x < ex)
|
|
|
{
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
int range_okNum = 0;
|
|
|
// 对一定范围的点进行判断
|
|
|
for (int k = nrange_start; k < nrange_end; k++)
|
|
|
{
|
|
|
int rangey = y + k;
|
|
|
if (rangey < 0 || rangey >= img.rows)
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
offt = rangey * img.cols + x;
|
|
|
if (offt < 0 || offt >= img.cols * img.rows)
|
|
|
{
|
|
|
printf("rangey %d off %d x %d y %d ey %d %d %d\n", rangey, offt, x, y, ey, img.cols, img.rows);
|
|
|
}
|
|
|
if (pdata[offt] >= pEdge_Search_Config->nValueThreshold) // 找到
|
|
|
{
|
|
|
range_okNum++;
|
|
|
}
|
|
|
}
|
|
|
if (range_okNum >= pEdge_Search_Config->nSearchrange)
|
|
|
{
|
|
|
if (bdbuge)
|
|
|
{
|
|
|
cv::circle(showimg, cv::Point(x, y), 1, cv::Scalar(0, 0, 255));
|
|
|
}
|
|
|
if (bOKNum == 0)
|
|
|
{
|
|
|
cur_x = x;
|
|
|
}
|
|
|
|
|
|
bOKNum++;
|
|
|
// 连续搜索到 满足要求的点。
|
|
|
if (bOKNum >= pEdge_Search_Config->nLimit)
|
|
|
{
|
|
|
bSucc = true;
|
|
|
succ_x = x;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
// 如果有间断,需要重新计算连续情况。
|
|
|
bOKNum = 0;
|
|
|
if (bdbuge)
|
|
|
{
|
|
|
cv::circle(showimg, cv::Point(x, y), 1, cv::Scalar(0, 255, 0));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
if (bSucc)
|
|
|
{
|
|
|
cv::Point p(cur_x, cur_y);
|
|
|
if (bdbuge)
|
|
|
{
|
|
|
cv::circle(showimg, p, 3, cv::Scalar(255, 0, 0));
|
|
|
}
|
|
|
pointList.push_back(p);
|
|
|
if (pointList.size() > 5)
|
|
|
{
|
|
|
// printf("=============feeeee\n");
|
|
|
sx = succ_x - 100;
|
|
|
ex = succ_x + 100;
|
|
|
if (sx < 0)
|
|
|
{
|
|
|
sx = 0;
|
|
|
}
|
|
|
if (ex >= img.cols)
|
|
|
{
|
|
|
ex = img.cols - 1;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (bdbuge)
|
|
|
{
|
|
|
cv::imwrite(pEdge_Search_Config->strchannel + "show.png", showimg);
|
|
|
}
|
|
|
|
|
|
{
|
|
|
const int maxDeviation = 10; // 可调阈值:最大允许偏离像素
|
|
|
|
|
|
std::vector<cv::Point> avgPoints;
|
|
|
|
|
|
int PNum = pointList.size();
|
|
|
// 第一次计算粗略均值
|
|
|
int sum_y = 0, sum_x = 0;
|
|
|
for (const auto &pt : pointList)
|
|
|
{
|
|
|
|
|
|
sum_x += pt.x;
|
|
|
sum_y += pt.y;
|
|
|
}
|
|
|
float avg_y = sum_y * 1.0f / PNum;
|
|
|
float avg_x = sum_x * 1.0f / PNum;
|
|
|
|
|
|
// 过滤异常点
|
|
|
std::vector<cv::Point> filtered;
|
|
|
for (const auto &pt : pointList)
|
|
|
{
|
|
|
if (search_UP_DOWN) // 横向:判断 y 偏差
|
|
|
{
|
|
|
|
|
|
if (std::abs(pt.y - avg_y) <= maxDeviation)
|
|
|
filtered.push_back(pt);
|
|
|
}
|
|
|
else // 纵向:判断 x 偏差
|
|
|
{
|
|
|
if (std::abs(pt.x - avg_x) <= maxDeviation)
|
|
|
filtered.push_back(pt);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (filtered.empty())
|
|
|
return -1;
|
|
|
|
|
|
int sum_fx = 0, sum_fy = 0;
|
|
|
for (const auto &pt : filtered)
|
|
|
{
|
|
|
sum_fx += pt.x;
|
|
|
sum_fy += pt.y;
|
|
|
}
|
|
|
|
|
|
if (search_UP_DOWN) // 横向:判断 y 偏差
|
|
|
{
|
|
|
outP = sum_fy / (int)filtered.size();
|
|
|
}
|
|
|
else // 纵向:判断 x 偏差
|
|
|
{
|
|
|
outP = sum_fx / (int)filtered.size();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int CameraCheckAnalysisy::GetLine(const cv::Mat &img, std::vector<cv::Point> &pointList, int lineNum, int xory, int &outP)
|
|
|
{
|
|
|
|
|
|
if (pointList.size() < 0)
|
|
|
return -1;
|
|
|
|
|
|
const int maxDeviation = 10; // 可调阈值:最大允许偏离像素
|
|
|
|
|
|
std::vector<cv::Point> avgPoints;
|
|
|
|
|
|
int PNum = pointList.size();
|
|
|
// 第一次计算粗略均值
|
|
|
int sum_y = 0, sum_x = 0;
|
|
|
for (const auto &pt : pointList)
|
|
|
{
|
|
|
|
|
|
sum_x += pt.x;
|
|
|
sum_y += pt.y;
|
|
|
}
|
|
|
float avg_y = sum_y * 1.0f / PNum;
|
|
|
float avg_x = sum_x * 1.0f / PNum;
|
|
|
|
|
|
// 过滤异常点
|
|
|
std::vector<cv::Point> filtered;
|
|
|
for (const auto &pt : pointList)
|
|
|
{
|
|
|
if (xory == 0) // 横向:判断 y 偏差
|
|
|
{
|
|
|
if (std::abs(pt.y - avg_y) <= maxDeviation)
|
|
|
filtered.push_back(pt);
|
|
|
}
|
|
|
else // 纵向:判断 x 偏差
|
|
|
{
|
|
|
if (std::abs(pt.x - avg_x) <= maxDeviation)
|
|
|
filtered.push_back(pt);
|
|
|
}
|
|
|
}
|
|
|
if (filtered.empty())
|
|
|
return -1;
|
|
|
|
|
|
int sum_fx = 0, sum_fy = 0;
|
|
|
for (const auto &pt : filtered)
|
|
|
{
|
|
|
sum_fx += pt.x;
|
|
|
sum_fy += pt.y;
|
|
|
}
|
|
|
|
|
|
if (xory == 0) // 横向:判断 y 偏差
|
|
|
{
|
|
|
outP = sum_fy / (int)filtered.size();
|
|
|
}
|
|
|
else // 纵向:判断 x 偏差
|
|
|
{
|
|
|
outP = sum_fx / (int)filtered.size();
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
}
|