|
|
|
@ -23,6 +23,11 @@ static const float PIN_SHIFT_BIN_SIZE_PX = 4.0f; // 位移投票的网格
|
|
|
|
static const float PIN_SHIFT_MAX_GAP_RATIO = 0.8f; // 整体位移量级上限 = 相邻pin最小间距 * 该比例
|
|
|
|
static const float PIN_SHIFT_MAX_GAP_RATIO = 0.8f; // 整体位移量级上限 = 相邻pin最小间距 * 该比例
|
|
|
|
// ======================================================================================
|
|
|
|
// ======================================================================================
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ===================== 图像模糊度(清晰度)检测参数 =====================
|
|
|
|
|
|
|
|
// 计算清晰度前把检测图最长边缩放到该尺寸(只缩小不放大), 使阈值与图像分辨率无关
|
|
|
|
|
|
|
|
static const int BLUR_CHECK_MAX_SIZE = 1000;
|
|
|
|
|
|
|
|
// ======================================================================
|
|
|
|
|
|
|
|
|
|
|
|
// 计算点相对旋转矩形“长边轴线”的带符号法向距离(检测图坐标系):
|
|
|
|
// 计算点相对旋转矩形“长边轴线”的带符号法向距离(检测图坐标系):
|
|
|
|
// 取矩形长边方向作为 Pin 排方向, 返回点沿短边(法线)方向相对矩形中心的投影;
|
|
|
|
// 取矩形长边方向作为 Pin 排方向, 返回点沿短边(法线)方向相对矩形中心的投影;
|
|
|
|
// 正负号天然把分布在矩形两侧的 Pin 分成两组(上下两排分别估计整体偏移)。
|
|
|
|
// 正负号天然把分布在矩形两侧的 Pin 分成两组(上下两排分别估计整体偏移)。
|
|
|
|
@ -804,6 +809,98 @@ int ImgCheckAnalysisy::TransformTplPinContoursToCur()
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 图像模糊度(清晰度)检测: 必须在 AI 检测之前执行。
|
|
|
|
|
|
|
|
// 1) 检测图 detImg 转灰度(本身就是单通道, 这里做兼容);
|
|
|
|
|
|
|
|
// 2) 最长边缩放到 BLUR_CHECK_MAX_SIZE(只缩小不放大), 保证阈值与图像分辨率无关;
|
|
|
|
|
|
|
|
// 3) 用拉普拉斯算子(CV_64F)响应的方差作为清晰度指标: 方差越小越模糊;
|
|
|
|
|
|
|
|
// 4) 方差 < 阈值(基础参数 blurDet.fThreshold, 对应界面参数 blur_threshold) -> 判为模糊图片,
|
|
|
|
|
|
|
|
// 参数 blurDet.bNG(界面 bNG)打开时直接判 NG。
|
|
|
|
|
|
|
|
// 返回: 1 图像模糊且需要判 NG; 0 正常 / 功能未开启 / 图像无效
|
|
|
|
|
|
|
|
int ImgCheckAnalysisy::BlurCheck(const cv::Mat &img)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (m_pbaseCheckFunction == NULL || !m_pbaseCheckFunction->blurDet.bOpen ||
|
|
|
|
|
|
|
|
m_pbaseCheckFunction->blurDet.fThreshold <= 0.0f)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 每帧重置模糊判定结果
|
|
|
|
|
|
|
|
if (m_pDetResult)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
m_pDetResult->bBlurNG = false;
|
|
|
|
|
|
|
|
m_pDetResult->fBlurScore = 0.0f;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (img.empty() || img.cols < 5 || img.rows < 5)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Blur Check", "input img invalid, skip");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 1、转灰度(detImg 为单通道, 其他通道情况做兼容)
|
|
|
|
|
|
|
|
cv::Mat grayImg;
|
|
|
|
|
|
|
|
if (1 == img.channels())
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
grayImg = img;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (3 == img.channels())
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
cv::cvtColor(img, grayImg, cv::COLOR_BGR2GRAY);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (4 == img.channels())
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
cv::cvtColor(img, grayImg, cv::COLOR_BGRA2GRAY);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_3, "Blur Check", "unsupported channels %d, skip", img.channels());
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 2、按最长边缩放(只缩小不放大)
|
|
|
|
|
|
|
|
cv::Mat checkImg = grayImg;
|
|
|
|
|
|
|
|
const int nMaxSide = std::max(grayImg.cols, grayImg.rows);
|
|
|
|
|
|
|
|
if (nMaxSide > BLUR_CHECK_MAX_SIZE)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
const double fScale = static_cast<double>(BLUR_CHECK_MAX_SIZE) / static_cast<double>(nMaxSide);
|
|
|
|
|
|
|
|
cv::resize(grayImg, checkImg, cv::Size(), fScale, fScale, cv::INTER_AREA);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 3、拉普拉斯方差(越大越清晰)
|
|
|
|
|
|
|
|
cv::Mat lapImg;
|
|
|
|
|
|
|
|
cv::Laplacian(checkImg, lapImg, CV_64F, 3);
|
|
|
|
|
|
|
|
cv::Scalar meanVal;
|
|
|
|
|
|
|
|
cv::Scalar stdVal;
|
|
|
|
|
|
|
|
cv::meanStdDev(lapImg, meanVal, stdVal);
|
|
|
|
|
|
|
|
const float fScore = static_cast<float>(stdVal[0] * stdVal[0]);
|
|
|
|
|
|
|
|
const float fThreshold = m_pbaseCheckFunction->blurDet.fThreshold;
|
|
|
|
|
|
|
|
const bool bNGOpen = m_pbaseCheckFunction->blurDet.bNG;
|
|
|
|
|
|
|
|
const bool bBlur = (fScore < fThreshold);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (m_pDetResult)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
m_pDetResult->fBlurScore = fScore;
|
|
|
|
|
|
|
|
m_pDetResult->bBlurNG = (bBlur && bNGOpen);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_0, "Blur Check",
|
|
|
|
|
|
|
|
"variance %.2f %s threshold %.2f -> %s (bNG %d, img [%d %d] -> check [%d %d])",
|
|
|
|
|
|
|
|
fScore, bBlur ? "<" : ">=", fThreshold, bBlur ? "BLUR" : "OK",
|
|
|
|
|
|
|
|
static_cast<int>(bNGOpen),
|
|
|
|
|
|
|
|
grayImg.cols, grayImg.rows, checkImg.cols, checkImg.rows);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (bBlur && bNGOpen)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_0, "Blur Check", "image blurred -> judge NG");
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bBlur)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_0, "Blur Check", "image blurred, but bNG is off -> not NG");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int ImgCheckAnalysisy::CheckRun()
|
|
|
|
int ImgCheckAnalysisy::CheckRun()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
@ -1064,6 +1161,15 @@ int ImgCheckAnalysisy::CheckRun()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
m_pImageAllResult->detImg = image(m_outer_roi).clone();
|
|
|
|
m_pImageAllResult->detImg = image(m_outer_roi).clone();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*图像模糊度(清晰度)检测: 必须在 AI 检测之前完成, 模糊图片直接判 NG*/
|
|
|
|
|
|
|
|
long time_blur_s = CheckUtil::getcurTime();
|
|
|
|
|
|
|
|
const bool bBlurNG = (BlurCheck(m_pImageAllResult->detImg) == 1);
|
|
|
|
|
|
|
|
long time_blur_e = CheckUtil::getcurTime();
|
|
|
|
|
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_0, "2.2、pre detect",
|
|
|
|
|
|
|
|
"-------------------------Blur Check------------%s---time %ld----\n",
|
|
|
|
|
|
|
|
bBlurNG ? "NG" : "OK", time_blur_e - time_blur_s);
|
|
|
|
|
|
|
|
|
|
|
|
/*多线程开启 AI 推理检测*/
|
|
|
|
/*多线程开启 AI 推理检测*/
|
|
|
|
long time_AI_s = CheckUtil::getcurTime();
|
|
|
|
long time_AI_s = CheckUtil::getcurTime();
|
|
|
|
m_AItask = std::make_shared<TaskInfo>();
|
|
|
|
m_AItask = std::make_shared<TaskInfo>();
|
|
|
|
@ -1086,6 +1192,12 @@ int ImgCheckAnalysisy::CheckRun()
|
|
|
|
|
|
|
|
|
|
|
|
m_CheckResult_shareP->nresult = 0;
|
|
|
|
m_CheckResult_shareP->nresult = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 图像模糊: 在 AI 检测之前已判定, 直接判 NG(nresult=1 与区域参数判断出的 NG 语义一致)
|
|
|
|
|
|
|
|
if (bBlurNG)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
m_CheckResult_shareP->nresult = 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*把临时可以绘制的结果都绘制出来。*/
|
|
|
|
/*把临时可以绘制的结果都绘制出来。*/
|
|
|
|
DrawResult_Step_1();
|
|
|
|
DrawResult_Step_1();
|
|
|
|
long time_AI_e;
|
|
|
|
long time_AI_e;
|
|
|
|
|