用传统算法优化上下料检测算法

master
xiewenji 3 weeks ago
parent abce6939cc
commit 1a02b69445

@ -87,12 +87,19 @@ int ALL_Detect::RunStart(void *pconfig1)
break;
}
case CAMERA_Feeding:
{
if (!m_checkBase)
m_checkBase = std::make_shared<Chip_Detect>();
runconfig.str_AIModelJson = m_cam_param.AIModel_param_path + "AIModel_Chip.json";
runconfig.str_RunJson = m_cam_param.check_param_path + "param_feed-up.json";
break;
}
case CAMERA_Blanking:
{
if (!m_checkBase)
m_checkBase = std::make_shared<Chip_Detect>();
runconfig.str_AIModelJson = m_cam_param.AIModel_param_path + "AIModel_Chip.json";
// runconfig.str_RunJson = m_cam_param.check_param_path + "param_Chip.json";
runconfig.str_RunJson = m_cam_param.check_param_path + "param_feed-down.json";
break;
}
default:

@ -117,6 +117,11 @@ enum DetRotateType
Ratio_180 = 2,
Ratio_270 = 3,
};
struct ChipDet{
cv::Rect rect{0, 0, 0, 0};
int detWidth = 0;
int detHeight = 0;
};
// 基础检测功能 基础检测
struct Base_Function_DetConfig
@ -132,6 +137,9 @@ struct Base_Function_DetConfig
int chip_height_offset_mm; // 芯片高度偏差 mm 1107-add
double calibration_coeff_x; // 标定系数x mm/pixel
double calibration_coeff_y; // 标定系数y mm/pixel
ChipDet chipDetConfig1;
ChipDet chipDetConfig2;
double chipThr;
Base_Function_DetConfig()
{
Init();
@ -150,6 +158,7 @@ struct Base_Function_DetConfig
chip_height_offset_mm = 0;
calibration_coeff_x = 1.0; // 1107-add
calibration_coeff_y = 1.0; // 1107-add
chipThr = 0;
}
void copy(Base_Function_DetConfig tem)
@ -165,6 +174,7 @@ struct Base_Function_DetConfig
this->chip_height_offset_mm = tem.chip_height_offset_mm;
this->calibration_coeff_x = tem.calibration_coeff_x; // 1107-add
this->calibration_coeff_y = tem.calibration_coeff_y; // 1107-add
this->chipThr = tem.chipThr;
}
void print(std::string str)
{

@ -559,5 +559,53 @@ int CheckBaseParamJson::GetFunction(Json::Value value)
// pdetConfig->Init();
// }
}
if ("ChipDet" == strCode) // 1009-add
{
auto value_f = value;
std::cout << value_f << std::endl;
// std::cout << "m_pconfig->baseCheckFunction.bChipOffsetOpen=" << m_pconfig->baseCheckFunction.bChipOffsetOpen << std::endl; // 1009-add
Base_Function_DetConfig *pdetConfig = &m_pconfig->baseCheckFunction.detconfig;
pdetConfig->bOpen = value_f["isOpen"].asBool();
if (pdetConfig->bOpen)
{
auto DetCrop1 = value_f["form"]["DetCrop1"];
if (DetCrop1.isObject()) {
cv::Rect rect{
DetCrop1["crop"]["x"] ? DetCrop1["crop"]["x"].asInt() : 0,
DetCrop1["crop"]["y"] ? DetCrop1["crop"]["y"].asInt() : 0,
DetCrop1["crop"]["width"] ? DetCrop1["crop"]["width"].asInt() : 0,
DetCrop1["crop"]["height"] ? DetCrop1["crop"]["height"].asInt() : 0
};
pdetConfig->chipDetConfig1.rect = rect;
pdetConfig->chipDetConfig1.detWidth = DetCrop1["cellWidth"].asInt();
pdetConfig->chipDetConfig1.detHeight = DetCrop1["cellHeight"].asInt();
}
auto DetCrop2 = value_f["form"]["DetCrop2"];
if (DetCrop2.isObject()) {
cv::Rect rect{
DetCrop2["crop"]["x"] ? DetCrop2["crop"]["x"].asInt() : 0,
DetCrop2["crop"]["y"] ? DetCrop2["crop"]["y"].asInt() : 0,
DetCrop2["crop"]["width"] ? DetCrop2["crop"]["width"].asInt() : 0,
DetCrop2["crop"]["height"] ? DetCrop2["crop"]["height"].asInt() : 0
};
pdetConfig->chipDetConfig2.rect = rect;
pdetConfig->chipDetConfig2.detWidth = DetCrop2["cellWidth"].asInt();
pdetConfig->chipDetConfig2.detHeight = DetCrop2["cellHeight"].asInt();
}
pdetConfig->chipThr = value_f["form"]["ChipThr"].asFloat();
if (pdetConfig->chipThr <= 0)
{
pdetConfig->chipThr = 0.1;
}
}
// else
// {
// pdetConfig->Init();
// }
}
return 0;
}

