|
|
|
|
@ -1897,37 +1897,40 @@ int ImgCheckAnalysisy::Pin_Qx_Det(const cv::Mat &img)
|
|
|
|
|
|
|
|
|
|
if (nTpl > 0)
|
|
|
|
|
{
|
|
|
|
|
// 1、统计模板 pin 中心与平均最小边长,用于自适应阈值
|
|
|
|
|
// 1、统计模板 pin 中心与外包矩形
|
|
|
|
|
std::vector<cv::Point2f> tplCenters(nTpl);
|
|
|
|
|
double sumMinDim = 0.0;
|
|
|
|
|
std::vector<cv::Rect> tplRects(nTpl);
|
|
|
|
|
for (int i = 0; i < nTpl; i++)
|
|
|
|
|
{
|
|
|
|
|
tplCenters[i] = getCenter(m_tplPinContours[i]);
|
|
|
|
|
cv::Rect r = cv::boundingRect(m_tplPinContours[i]);
|
|
|
|
|
sumMinDim += (r.width < r.height) ? r.width : r.height;
|
|
|
|
|
tplRects[i] = cv::boundingRect(m_tplPinContours[i]);
|
|
|
|
|
}
|
|
|
|
|
const float avgMinDim = static_cast<float>(sumMinDim / nTpl);
|
|
|
|
|
|
|
|
|
|
// 偏移阈值约 1/4 个 pin 尺寸,缺失阈值约 3/4 个 pin 尺寸
|
|
|
|
|
float offsetTh = avgMinDim * 0.5f;
|
|
|
|
|
if (offsetTh < 3.0f)
|
|
|
|
|
{
|
|
|
|
|
offsetTh = 3.0f;
|
|
|
|
|
}
|
|
|
|
|
float missTh = avgMinDim * 0.75f;
|
|
|
|
|
if (missTh < offsetTh + 1.0f)
|
|
|
|
|
{
|
|
|
|
|
missTh = offsetTh + 1.0f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2、当前 pin 中心
|
|
|
|
|
// 2、当前 pin 中心与外包矩形
|
|
|
|
|
std::vector<cv::Point2f> curCenters(nCur);
|
|
|
|
|
std::vector<cv::Rect> curRects(nCur);
|
|
|
|
|
for (int i = 0; i < nCur; i++)
|
|
|
|
|
{
|
|
|
|
|
curCenters[i] = getCenter(m_curPinContours[i]);
|
|
|
|
|
curRects[i] = cv::boundingRect(m_curPinContours[i]);
|
|
|
|
|
}
|
|
|
|
|
std::vector<bool> curUsed(nCur, false);
|
|
|
|
|
|
|
|
|
|
// 3、偏移阈值由基础参数 pin_x_offset / pin_y_offset (mm) 换算为像素
|
|
|
|
|
float offsetThX = 0.0f;
|
|
|
|
|
float offsetThY = 0.0f;
|
|
|
|
|
if (m_pbaseCheckFunction != NULL)
|
|
|
|
|
{
|
|
|
|
|
if (m_fImgage_Scale_X > 0.0f)
|
|
|
|
|
{
|
|
|
|
|
offsetThX = m_pbaseCheckFunction->pinDet.pin_x_offset / m_fImgage_Scale_X;
|
|
|
|
|
}
|
|
|
|
|
if (m_fImgage_Scale_Y > 0.0f)
|
|
|
|
|
{
|
|
|
|
|
offsetThY = m_pbaseCheckFunction->pinDet.pin_y_offset / m_fImgage_Scale_Y;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 上报缺失/偏移缺陷(缺陷类型可按需调整)
|
|
|
|
|
auto reportPinError = [&](int pinIdx, const cv::Point2f &tplCenter, const std::string &reason)
|
|
|
|
|
{
|
|
|
|
|
@ -1954,7 +1957,7 @@ int ImgCheckAnalysisy::Pin_Qx_Det(const cv::Mat &img)
|
|
|
|
|
int nMiss = 0;
|
|
|
|
|
int nOffset = 0;
|
|
|
|
|
|
|
|
|
|
// 3、逐个模板 pin 找最近且未被占用的当前 pin
|
|
|
|
|
// 4、逐个模板 pin 找与其相交且未被占用的当前 pin
|
|
|
|
|
for (int i = 0; i < nTpl; i++)
|
|
|
|
|
{
|
|
|
|
|
int bestIdx = -1;
|
|
|
|
|
@ -1965,6 +1968,14 @@ int ImgCheckAnalysisy::Pin_Qx_Det(const cv::Mat &img)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 完全与模板没有相交 -> 不算候选
|
|
|
|
|
cv::Rect inter = tplRects[i] & curRects[j];
|
|
|
|
|
if (inter.width <= 0 || inter.height <= 0)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float dx = tplCenters[i].x - curCenters[j].x;
|
|
|
|
|
float dy = tplCenters[i].y - curCenters[j].y;
|
|
|
|
|
double d = std::sqrt(static_cast<double>(dx) * dx + static_cast<double>(dy) * dy);
|
|
|
|
|
@ -1975,8 +1986,8 @@ int ImgCheckAnalysisy::Pin_Qx_Det(const cv::Mat &img)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 无候选或距离过远 -> 缺失
|
|
|
|
|
if (bestIdx < 0 || bestDist > missTh)
|
|
|
|
|
// 没有相交的当前 pin -> 缺失
|
|
|
|
|
if (bestIdx < 0)
|
|
|
|
|
{
|
|
|
|
|
nMiss++;
|
|
|
|
|
reportPinError(i, tplCenters[i], "miss");
|
|
|
|
|
@ -1986,14 +1997,18 @@ int ImgCheckAnalysisy::Pin_Qx_Det(const cv::Mat &img)
|
|
|
|
|
|
|
|
|
|
curUsed[bestIdx] = true;
|
|
|
|
|
|
|
|
|
|
// 距离超出偏移阈值 -> 偏移
|
|
|
|
|
if (bestDist > offsetTh)
|
|
|
|
|
// x 或 y 方向偏移超过配置阈值 -> 偏移
|
|
|
|
|
float dx = tplCenters[i].x - curCenters[bestIdx].x;
|
|
|
|
|
float dy = tplCenters[i].y - curCenters[bestIdx].y;
|
|
|
|
|
float absDx = std::fabs(dx);
|
|
|
|
|
float absDy = std::fabs(dy);
|
|
|
|
|
if (absDx > offsetThX || absDy > offsetThY)
|
|
|
|
|
{
|
|
|
|
|
nOffset++;
|
|
|
|
|
char buf[64];
|
|
|
|
|
snprintf(buf, sizeof(buf), "offset %.1fpx", bestDist);
|
|
|
|
|
snprintf(buf, sizeof(buf), "offset dx %.1f dy %.1f", absDx, absDy);
|
|
|
|
|
reportPinError(i, tplCenters[i], buf);
|
|
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_0, "Pin Check", "pin %d OFFSET %.1fpx", i, bestDist);
|
|
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_0, "Pin Check", "pin %d OFFSET dx %.1f dy %.1f", i, absDx, absDy);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|