|
|
|
@ -0,0 +1,800 @@
|
|
|
|
|
|
|
|
#include "Chip_Detect.hpp"
|
|
|
|
|
|
|
|
#include "CheckErrorCode.hpp"
|
|
|
|
|
|
|
|
#include "CheckUtil.hpp"
|
|
|
|
|
|
|
|
#include "DetCommonDefine.hpp"
|
|
|
|
|
|
|
|
using namespace cv;
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
// 检测模型 单个小图 输入模型图片尺寸
|
|
|
|
|
|
|
|
#define SRC_CUT_IMAGE_WIDTH 512
|
|
|
|
|
|
|
|
#define SRC_CUT_IMAGE_HEIGHT 512
|
|
|
|
|
|
|
|
#define CHIP_SIZE 140
|
|
|
|
|
|
|
|
// std::shared_ptr<ImgCheckBase> ImgCheckBase::GetInstance()
|
|
|
|
|
|
|
|
// {
|
|
|
|
|
|
|
|
// return std::shared_ptr<ImgCheckBase>(new Chip_Detect());
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Chip_Detect::Chip_Detect()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
bwriteImg = false;
|
|
|
|
|
|
|
|
m_Update_config = false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Chip_Detect::~Chip_Detect()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
printf("----------------~Chip_Detect \n");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
// {
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int Chip_Detect::CheckImg(std::shared_ptr<shareImage> p, std::shared_ptr<CheckResult> &pResult)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
DetImgInfo_shareP = p;
|
|
|
|
|
|
|
|
// printf("%d DetImgInfo_shareP count %ld \n", m_RunConfig.nThreadIdx, DetImgInfo_shareP.use_count());
|
|
|
|
|
|
|
|
int re = CheckRun();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pResult = m_CheckResult_shareP;
|
|
|
|
|
|
|
|
m_CheckResult_shareP.reset();
|
|
|
|
|
|
|
|
DetImgInfo_shareP.reset();
|
|
|
|
|
|
|
|
if (!m_resultImg.empty())
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
m_resultImg.release();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return re;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int Chip_Detect::UpdateConfig(void *pconfig, int nConfigType)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
m_Update_config = true;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int Chip_Detect::CheckRun()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
printf("CheckRun start \n");
|
|
|
|
|
|
|
|
long t1, t2;
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
if (DetImgInfo_shareP->bdebugSaveImg)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
bwriteImg = true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 芯片检测
|
|
|
|
|
|
|
|
int re = 0;
|
|
|
|
|
|
|
|
re = DetectImg(detimg);
|
|
|
|
|
|
|
|
if (0 != re)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// 失败NG
|
|
|
|
|
|
|
|
m_CheckResult_shareP->nresult = 1;
|
|
|
|
|
|
|
|
return re;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
t2 = CheckUtil::getcurTime();
|
|
|
|
|
|
|
|
m_CheckResult_shareP->UseTimeMS = t2 - t1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
printf("Check time %ld \n", t2 - t1);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int Chip_Detect::CheckImgInit()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
m_CheckResult_shareP = std::make_shared<CheckResult>();
|
|
|
|
|
|
|
|
m_nErrorCode = CHECK_OK;
|
|
|
|
|
|
|
|
memset(&m_blob, 0, sizeof(ERROR_DOTS_BLOBS));
|
|
|
|
|
|
|
|
m_resultList.erase(m_resultList.begin(), m_resultList.end());
|
|
|
|
|
|
|
|
m_resultList.clear();
|
|
|
|
|
|
|
|
m_AlignMaxRoi = cv::Rect(0, 0, 0, 0);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int Chip_Detect::InitModel()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
printf("InitModel>>>>>>>>>>> start \n");
|
|
|
|
|
|
|
|
int re = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < m_AIModelConfigList->AIModelConfigList.size(); i++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
AI_Model_Param *p = &m_AIModelConfigList->AIModelConfigList.at(i);
|
|
|
|
|
|
|
|
p->pdetect = std::make_shared<DetectModel>();
|
|
|
|
|
|
|
|
std::string str = p->strModelPath;
|
|
|
|
|
|
|
|
AI_ConfigInfo config;
|
|
|
|
|
|
|
|
config.strdetect_model_path = str;
|
|
|
|
|
|
|
|
config.ai_Model_Type = AI_MODEL_TYPE_FLOAT16;
|
|
|
|
|
|
|
|
config.dataArr_In[AI_DATA_IDX_T] = 1;
|
|
|
|
|
|
|
|
config.dataArr_In[AI_DATA_IDX_HEIGHT] = p->in_img.height;
|
|
|
|
|
|
|
|
config.dataArr_In[AI_DATA_IDX_WIDTH] = p->in_img.width;
|
|
|
|
|
|
|
|
config.dataArr_In[AI_DATA_IDX_CHANNELS] = p->in_img.channels;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
config.dataArr_Out[AI_DATA_IDX_T] = 1;
|
|
|
|
|
|
|
|
config.dataArr_Out[AI_DATA_IDX_HEIGHT] = p->out_img.height;
|
|
|
|
|
|
|
|
config.dataArr_Out[AI_DATA_IDX_WIDTH] = p->out_img.width;
|
|
|
|
|
|
|
|
config.dataArr_Out[AI_DATA_IDX_CHANNELS] = p->out_img.channels;
|
|
|
|
|
|
|
|
config.userflag = 1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if (p->type == AI_Model_Type_Reconstruct)
|
|
|
|
|
|
|
|
// {
|
|
|
|
|
|
|
|
// re = p->pdetect->init_reconstruct(config);
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
re = p->pdetect->init(config);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (re != 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
printf("InitModel>>>>>>>>>>> Fail \n");
|
|
|
|
|
|
|
|
return re;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("InitModel>>>>>>>>>>> End \n");
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
cv::cvtColor(img, resultimg, cv::COLOR_GRAY2BGR);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
resultimg = img.clone();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// //裁剪到包括产品(1600x1200)
|
|
|
|
|
|
|
|
// int w = 1600;
|
|
|
|
|
|
|
|
// int h = 1200;
|
|
|
|
|
|
|
|
// cv::Point center{this->m_AlignMaxRoi.x + this->m_AlignMaxRoi.width / 2, this->m_AlignMaxRoi.y + this->m_AlignMaxRoi.height / 2};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// int x = center.x - w / 2;
|
|
|
|
|
|
|
|
// int y = center.y - h / 2;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // 确保裁剪区域不超出图像边界
|
|
|
|
|
|
|
|
// x = std::max(0, x);
|
|
|
|
|
|
|
|
// y = std::max(0, y);
|
|
|
|
|
|
|
|
// x = std::min(x, img.cols - w);
|
|
|
|
|
|
|
|
// y = std::min(y, img.rows - h);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // 创建裁剪区域
|
|
|
|
|
|
|
|
// cv::Rect cropRoi(x, y, w, h);
|
|
|
|
|
|
|
|
// resultimg = resultimg(cropRoi);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// cv::polylines(resultimg, m_CheckBaseConfig->pointArry, true, cv::Scalar(0, 255, 0), 2);
|
|
|
|
|
|
|
|
// auto regions = m_CheckBaseConfig->nodeConfigArr[0].regionConfigArr;
|
|
|
|
|
|
|
|
// for (int i = 0; i < regions.size(); i++)
|
|
|
|
|
|
|
|
// {
|
|
|
|
|
|
|
|
// cv::polylines(resultimg, regions[i].basicInfo.pointArry, true, cv::Scalar(0, 255, 0), 2);
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int fontFace = cv::FONT_HERSHEY_SIMPLEX; // 字体样式
|
|
|
|
|
|
|
|
double fontScale = 1; // 字体大小
|
|
|
|
|
|
|
|
cv::Scalar color_NG(0, 0, 255); // 文本颜色
|
|
|
|
|
|
|
|
cv::Scalar color_OK(0, 255, 0); // 文本颜色
|
|
|
|
|
|
|
|
int thickness = 1; // 文本线条粗细
|
|
|
|
|
|
|
|
for (int i = 0; i < m_resultList.size(); i++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
cv::Scalar color;
|
|
|
|
|
|
|
|
color = color_OK;
|
|
|
|
|
|
|
|
if (m_resultList.at(i).nresult == 0 && m_resultList.at(i).nYsresult == 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (m_resultList.at(i).nresult != 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
color = color_NG;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
color = cv::Scalar(0, 255, 255);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
cv::Rect roi = m_resultList.at(i).roi;
|
|
|
|
|
|
|
|
cv::Point pc;
|
|
|
|
|
|
|
|
pc.x = roi.x + roi.width * 0.5;
|
|
|
|
|
|
|
|
pc.y = roi.y + roi.height * 0.5;
|
|
|
|
|
|
|
|
int rw = roi.width * 0.5;
|
|
|
|
|
|
|
|
int rh = roi.height * 0.5;
|
|
|
|
|
|
|
|
int r = std::sqrt(rw * rw + rh * rh) * 1.1 + 8;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (r < 20)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
r = 20;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
cv::circle(resultimg, pc, r, color);
|
|
|
|
|
|
|
|
char buffer[32];
|
|
|
|
|
|
|
|
sprintf(buffer, " A %.3f HJ %d ", m_resultList.at(i).area_mm2, m_resultList.at(i).hj);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
string show_info = buffer;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cv::Point p;
|
|
|
|
|
|
|
|
p.x = m_resultList.at(i).roi.x;
|
|
|
|
|
|
|
|
p.y = m_resultList.at(i).roi.y;
|
|
|
|
|
|
|
|
cv::putText(resultimg, show_info, p, fontFace, 1, color, 1);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 裁剪
|
|
|
|
|
|
|
|
cv::Size dstSize(RESULT_WIDTH, RESULT_HEIGHT);
|
|
|
|
|
|
|
|
cv::resize(resultimg, resultimg, dstSize);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int Chip_Detect::GetBlob(cv::Mat maskImg)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
unsigned char *pimgdata = (unsigned char *)maskImg.data;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int width = maskImg.cols;
|
|
|
|
|
|
|
|
int height = maskImg.rows;
|
|
|
|
|
|
|
|
if (maskImg.empty())
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
long t1 = CheckUtil::getcurTime();
|
|
|
|
|
|
|
|
GetImg_Blob(&m_blob, pimgdata, width, height);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
printf("blob num %d \n", m_blob.blobCount);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (bwriteImg)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
cv::Mat tm;
|
|
|
|
|
|
|
|
cv::cvtColor(maskImg, tm, cv::COLOR_GRAY2RGB); // 彩色 可选项
|
|
|
|
|
|
|
|
for (int i = 0; i < m_blob.blobCount; i++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cv::rectangle(tm, roi, cv::Scalar(0, 0, 255));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
cv::imwrite("image_resize_blob.png", tm);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// getchar();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
long t2 = CheckUtil::getcurTime();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int Chip_Detect::ImgAlinRotate(const cv::Mat &img, cv::Mat &alignImg)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
cv::Mat ColorImg;
|
|
|
|
|
|
|
|
if (img.channels() == 1)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
cv::cvtColor(img, ColorImg, cv::COLOR_GRAY2BGR);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
ColorImg = img;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
ROI2ROI_SCALE AlignToSrc;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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_Align)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
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(ColorImg, temimg, sz);
|
|
|
|
|
|
|
|
AlignToSrc.setResize(ColorImg, temimg);
|
|
|
|
|
|
|
|
if (bwriteImg)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
std::string str = p->strAIModelName + "_AI_in.png";
|
|
|
|
|
|
|
|
cv::imwrite(str, temimg);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cv::Mat outimg;
|
|
|
|
|
|
|
|
int re = p->pdetect->run(temimg, outimg, false);
|
|
|
|
|
|
|
|
if (re != 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
printf("AI_Run Align run fail \n");
|
|
|
|
|
|
|
|
return re;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bwriteImg)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
std::string str = p->strAIModelName + "_AI_out.png";
|
|
|
|
|
|
|
|
cv::imwrite(str, outimg);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m_AlignMaxRoi = CheckUtil::findMaxBoundingBox(outimg);
|
|
|
|
|
|
|
|
AlignToSrc.UPdateRoi(m_AlignMaxRoi);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CheckUtil::printROI(m_AlignMaxRoi, "maxroi");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
alignImg = ColorImg(m_AlignMaxRoi);
|
|
|
|
|
|
|
|
if (bwriteImg)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
cv::rectangle(ColorImg, m_AlignMaxRoi, cv::Scalar(255, 0, 0));
|
|
|
|
|
|
|
|
std::string str = p->strAIModelName + "_AI_out_res.png";
|
|
|
|
|
|
|
|
cv::imwrite(str, ColorImg);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// printf("AI_Run time %ld \n", t2 - t1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (alignImg.empty())
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
printf("Align is Error exit \n");
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 判断尺寸
|
|
|
|
|
|
|
|
int w = m_CheckBaseConfig->baseCheckFunction.detconfig.chip_width_mm / m_CheckBaseConfig->imageScaleParam.fScale_X;
|
|
|
|
|
|
|
|
int h = m_CheckBaseConfig->baseCheckFunction.detconfig.chip_height_mm / m_CheckBaseConfig->imageScaleParam.fScale_Y;
|
|
|
|
|
|
|
|
auto w_offset = std::abs(w - m_AlignMaxRoi.width);
|
|
|
|
|
|
|
|
auto h_offset = std::abs(h - m_AlignMaxRoi.height);
|
|
|
|
|
|
|
|
int param_w_offset = m_CheckBaseConfig->baseCheckFunction.detconfig.chip_width_offset_mm / m_CheckBaseConfig->imageScaleParam.fScale_X;
|
|
|
|
|
|
|
|
int param_h_offset = m_CheckBaseConfig->baseCheckFunction.detconfig.chip_height_offset_mm / m_CheckBaseConfig->imageScaleParam.fScale_Y;
|
|
|
|
|
|
|
|
if (w_offset > param_w_offset || h_offset > param_h_offset)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
printf("Align error, no product\n");
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// DetRotateType ratio = m_CheckBaseConfig->baseCheckFunction.detconfig.rotate;
|
|
|
|
|
|
|
|
// std::cout << "rotate ratio : " << ratio << std::endl;
|
|
|
|
|
|
|
|
// if (ratio == Ratio_0)
|
|
|
|
|
|
|
|
// {
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// else if (ratio == Ratio_90)
|
|
|
|
|
|
|
|
// {
|
|
|
|
|
|
|
|
// cv::rotate(alignImg, alignImg, cv::ROTATE_90_COUNTERCLOCKWISE);
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// else if (ratio == Ratio_180)
|
|
|
|
|
|
|
|
// {
|
|
|
|
|
|
|
|
// cv::rotate(alignImg, alignImg, cv::ROTATE_180);
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// else if (ratio == Ratio_270)
|
|
|
|
|
|
|
|
// {
|
|
|
|
|
|
|
|
// cv::rotate(alignImg, alignImg, cv::ROTATE_90_CLOCKWISE); // 270° 逆时针 == 90° 顺时针
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 二维码定位处理
|
|
|
|
|
|
|
|
long t12, t13;
|
|
|
|
|
|
|
|
t12 = CheckUtil::getcurTime();
|
|
|
|
|
|
|
|
cv::Mat ColorCodeImg;
|
|
|
|
|
|
|
|
if (alignImg.channels() == 1)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
cv::cvtColor(alignImg, ColorCodeImg, cv::COLOR_GRAY2BGR);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
ColorCodeImg = alignImg;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < m_AIModelConfigList->AIModelConfigList.size(); i++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
AI_Model_Param *p = &m_AIModelConfigList->AIModelConfigList.at(i);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::cout << "p->name=" << p->strAIModelName << std::endl; // 0924-add
|
|
|
|
|
|
|
|
std::cout << "p->strModelPath=" << p->strModelPath << std::endl; // 0924-add
|
|
|
|
|
|
|
|
std::cout << "p->type=" << p->type << std::endl; // 1015-add
|
|
|
|
|
|
|
|
// getchar();//0924-add
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 定位类型
|
|
|
|
|
|
|
|
if (p->type != AI_Model_Type_CodeAlign)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
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 temimg2;
|
|
|
|
|
|
|
|
cv::resize(ColorCodeImg, temimg2, sz);
|
|
|
|
|
|
|
|
AlignToSrc.setResize(ColorCodeImg, temimg2);
|
|
|
|
|
|
|
|
if (bwriteImg)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
std::string str = p->strAIModelName + "_AI_in.png";
|
|
|
|
|
|
|
|
cv::imwrite(str, temimg2);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cv::Mat outimg;
|
|
|
|
|
|
|
|
int re = p->pdetect->run(temimg2, outimg, false);
|
|
|
|
|
|
|
|
if (re != 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
printf("CodeAlign----p->pdetect->run--failed \n");
|
|
|
|
|
|
|
|
return re;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
t2 = CheckUtil::getcurTime();
|
|
|
|
|
|
|
|
std::cout << "1.2 codeLoc model-run-----time cost -----------" << t2 - t1 << "ms" << std::endl;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (bwriteImg)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
std::string str = p->strAIModelName + "_AI_out.png";
|
|
|
|
|
|
|
|
cv::imwrite(str, outimg);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cv::Mat src_mask;
|
|
|
|
|
|
|
|
cv::resize(outimg, src_mask, cv::Size(ColorCodeImg.cols, ColorCodeImg.rows));
|
|
|
|
|
|
|
|
if (bwriteImg)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
std::string str = p->strAIModelName + "_AI_mask.png";
|
|
|
|
|
|
|
|
cv::imwrite(str, src_mask);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 求取二维码位置
|
|
|
|
|
|
|
|
cv::Rect codeLocRoi = CheckUtil::findMaxBoundingBox(outimg); // 直接在输入模型图像上找-更节省时间
|
|
|
|
|
|
|
|
if (codeLocRoi.empty())
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
std::cout << "CodeAlign---no--Product" << std::endl;
|
|
|
|
|
|
|
|
return 6; // 返回6
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (bwriteImg)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
cv::Mat codeLocShowImg;
|
|
|
|
|
|
|
|
if (1 == outimg.channels())
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
cvtColor(outimg, codeLocShowImg, cv::COLOR_GRAY2BGR);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (3 == outimg.channels())
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
codeLocShowImg = outimg.clone();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
cv::rectangle(codeLocShowImg, codeLocRoi, cv::Scalar(0, 0, 255), 2, 8);
|
|
|
|
|
|
|
|
std::string str = p->strAIModelName + "_CodeLocShow.png";
|
|
|
|
|
|
|
|
cv::imwrite(str, codeLocShowImg);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
cv::Point codeCenterPt = CheckUtil::getCenterPoint(codeLocRoi); // CheckUtil::getCenterPoint
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (m_pRunConfig.flag0 == CAMERA_TOP_1)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (codeCenterPt.x < outimg.cols / 2)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// 二维码在左侧则旋转90°逆时针
|
|
|
|
|
|
|
|
cv::rotate(alignImg, alignImg, cv::ROTATE_90_COUNTERCLOCKWISE);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (codeCenterPt.x > outimg.cols / 2)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// 二维码在右侧则旋转90°顺时针
|
|
|
|
|
|
|
|
cv::rotate(alignImg, alignImg, cv::ROTATE_90_CLOCKWISE);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (m_pRunConfig.flag0 == CAMERA_TOP_2)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// 二维码在上方则旋转180°
|
|
|
|
|
|
|
|
if (codeCenterPt.y < outimg.rows / 2)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
cv::rotate(alignImg, alignImg, cv::ROTATE_180);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
}
|