@ -28,8 +28,6 @@ private:
// 初始化模型
int InitModel();
int Thread_Run(const cv::Mat &img);
int Draw(const cv::Mat &img, cv::Mat &resultimg);
int GetBlob(cv::Mat maskImg);
@ -38,6 +36,8 @@ private:
int DetectImg(const cv::Mat &img);
int CutChipDetRoi(const cv::Mat &img, cv::Rect &Roi, std::vector<cv::Rect> &smallRoiList);
private:
int m_nErrorCode; // 错误代码
std::shared_ptr<shareImage> DetImgInfo_shareP;

@ -29,29 +29,29 @@ int Chip_Detect::RunStart(void *pconfig1)
m_pRunConfig.copy(*(RunInfoST *)pconfig1);
m_bInitSucc = false;
LoadAIModelParm(m_pRunConfig.str_AIModelJson, m_AIModelConfigList);
if (m_AIModelConfigList.get() == nullptr)
{
std::cout << "m_AIModelConfigList is null\n";
return 1;
}
m_AIModelConfigList->print("m_AIModelConfigList");
// LoadCheckBaseConfig(m_pRunConfig.str_RunJson, m_CheckBaseConfig);
// if (m_CheckBaseConfig.get() == nullptr)
// LoadAIModelParm(m_pRunConfig.str_AIModelJson, m_AIModelConfigList);
// if (m_AIModelConfigList.get() == nullptr)
// {
// std::cout << "m_CheckBaseConfig is null\n";
// std::cout << "m_AIModelConfigList is null\n";
// return 1;
// }
// m_CheckBaseConfig->print("m_CheckBaseConfig");
int re = InitModel();
if (0 != re)
// m_AIModelConfigList->print("m_AIModelConfigList");
LoadCheckBaseConfig(m_pRunConfig.str_RunJson, m_CheckBaseConfig);
if (m_CheckBaseConfig.get() == nullptr)
{
printf("AI_DetModel Init Fail\n");
return re;
std::cout << "m_CheckBaseConfig is null\n";
return 1;
}
m_CheckBaseConfig->print("m_CheckBaseConfig");
// int re = InitModel();
// if (0 != re)
// {
// printf("AI_DetModel Init Fail\n");
// return re;
// }
printf("init end \n");
m_bInitSucc = true;
return 0;
@ -87,22 +87,26 @@ int Chip_Detect::CheckRun()
t1 = CheckUtil::getcurTime();
CheckImgInit();
cv::Mat detimg = DetImgInfo_shareP->img;
if (detimg.empty())
{
std::cout << "detimg is empty\n";
return 1;
}
// if (!CheckUtil::RoiInImg(m_CheckBaseConfig->crop, detimg))
// {
// return 1;
// }
// if (m_Update_config)
// {
// LoadCheckBaseConfig(m_pRunConfig.str_RunJson, m_CheckBaseConfig);
// m_Update_config = false;
// }
// Base_Function_DetConfig *pdetConfig = &m_CheckBaseConfig->baseCheckFunction.detconfig;
// // detimg = DetImgInfo_shareP->img(pdetConfig->cropROI);
Base_Function_DetConfig *pdetConfig = &m_CheckBaseConfig->baseCheckFunction.detconfig;
auto rec1 = pdetConfig->chipDetConfig1.rect;
auto rec2 = pdetConfig->chipDetConfig2.rect;
if (!CheckUtil::RoiInImg(rec1, detimg) || !CheckUtil::RoiInImg(rec2, detimg))
{
std::cout << "crop roi is invalid\n";
return 1;
}
if (m_Update_config)
{
LoadCheckBaseConfig(m_pRunConfig.str_RunJson, m_CheckBaseConfig);
m_Update_config = false;
}
// detimg = DetImgInfo_shareP->img(pdetConfig->cropROI);
if (DetImgInfo_shareP->bdebugSaveImg)
{
bwriteImg = true;
@ -178,114 +182,6 @@ int Chip_Detect::InitModel()
return 0;
}
int Chip_Detect::Thread_Run(const cv::Mat &img)
{
cv::Size windowSize(512, 512); // 每个区域大小
cv::Size stride(450, 450); // 步长(小于区域大小就是重叠)
cv::Mat img_gray;
if (img.channels() != 1)
{
cv::cvtColor(img, img_gray, cv::COLOR_BGR2GRAY);
}
else
{
img_gray = img;
}
cv::Mat blurred;
cv::GaussianBlur(img_gray, blurred, cv::Size(21, 21), 5.5);
cv::Mat showimg = blurred.clone();
cv::Mat maskimg = cv::Mat::zeros(img.size(), CV_8U);
for (int y = 0; y < img.rows; y += stride.height)
{
for (int x = 0; x < img.cols; x += stride.width)
{
int width = std::min(windowSize.width, img.cols - x);
int height = std::min(windowSize.height, img.rows - y);
cv::Rect roi(x, y, width, height);
cv::rectangle(showimg, roi, cv::Scalar(255, 0, 50));
cv::Mat patch = blurred(roi);
double meanVal = cv::mean(patch)[0];
cv::Mat mean, stddev;
cv::meanStdDev(patch, mean, stddev);
double sd = stddev.at<double>(0, 0);
double lowerThresh = m_CheckBaseConfig->det_ratio_min * meanVal;
double upperThresh = m_CheckBaseConfig->det_ratio_max * meanVal;
// 创建二值图
cv::Mat maskLow, maskHigh, resultMask;
// 低于下限
cv::threshold(patch, maskLow, lowerThresh, 255, cv::THRESH_BINARY_INV);
// 高于上限
cv::threshold(patch, maskHigh, upperThresh, 255, cv::THRESH_BINARY);
// 合并两个条件:低或高
cv::bitwise_or(maskLow, maskHigh, resultMask);
resultMask.copyTo(maskimg(roi), resultMask);
}
}
cv::Mat m_element;
m_element = getStructuringElement(cv::MORPH_RECT, cv::Size(17, 17));
cv::Mat m12322;
// 增加闭运算
cv::morphologyEx(maskimg, m12322, cv::MORPH_CLOSE, m_element);
GetBlob(m12322);
for (int i = 0; i < m_blob.blobCount; i++)
{
BlobResult tem;
cv::Rect roi;
roi.x = m_blob.blobTab[i].minx;
roi.y = m_blob.blobTab[i].miny;
roi.width = m_blob.blobTab[i].maxx - m_blob.blobTab[i].minx + 1;
roi.height = m_blob.blobTab[i].maxy - m_blob.blobTab[i].miny + 1;
tem.roi = roi;
cv::Point pCenter;
pCenter.x = roi.x + roi.width * 0.5;
pCenter.y = roi.y + roi.height * 0.5;
double result = cv::pointPolygonTest(m_CheckBaseConfig->pointArry, pCenter, false);
if (result < 0)
{
printf("Not in region \n");
continue;
}
CheckUtil::printROI(roi, "roi");
CheckUtil::printROI(tem.roi, "tem.roi ");
tem.area_piexl = m_blob.blobTab[i].area;
tem.hj = m_blob.blobTab[i].grayDis;
tem.type = m_blob.blobTab[i].UserErrorType;
tem.area_mm2 = m_blob.blobTab[i].area * m_CheckBaseConfig->imageScaleParam.fScale_X * m_CheckBaseConfig->imageScaleParam.fScale_Y;
if (tem.area_mm2 > m_CheckBaseConfig->qxSegParam.Area)
{
tem.nresult = 1;
m_CheckResult_shareP->nresult = 1;
}
printf("tem.nresult %d = %f %f \n", tem.nresult, tem.area_mm2, m_CheckBaseConfig->qxSegParam.Area);
m_resultList.push_back(tem);
}
// cv::imwrite("feeee.png", showimg);
// cv::imwrite("feeeemask.png", maskimg);
// cv::imwrite("feeeemask123.png", m12322);
return 0;
}
int Chip_Detect::Draw(const cv::Mat &img, cv::Mat &resultimg)
{
if (img.channels() == 1)
@ -639,123 +535,84 @@ int Chip_Detect::ImgAlinRotate(const cv::Mat &img, cv::Mat &alignImg)
int Chip_Detect::DetectImg(const cv::Mat &img)
{
printf("AI_Run>>>>>>>>>>> start \n");
cv::Mat ColorImg;
if (img.channels() == 1)
{
cv::cvtColor(img, ColorImg, cv::COLOR_GRAY2BGR);
}
else
auto basecheckconfig = m_CheckBaseConfig->baseCheckFunction.detconfig;
// 区域1
std::vector<cv::Rect> smallRoiList1;
int re = CutChipDetRoi(img, basecheckconfig.chipDetConfig1.rect, smallRoiList1);
if (re != 0)
{
ColorImg = img;
std::cout << "CutChipDetRoi region1 fail \n";
return re;
}
int re = 0;
cv::Mat AlignImg = img;
printf("start --- seg \n");
cv::Mat detSrcMask = cv::Mat(AlignImg.rows, AlignImg.cols, CV_8U, cv::Scalar(0));
ROI2ROI_SCALE SegImgToSrcImg;
// 2、分割
for (int i = 0; i < m_AIModelConfigList->AIModelConfigList.size(); i++)
if (smallRoiList1.size() != CHIP_SIZE / 2)
{
AI_Model_Param *p = &m_AIModelConfigList->AIModelConfigList.at(i);
// 分割类型
if (p->type != AI_Model_Type_Seg)
{
continue;
}
long t1, t2, t3;
t1 = CheckUtil::getcurTime();
cv::Size sz;
sz.width = p->in_img.width;
sz.height = p->in_img.height;
cv::Mat temimg;
cv::resize(AlignImg, temimg, sz);
SegImgToSrcImg.setResize(AlignImg, temimg);
if (bwriteImg)
{
std::string str = p->strAIModelName + "_cut_AI_in.png";
cv::imwrite(str, temimg);
std::cout << "CutChipDetRoi region1 size error size=" << smallRoiList1.size() << "\n";
return 1;
}
cv::Mat SegmaskImg;
int re = p->pdetect->run(temimg, SegmaskImg, false);
// 区域2
std::vector<cv::Rect> smallRoiList2;
re = CutChipDetRoi(img, basecheckconfig.chipDetConfig2.rect, smallRoiList2);
if (re != 0)
{
printf("AI_Run seg run fail \n");
std::cout << "CutChipDetRoi region2 fail \n";
return re;
}
SegmaskImg *= 255;
if (bwriteImg)
{
std::string str = p->strAIModelName + "_cut_AI_out_.png";
cv::imwrite(str, SegmaskImg);
}
cv::Size srcsz;
srcsz.width = AlignImg.cols;
srcsz.height = AlignImg.rows;
cv::Mat temmask;
cv::resize(SegmaskImg, detSrcMask, srcsz);
if (bwriteImg)
if (smallRoiList2.size() != CHIP_SIZE / 2)
{
std::string str = p->strAIModelName + "_detSrcMask_res.png";
cv::imwrite(str, detSrcMask);
}
break;
std::cout << "CutChipDetRoi region2 size error size=" << smallRoiList2.size() << "\n";
return 1;
}
printf("End --- seg \n");
if (detSrcMask.empty())
// 转换为原图rec
for (auto &r : smallRoiList1)
{
printf("Seg is Error exit \n");
return 1;
r.x += basecheckconfig.chipDetConfig1.rect.x;
r.y += basecheckconfig.chipDetConfig1.rect.y;
}
m_resultImg = AlignImg;
for (auto &r : smallRoiList2)
{
// 定义腐蚀操作的内核
cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
cv::erode(detSrcMask, detSrcMask, kernel);
r.x += basecheckconfig.chipDetConfig2.rect.x;
r.y += basecheckconfig.chipDetConfig2.rect.y;
}
// 合并两个list
smallRoiList1.insert(smallRoiList1.end(), smallRoiList2.begin(), smallRoiList2.end());
std::vector<cv::Vec4i> hierarchy;
std::vector<std::vector<cv::Point>> contours; // 0929-add
cv::findContours(detSrcMask, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
if (contours.size() != CHIP_SIZE)
if (bwriteImg)
{
std::cout << "contours size != " << CHIP_SIZE << ", actual size: " << contours.size() << std::endl;
return 1;
}
std::vector<cv::Rect> boundRect;
for (const auto &contour : contours)
auto test = img.clone();
for (auto &r : smallRoiList1)
{
boundRect.emplace_back(cv::boundingRect(contour));
cv::rectangle(test, r, cv::Scalar(0, 255, 0), 1);
}
if (boundRect.empty())
{
std::cout << "boundRect is empty\n";
return 1;
cv::imwrite("tesssss.png", test); // 0929-add
}
// 按从上到下、从左到右排序
std::sort(boundRect.begin(), boundRect.end(), [](const cv::Rect &a, const cv::Rect &b) -> bool
// 排序
std::sort(smallRoiList1.begin(), smallRoiList1.end(), [&](const cv::Rect &a, const cv::Rect &b) -> bool
{
int rowTolerance = 50;
// 如果在同一行y坐标相近
if (abs(a.y - b.y) <= rowTolerance)
{
return a.x < b.x; // 从左到右
// CAMERA_Feeding从左到右, CAMERA_Blanking从右到左
return m_pRunConfig.flag0 == CAMERA_Feeding ? a.x < b.x : a.x > b.x;
}
// 否则从下到上排序
return a.y > b.y; });
//初始化存图
if (img.channels() == 1)
{
cv::cvtColor(img, m_CheckResult_shareP->resultImg, cv::COLOR_GRAY2BGR);
}
else
{
m_CheckResult_shareP->resultImg = img.clone();
}
int j = 0;
auto showimg = AlignImg.clone();
for (const auto &rect : boundRect)
for (const auto &rect : smallRoiList1)
{
auto smallImg = AlignImg(rect);
auto smallImg = img(rect);
cv::Mat gray;
if (smallImg.channels() == 3)
{
@ -772,29 +629,227 @@ int Chip_Detect::DetectImg(const cv::Mat &img)
int totalPixels = binaryImg.rows * binaryImg.cols;
double nonZeroRatio = static_cast<double>(nonZeroCount) / totalPixels;
int res = 0;
if (nonZeroRatio >= 0.1)
if (nonZeroRatio >= basecheckconfig.chipThr)
{
res = 1;
}
m_CheckResult_shareP->chipDataList.emplace_back(res);
auto ts = CheckUtil::getcurTime();
// 绘制
// if (bwriteImg)
{
if (bwriteImg)
{
std::string chipBinaryImgName = "chip_binary_" + std::to_string(j) + ".png";
cv::imwrite(chipBinaryImgName, binaryImg); // 0929-add
cv::rectangle(showimg, rect, cv::Scalar(0, 255, 0), 1);
cv::putText(showimg, std::to_string(j), cv::Point(rect.x + rect.width / 2, rect.y + rect.height / 2), cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar(255, 0, 0), 1);
cv::putText(showimg, std::to_string(res) + "::" + std::to_string(nonZeroRatio), cv::Point(rect.x + rect.width / 2 - 50, rect.y + rect.height / 2 + 30), cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar(0, 0, 255), 1);
}
cv::rectangle(m_CheckResult_shareP->resultImg, rect, cv::Scalar(0, 255, 0), 1);
cv::putText(m_CheckResult_shareP->resultImg, std::to_string(j), cv::Point(rect.x + rect.width / 2, rect.y + rect.height / 2), cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar(255, 0, 0), 1);
cv::putText(m_CheckResult_shareP->resultImg, std::to_string(res) + "::" + std::to_string(nonZeroRatio), cv::Point(rect.x + rect.width / 2 - 50, rect.y + rect.height / 2 + 30), cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar(0, 0, 255), 1);
j++;
}
}
printf("AI_Run>>>>>>>>>>> End \n");
return 0;
}
int Chip_Detect::CutChipDetRoi(const cv::Mat &img, cv::Rect &Roi, std::vector<cv::Rect> &smallRoiList)
{
if (!CheckUtil::RoiInImg(Roi, img))
{
std::cout << "CutChipDetRoi --- crop roi is invalid\n";
return 1;
}
auto detimg1 = img(Roi);
cv::Rect cutRoi;
cutRoi.x = 0;
cutRoi.y = 0;
cutRoi.width = detimg1.cols - 0;
cutRoi.height = detimg1.rows - 0;
auto basecheckconfig = m_CheckBaseConfig->baseCheckFunction.detconfig;
int re = CheckUtil::cutSmallImg(detimg1, smallRoiList, cutRoi, basecheckconfig.chipDetConfig1.detWidth, basecheckconfig.chipDetConfig1.detHeight, 0, 0);
if (re != 0)
{
return re;
}
if (smallRoiList.size() <= 0)
{
std::cout << "CutChipDetRoi --- smallRoiList <= 0\n";
return 1;
}
if (bwriteImg)
{
cv::imwrite("chip_res.png", showimg); // 0929-add
auto test = detimg1.clone();
for (auto &r : smallRoiList)
{
cv::rectangle(test, r, cv::Scalar(0, 255, 0), 1);
}
cv::imwrite("chip_detect_cutroi.png", test); // 0929-add
}
printf("AI_Run>>>>>>>>>>> End \n");
return 0;
}
// int Chip_Detect::DetectImg(const cv::Mat &img)
// {
// printf("AI_Run>>>>>>>>>>> start \n");
// cv::Mat ColorImg;
// if (img.channels() == 1)
// {
// cv::cvtColor(img, ColorImg, cv::COLOR_GRAY2BGR);
// }
// else
// {
// ColorImg = img;
// }
// int re = 0;
// cv::Mat AlignImg = img;
// printf("start --- seg \n");
// cv::Mat detSrcMask = cv::Mat(AlignImg.rows, AlignImg.cols, CV_8U, cv::Scalar(0));
// ROI2ROI_SCALE SegImgToSrcImg;
// // 2、分割
// for (int i = 0; i < m_AIModelConfigList->AIModelConfigList.size(); i++)
// {
// AI_Model_Param *p = &m_AIModelConfigList->AIModelConfigList.at(i);
// // 分割类型
// if (p->type != AI_Model_Type_Seg)
// {
// continue;
// }
// long t1, t2, t3;
// t1 = CheckUtil::getcurTime();
// cv::Size sz;
// sz.width = p->in_img.width;
// sz.height = p->in_img.height;
// cv::Mat temimg;
// cv::resize(AlignImg, temimg, sz);
// SegImgToSrcImg.setResize(AlignImg, temimg);
// if (bwriteImg)
// {
// std::string str = p->strAIModelName + "_cut_AI_in.png";
// cv::imwrite(str, temimg);
// }
// cv::Mat SegmaskImg;
// int re = p->pdetect->run(temimg, SegmaskImg, false);
// if (re != 0)
// {
// printf("AI_Run seg run fail \n");
// return re;
// }
// SegmaskImg *= 255;
// if (bwriteImg)
// {
// std::string str = p->strAIModelName + "_cut_AI_out_.png";
// cv::imwrite(str, SegmaskImg);
// }
// cv::Size srcsz;
// srcsz.width = AlignImg.cols;
// srcsz.height = AlignImg.rows;
// cv::Mat temmask;
// cv::resize(SegmaskImg, detSrcMask, srcsz);
// if (bwriteImg)
// {
// std::string str = p->strAIModelName + "_detSrcMask_res.png";
// cv::imwrite(str, detSrcMask);
// }
// break;
// }
// printf("End --- seg \n");
// if (detSrcMask.empty())
// {
// printf("Seg is Error exit \n");
// return 1;
// }
// m_resultImg = AlignImg;
// {
// // 定义腐蚀操作的内核
// cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
// cv::erode(detSrcMask, detSrcMask, kernel);
// }
// std::vector<cv::Vec4i> hierarchy;
// std::vector<std::vector<cv::Point>> contours; // 0929-add
// cv::findContours(detSrcMask, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
// if (contours.size() != CHIP_SIZE)
// {
// std::cout << "contours size != " << CHIP_SIZE << ", actual size: " << contours.size() << std::endl;
// return 1;
// }
// std::vector<cv::Rect> boundRect;
// for (const auto &contour : contours)
// {
// boundRect.emplace_back(cv::boundingRect(contour));
// }
// if (boundRect.empty())
// {
// std::cout << "boundRect is empty\n";
// return 1;
// }
// // 按从上到下、从左到右排序
// std::sort(boundRect.begin(), boundRect.end(), [](const cv::Rect &a, const cv::Rect &b) -> bool
// {
// int rowTolerance = 50;
// // 如果在同一行y坐标相近
// if (abs(a.y - b.y) <= rowTolerance)
// {
// return a.x < b.x; // 从左到右
// }
// // 否则从下到上排序
// return a.y > b.y; });
// int j = 0;
// auto showimg = AlignImg.clone();
// for (const auto &rect : boundRect)
// {
// auto smallImg = AlignImg(rect);
// cv::Mat gray;
// if (smallImg.channels() == 3)
// {
// cv::cvtColor(smallImg, gray, cv::COLOR_BGR2GRAY);
// }
// else
// {
// gray = smallImg.clone();
// }
// cv::Mat binaryImg;
// // cv::threshold(gray, binaryImg, 0, 255, cv::THRESH_BINARY_INV | cv::THRESH_OTSU);
// cv::threshold(gray, binaryImg, 128, 255, cv::THRESH_BINARY_INV);
// int nonZeroCount = cv::countNonZero(binaryImg);
// int totalPixels = binaryImg.rows * binaryImg.cols;
// double nonZeroRatio = static_cast<double>(nonZeroCount) / totalPixels;
// int res = 0;
// if (nonZeroRatio >= 0.1)
// {
// res = 1;
// }
// m_CheckResult_shareP->chipDataList.emplace_back(res);
// // 绘制
// if (bwriteImg)
// {
// std::string chipBinaryImgName = "chip_binary_" + std::to_string(j) + ".png";
// cv::imwrite(chipBinaryImgName, binaryImg); // 0929-add
// cv::rectangle(showimg, rect, cv::Scalar(0, 255, 0), 1);
// cv::putText(showimg, std::to_string(j), cv::Point(rect.x + rect.width / 2, rect.y + rect.height / 2), cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar(255, 0, 0), 1);
// cv::putText(showimg, std::to_string(res) + "::" + std::to_string(nonZeroRatio), cv::Point(rect.x + rect.width / 2 - 50, rect.y + rect.height / 2 + 30), cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar(0, 0, 255), 1);
// j++;
// }
// }
// if (bwriteImg)
// {
// cv::imwrite("chip_res.png", showimg); // 0929-add
// }
// printf("AI_Run>>>>>>>>>>> End \n");
// return 0;
// }

@ -146,6 +146,14 @@ int CheckUtil::printROI(cv::Rect roi, std::string str)
bool CheckUtil::RoiInImg(cv::Rect roi, cv::Mat img)
{
if (img.empty())
return false;
// 检查 ROI 是否有效
if (roi.width <= 0 || roi.height <= 0)
{
return false;
}
if ((roi & cv::Rect(0, 0, img.cols, img.rows)) == roi)
{
return true;

Loading…
Cancel
Save