|
|
|
|
@ -101,7 +101,7 @@ int ALLImgCheckAnalysisy::RunStart(void *pconfig1)
|
|
|
|
|
{
|
|
|
|
|
if (item.second)
|
|
|
|
|
{
|
|
|
|
|
item.second->SetTplInfo(m_tplOuterRect, m_tplPinContours);
|
|
|
|
|
item.second->SetTplInfo(m_tplOuterRect, m_tplInnerRect, m_tplPinContours);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
m_nErrorCode = CHECK_OK;
|
|
|
|
|
@ -172,7 +172,7 @@ int ALLImgCheckAnalysisy::UpdateConfig(void *pconfig, int nConfigType)
|
|
|
|
|
{
|
|
|
|
|
if (item.second)
|
|
|
|
|
{
|
|
|
|
|
item.second->SetTplInfo(m_tplOuterRect, m_tplPinContours);
|
|
|
|
|
item.second->SetTplInfo(m_tplOuterRect, m_tplInnerRect, m_tplPinContours);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -249,7 +249,7 @@ int ALLImgCheckAnalysisy::InitAIFactory()
|
|
|
|
|
int ALLImgCheckAnalysisy::InitTemplateMask()
|
|
|
|
|
{
|
|
|
|
|
std::shared_ptr<AIFactory> AI_Factory = AIFactory::GetInstance();
|
|
|
|
|
if (!AI_Factory || !AI_Factory->Align_Outer || !AI_Factory->Pin_Loc)
|
|
|
|
|
if (!AI_Factory || !AI_Factory->Align_Outer || !AI_Factory->Align_Inner || !AI_Factory->Pin_Loc)
|
|
|
|
|
{
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
@ -322,6 +322,78 @@ int ALLImgCheckAnalysisy::InitTemplateMask()
|
|
|
|
|
}
|
|
|
|
|
tplOuterRect = cv::minAreaRect(srcContour);
|
|
|
|
|
|
|
|
|
|
// 模板内边缘矩形,通过模型Align_Inner得到
|
|
|
|
|
// 与 AI_Edge_Algin::Detect 的内定位流程保持一致:按外接矩形裁剪模板图 -> Align_Inner 推理 -> 轮廓还原并把裁剪偏移加回,得到模板图坐标系下的内边缘矩形
|
|
|
|
|
// PIN 偏移/缺失检测的仿射变换以内定位为基准,模板侧需先准备好该矩形;计算失败时保持空值,运行时自动回退外定位
|
|
|
|
|
cv::RotatedRect tplInnerRect;
|
|
|
|
|
bool bTplInnerOk = false;
|
|
|
|
|
std::shared_ptr<AIModel_Base> pSocket_AlignInner = AI_Factory->Align_Inner;
|
|
|
|
|
cv::Rect tplOuterBound = tplOuterRect.boundingRect() & cv::Rect(0, 0, tplImg.cols, tplImg.rows);
|
|
|
|
|
if (pSocket_AlignInner && tplOuterBound.width > 0 && tplOuterBound.height > 0)
|
|
|
|
|
{
|
|
|
|
|
cv::Mat innerCropImg = tplImg(tplOuterBound).clone();
|
|
|
|
|
cv::Size innerSz;
|
|
|
|
|
innerSz.width = pSocket_AlignInner->input_0.width;
|
|
|
|
|
innerSz.height = pSocket_AlignInner->input_0.height;
|
|
|
|
|
cv::Mat innerDetImg;
|
|
|
|
|
cv::resize(innerCropImg, innerDetImg, innerSz);
|
|
|
|
|
if (innerDetImg.channels() != 1)
|
|
|
|
|
{
|
|
|
|
|
// 与运行时 AI_Edge_Algin::Get_Edge 内定位的灰度化保持一致(BGR 顺序)
|
|
|
|
|
cv::cvtColor(innerDetImg, innerDetImg, cv::COLOR_BGR2GRAY);
|
|
|
|
|
}
|
|
|
|
|
cv::Mat innerMask;
|
|
|
|
|
int reInner = pSocket_AlignInner->AIDet(innerDetImg, innerMask);
|
|
|
|
|
if (reInner != 0)
|
|
|
|
|
{
|
|
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_1, "Init Tpl", "AICheck_Inner----error %d ", reInner);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// 找到最大轮廓
|
|
|
|
|
bool innerFound = false;
|
|
|
|
|
std::vector<cv::Point> innerBoundingBox = CheckUtil::getLargestContourROI(innerMask, innerFound);
|
|
|
|
|
if (!innerFound || innerBoundingBox.size() < 3)
|
|
|
|
|
{
|
|
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_1, "Init Tpl", "Inner align: No contours found!----error ");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// 内定位小图 到 裁剪图 的缩放比例
|
|
|
|
|
const float inner_scale_x = static_cast<float>(innerCropImg.cols) / innerSz.width;
|
|
|
|
|
const float inner_scale_y = static_cast<float>(innerCropImg.rows) / innerSz.height;
|
|
|
|
|
std::vector<cv::Point2f> innerContour;
|
|
|
|
|
innerContour.reserve(innerBoundingBox.size());
|
|
|
|
|
for (const auto &pt : innerBoundingBox)
|
|
|
|
|
{
|
|
|
|
|
innerContour.emplace_back(pt.x * inner_scale_x, pt.y * inner_scale_y);
|
|
|
|
|
}
|
|
|
|
|
tplInnerRect = cv::minAreaRect(innerContour);
|
|
|
|
|
// 裁剪图坐标 -> 模板图坐标(与 AI_Edge_Algin::Detect 中 smallroi 偏移加回一致)
|
|
|
|
|
tplInnerRect.center.x += static_cast<float>(tplOuterBound.x);
|
|
|
|
|
tplInnerRect.center.y += static_cast<float>(tplOuterBound.y);
|
|
|
|
|
bTplInnerOk = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_1, "Init Tpl", "Inner align: model null or outer bound invalid!----error ");
|
|
|
|
|
}
|
|
|
|
|
if (bTplInnerOk)
|
|
|
|
|
{
|
|
|
|
|
m_tplInnerRect = tplInnerRect;
|
|
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_1, "Init Tpl",
|
|
|
|
|
"tplInnerRect center(%.1f %.1f) size(%.1f %.1f) angle %.1f",
|
|
|
|
|
tplInnerRect.center.x, tplInnerRect.center.y,
|
|
|
|
|
tplInnerRect.size.width, tplInnerRect.size.height, tplInnerRect.angle);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
m_tplInnerRect = cv::RotatedRect();
|
|
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_1, "Init Tpl", "Tpl Inner align invalid, runtime fallback to Outer align!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 模板Pinmask,通过模型Pin_Loc得到
|
|
|
|
|
Mat tplPinMask; // 模板mask
|
|
|
|
|
std::shared_ptr<AIModel_Base> pSocket_Pin;
|
|
|
|
|
|