|
|
|
|
@ -15,6 +15,7 @@
|
|
|
|
|
#include <opencv2/opencv.hpp> // OpenCV核心功能
|
|
|
|
|
#include <opencv2/imgproc.hpp> // 图像处理模块
|
|
|
|
|
#include <vector> // 向量容器
|
|
|
|
|
#include <algorithm> // std::sort
|
|
|
|
|
#include <iostream> // 输入输出流
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@ -233,8 +234,9 @@ int AI_Edge_Algin::Detect(const cv::Mat &img, DetConfig *pDetConfig, std::shared
|
|
|
|
|
// 1、初步定位 找到产品大致区域
|
|
|
|
|
int re = 0;
|
|
|
|
|
|
|
|
|
|
cv::RotatedRect Big_roi;
|
|
|
|
|
cv::RotatedRect Small_roi;
|
|
|
|
|
std::vector<cv::RotatedRect> Big_roi;
|
|
|
|
|
std::vector<cv::RotatedRect> Small_roi;
|
|
|
|
|
std::vector<cv::RotatedRect> Tag_roi;
|
|
|
|
|
|
|
|
|
|
re = Get_Edge(0, img, pDetConfig, m_pDetConfig->strChannel, Big_roi);
|
|
|
|
|
if (re != 0)
|
|
|
|
|
@ -256,9 +258,20 @@ int AI_Edge_Algin::Detect(const cv::Mat &img, DetConfig *pDetConfig, std::shared
|
|
|
|
|
}
|
|
|
|
|
return re;
|
|
|
|
|
}
|
|
|
|
|
re = Get_Edge(2, img, pDetConfig, m_pDetConfig->strChannel, Tag_roi);
|
|
|
|
|
if (re != 0)
|
|
|
|
|
{
|
|
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "AI_Edge_Algin ", "AICheck_Tag----error %d ", re);
|
|
|
|
|
if (m_pDetConfig->IsSaveProcessImg())
|
|
|
|
|
{
|
|
|
|
|
cv::imwrite(str_error, img);
|
|
|
|
|
}
|
|
|
|
|
return re;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_pCheckResult_Aling->bigroi = Big_roi;
|
|
|
|
|
m_pCheckResult_Aling->smallroi = Small_roi;
|
|
|
|
|
m_pCheckResult_Aling->tagroi = Tag_roi;
|
|
|
|
|
|
|
|
|
|
pCheckResult_Aling = m_pCheckResult_Aling;
|
|
|
|
|
// return 1;
|
|
|
|
|
@ -330,7 +343,7 @@ int AI_Edge_Algin::InitModel_ALL()
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int AI_Edge_Algin::Get_Edge(int AIModel_type, const cv::Mat &img, DetConfig *pDetConfig, std::string strChannel, cv::RotatedRect &Roi)
|
|
|
|
|
int AI_Edge_Algin::Get_Edge(int AIModel_type, const cv::Mat &img, DetConfig *pDetConfig, std::string strChannel, std::vector<cv::RotatedRect> &RoiList)
|
|
|
|
|
{
|
|
|
|
|
std::shared_ptr<AIModel_Base> pBackPlate_Align;
|
|
|
|
|
switch (AIModel_type)
|
|
|
|
|
@ -341,6 +354,9 @@ int AI_Edge_Algin::Get_Edge(int AIModel_type, const cv::Mat &img, DetConfig *pDe
|
|
|
|
|
case 1:
|
|
|
|
|
pBackPlate_Align = AI_Factory->Align_Inner;
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
pBackPlate_Align = AI_Factory->Tag_Loc;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
pBackPlate_Align = AI_Factory->Align_Outer;
|
|
|
|
|
break;
|
|
|
|
|
@ -393,42 +409,73 @@ int AI_Edge_Algin::Get_Edge(int AIModel_type, const cv::Mat &img, DetConfig *pDe
|
|
|
|
|
cv::imwrite(strChannel +"_edge_"+ to_string(AIModel_type) +"_out_mask.png", mask);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 找到最大轮廓
|
|
|
|
|
bool found;
|
|
|
|
|
std::vector<cv::Point> boundingBox = CheckUtil::getLargestContourROI(mask, found);
|
|
|
|
|
if (!found)
|
|
|
|
|
{
|
|
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AI_Edge_Algin ", "No contours found!----error ");
|
|
|
|
|
return 4;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 边缘轮廓点集还原为原图坐标,并计算得到RotateROI
|
|
|
|
|
// 检查模型输入尺寸
|
|
|
|
|
if (sz.width <= 0 || sz.height <= 0)
|
|
|
|
|
{
|
|
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AI_Edge_Algin ", "invalid model input size!----error ");
|
|
|
|
|
return 5;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 找到所有轮廓
|
|
|
|
|
std::vector<std::vector<cv::Point>> contours;
|
|
|
|
|
std::vector<cv::Vec4i> hierarchy;
|
|
|
|
|
cv::findContours(mask.clone(), contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
|
|
|
|
|
if (contours.empty())
|
|
|
|
|
{
|
|
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AI_Edge_Algin ", "No contours found!----error ");
|
|
|
|
|
return 4;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 检测小图 到 原图 的缩放比例
|
|
|
|
|
const float scale_x = static_cast<float>(img.cols) / sz.width;
|
|
|
|
|
const float scale_y = static_cast<float>(img.rows) / sz.height;
|
|
|
|
|
|
|
|
|
|
// 轮廓点还原到原图坐标系
|
|
|
|
|
std::vector<cv::Point2f> srcContour;
|
|
|
|
|
srcContour.reserve(boundingBox.size());
|
|
|
|
|
for (const auto &pt : boundingBox)
|
|
|
|
|
RoiList.clear();
|
|
|
|
|
|
|
|
|
|
// 按轮廓面积从大到小排序(记录面积与轮廓索引)
|
|
|
|
|
std::vector<std::pair<double, size_t>> areaIdx;
|
|
|
|
|
areaIdx.reserve(contours.size());
|
|
|
|
|
for (size_t i = 0; i < contours.size(); i++)
|
|
|
|
|
{
|
|
|
|
|
double area = cv::contourArea(contours[i]);
|
|
|
|
|
if (area > 0)
|
|
|
|
|
{
|
|
|
|
|
areaIdx.emplace_back(area, i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (areaIdx.empty())
|
|
|
|
|
{
|
|
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AI_Edge_Algin ", "No valid contours found!----error ");
|
|
|
|
|
return 4;
|
|
|
|
|
}
|
|
|
|
|
std::sort(areaIdx.begin(), areaIdx.end(),
|
|
|
|
|
[](const std::pair<double, size_t> &a, const std::pair<double, size_t> &b)
|
|
|
|
|
{ return a.first > b.first; });
|
|
|
|
|
|
|
|
|
|
// 按面积从大到小,将每个轮廓点还原到原图坐标系并计算 RotatedRect
|
|
|
|
|
RoiList.reserve(areaIdx.size());
|
|
|
|
|
for (const auto &ai : areaIdx)
|
|
|
|
|
{
|
|
|
|
|
srcContour.emplace_back(pt.x * scale_x, pt.y * scale_y);
|
|
|
|
|
const std::vector<cv::Point> &contour = contours[ai.second];
|
|
|
|
|
if (contour.size() < 3)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
std::vector<cv::Point2f> srcContour;
|
|
|
|
|
srcContour.reserve(contour.size());
|
|
|
|
|
for (const auto &pt : contour)
|
|
|
|
|
{
|
|
|
|
|
srcContour.emplace_back(pt.x * scale_x, pt.y * scale_y);
|
|
|
|
|
}
|
|
|
|
|
RoiList.emplace_back(cv::minAreaRect(srcContour));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (srcContour.size() < 3)
|
|
|
|
|
if (RoiList.empty())
|
|
|
|
|
{
|
|
|
|
|
m_pdetlog->AddCheckstr(PrintLevel_3, DET_LOG_LEVEL_3, "AI_Edge_Algin ", "contour points too few!----error ");
|
|
|
|
|
return 6;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Roi = cv::minAreaRect(srcContour);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|