feat 添加手把缺失检测

main
liusiyang 2 weeks ago
parent 55eb4e571d
commit dc2ff1c8ec

@ -55,6 +55,9 @@ public:
std::vector<cv::RotatedRect> bigroi; // 轮廓面积从大到小排序
std::vector<cv::RotatedRect> smallroi; // 轮廓面积从大到小排序
std::vector<cv::RotatedRect> tagroi; // 轮廓面积从大到小排序
cv::Mat bigmask; // 大轮廓掩码
cv::Mat smallmask; // 小轮廓掩码
cv::Mat tagmask; // 标记掩码
bool buseOfft;
int offt_x;
int offt_y;
@ -75,6 +78,9 @@ public:
bigroi.clear();
smallroi.clear();
tagroi.clear();
bigmask.release();
smallmask.release();
tagmask.release();
markresulList.clear();
if (!H.empty())
{
@ -154,7 +160,7 @@ public:
private:
int InitModel_Big();
int Get_Edge(int AIModel_type, const cv::Mat &img, DetConfig *pDetConfig, std::string strChannel, std::vector<cv::RotatedRect> &RoiList);
int Get_Edge(int AIModel_type, const cv::Mat &img, DetConfig *pDetConfig, std::string strChannel, std::vector<cv::RotatedRect> &RoiList, Mat &outmask);
int creatsavedir();

@ -237,8 +237,11 @@ int AI_Edge_Algin::Detect(const cv::Mat &img, DetConfig *pDetConfig, std::shared
std::vector<cv::RotatedRect> Big_roi;
std::vector<cv::RotatedRect> Small_roi;
std::vector<cv::RotatedRect> Tag_roi;
cv::Mat Big_outimg;
cv::Mat Small_outimg;
cv::Mat Tag_outimg;
re = Get_Edge(0, img, pDetConfig, m_pDetConfig->strChannel, Big_roi);
re = Get_Edge(0, img, pDetConfig, m_pDetConfig->strChannel, Big_roi, Big_outimg);
if (re != 0)
{
m_pdetlog->AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "AI_Edge_Algin ", "AICheck_Edge_Big----error %d ", re);
@ -248,7 +251,7 @@ int AI_Edge_Algin::Detect(const cv::Mat &img, DetConfig *pDetConfig, std::shared
}
return re;
}
re = Get_Edge(1, img, pDetConfig, m_pDetConfig->strChannel, Small_roi);
re = Get_Edge(1, img, pDetConfig, m_pDetConfig->strChannel, Small_roi, Small_outimg);
if (re != 0)
{
m_pdetlog->AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "AI_Edge_Algin ", "AICheck_Edge_Small----error %d ", re);
@ -258,7 +261,7 @@ 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);
re = Get_Edge(2, img, pDetConfig, m_pDetConfig->strChannel, Tag_roi, Tag_outimg);
if (re != 0)
{
m_pdetlog->AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "AI_Edge_Algin ", "AICheck_Tag----error %d ", re);
@ -272,9 +275,11 @@ int AI_Edge_Algin::Detect(const cv::Mat &img, DetConfig *pDetConfig, std::shared
m_pCheckResult_Aling->bigroi = Big_roi;
m_pCheckResult_Aling->smallroi = Small_roi;
m_pCheckResult_Aling->tagroi = Tag_roi;
m_pCheckResult_Aling->bigmask = Big_outimg;
m_pCheckResult_Aling->smallmask = Small_outimg;
m_pCheckResult_Aling->tagmask = Tag_outimg;
pCheckResult_Aling = m_pCheckResult_Aling;
// return 1;
return 0;
}
@ -343,7 +348,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, std::vector<cv::RotatedRect> &RoiList)
int AI_Edge_Algin::Get_Edge(int AIModel_type, const cv::Mat &img, DetConfig *pDetConfig, std::string strChannel, std::vector<cv::RotatedRect> &RoiList, Mat &outmask)
{
std::shared_ptr<AIModel_Base> pBackPlate_Align;
switch (AIModel_type)
@ -403,11 +408,13 @@ int AI_Edge_Algin::Get_Edge(int AIModel_type, const cv::Mat &img, DetConfig *pDe
}
}
// if (m_pDetConfig->bSaveResultImg)
if (m_pDetConfig->bSaveResultImg)
{
cv::imwrite(strChannel +"_edge_"+ to_string(AIModel_type) +"_in.png", detImg);
cv::imwrite(strChannel +"_edge_"+ to_string(AIModel_type) +"_out_mask.png", mask);
}
// resize out_mask并返回
cv::resize(mask, outmask, img.size());
// 检查模型输入尺寸
if (sz.width <= 0 || sz.height <= 0)

@ -348,7 +348,7 @@ int ALLImgCheckAnalysisy::InitTemplateMask()
m_pdetlog->AddCheckstr(PrintLevel_1, DET_LOG_LEVEL_1, "---Init Tpl---" , "start");
// 模板图路径,暂时使用固定路径
string tplImgPath = "/home/aidlux/BOE/ZB_PLATE/Tpl/tpl.bmp"; // 模板图片路径
string tplImgPath = "/home/aidlux/BOE/ZB_BACKPLATE/Tpl/tpl.bmp"; // 模板图片路径
Mat tplImg = imread(tplImgPath, IMREAD_UNCHANGED);
if (tplImg.empty())
{

@ -11,6 +11,7 @@
#include "Define.h"
#include <omp.h>
#include "AICommonDefine.h"
#include <algorithm>
// 用于排序轮廓的比较函数
static bool compareContourAreas(const vector<Point> &contour1, const vector<Point> &contour2)
{
@ -2025,6 +2026,8 @@ int ImgCheckAnalysisy::AI_Edge(const cv::Mat &img, cv::RotatedRect &outerRoi, cv
}
config.strChannel = DetImgInfo_shareP->strChannel;
config.pBaseCheckFunction = m_pbaseCheckFunction;
/* 定位获取三个roi */
int re = m_pAI_Edge_Algin.Detect(img, &config, m_pEdge_Align_Result);
if (re != 0)
{
@ -2042,7 +2045,92 @@ int ImgCheckAnalysisy::AI_Edge(const cv::Mat &img, cv::RotatedRect &outerRoi, cv
{
tagroiList = m_pEdge_Align_Result->tagroi;
}
// getchar();
/*使用m_pEdge_Align_Result->bigmask检测把手是否缺失*/
// 截取把手大致区域
RotatedRect tpl_handle_rroi = m_pbaseCheckFunction->supportDet.handleRect;
Rect handle_rect = Rect(tpl_handle_rroi.boundingRect().x, 0, tpl_handle_rroi.boundingRect().width, m_pEdge_Align_Result->bigmask.rows);
Mat handle_roi = m_pEdge_Align_Result->bigmask(handle_rect & Rect(0, 0, m_pEdge_Align_Result->bigmask.cols, m_pEdge_Align_Result->bigmask.rows)).clone();
// 对handle_roi做一下开运算
Mat element = getStructuringElement(MORPH_RECT, Size(tpl_handle_rroi.boundingRect().width / 3, tpl_handle_rroi.boundingRect().height / 3));
morphologyEx(handle_roi, handle_roi, MORPH_OPEN, element);
// imwrite("handle_roi.png", handle_roi);
// handle_roi找到最大连通域和tpl_handle_rroi做面积形状比较差异过大判为把手缺失添加到缺陷并NG
{
Base_Function_Support_Det &handleDet = m_pbaseCheckFunction->supportDet;
if (handleDet.bOpen && tpl_handle_rroi.size.width > 0 && tpl_handle_rroi.size.height > 0 && !handle_roi.empty())
{
std::vector<std::vector<cv::Point>> handle_contours;
cv::findContours(handle_roi, handle_contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
bool bHandleLoss = false;
if (handle_contours.empty())
{
bHandleLoss = true; // 没有连通域,把手完全缺失
}
else
{
// 取最大连通域
std::sort(handle_contours.begin(), handle_contours.end(), compareContourAreas);
cv::RotatedRect cur_handle_rrect = cv::minAreaRect(handle_contours[0]);
double curArea = cv::contourArea(handle_contours[0]);
// 面积比较
double tplArea = tpl_handle_rroi.size.width * tpl_handle_rroi.size.height;
double areaRatio = (tplArea > 0.0) ? (curArea / tplArea) : 0.0;
// 形状比较(长宽比)
float tplW = std::max(tpl_handle_rroi.size.width, tpl_handle_rroi.size.height);
float tplH = std::min(tpl_handle_rroi.size.width, tpl_handle_rroi.size.height);
float curW = std::max(cur_handle_rrect.size.width, cur_handle_rrect.size.height);
float curH = std::min(cur_handle_rrect.size.width, cur_handle_rrect.size.height);
float tplRatio = (tplH > 0.0f) ? (tplW / tplH) : 0.0f;
float curRatio = (curH > 0.0f) ? (curW / curH) : 0.0f;
float ratioDiff = (tplRatio > 0.0f) ? fabs(curRatio - tplRatio) / tplRatio : 0.0f;
// 面积差异过大 或 形状差异过大 判为把手缺失
if (areaRatio < 0.6f || ratioDiff > 0.6f)
{
bHandleLoss = true;
}
m_pdetlog->AddCheckstr(PrintLevel_0, "把手检测", "areaRatio %f ratioDiff %f", areaRatio, ratioDiff);
}
if (bHandleLoss)
{
QX_ERROR_INFO_ temerror;
temerror.Idx = m_pDetResult->pQx_ErrorList->size();
// 把手模板 roi 在原图坐标系,转换为检测图(detImg)坐标系
cv::Rect roi = tpl_handle_rroi.boundingRect();
roi.x -= outerRoi.boundingRect().x;
roi.y -= outerRoi.boundingRect().y;
roi &= cv::Rect(0, 0, outerRoi.boundingRect().width, outerRoi.boundingRect().height);
temerror.roi = roi;
temerror.area = roi.width * roi.height;
temerror.JudgArea = roi.width * m_fImgage_Scale_X * roi.height * m_fImgage_Scale_Y;
temerror.JudgArea_second = temerror.JudgArea;
float w = tpl_handle_rroi.size.width;
float h = tpl_handle_rroi.size.height;
temerror.flen = (w > h ? w : h) * m_fImgage_Scale_X;
temerror.fbreadth = (w > h ? h : w) * m_fImgage_Scale_Y;
temerror.nconfig_qx_type = CONFIG_QX_NAME_support_loss;
temerror.qx_name = CONFIG_QX_NAME_Names[temerror.nconfig_qx_type];
temerror.result = QX_RESULT_TYPE_NG;
temerror.result_name = QX_RESULT_TYPE_Names[QX_RESULT_TYPE_NG];
temerror.detRegionidxList.push_back(0);
m_pDetResult->pQx_ErrorList->push_back(temerror);
m_pdetlog->AddCheckstr(PrintLevel_0, "把手检测", "handle loss NG roi [%d %d %d %d]", roi.x, roi.y, roi.width, roi.height);
}
}
}
return re;
}

@ -19,7 +19,7 @@ message(STATUS "oPENCV Library status:")
message(STATUS ">version:${OpenCV_VERSION}")
message(STATUS "Include:${OpenCV_INCLUDE_DIRS}")
set(CMAKE_BUILD_TYPE "debug")
set(CMAKE_BUILD_TYPE "release")
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON) # C++17
set(CMAKE_CXX_EXTENSIONS OFF) # GNU

@ -1306,11 +1306,13 @@ struct Base_Function_Edge_Det
struct Base_Function_Support_Det
{
bool bOpen; // 是否开启
std::vector<cv::Point> region;
std::vector<cv::Point> supportRegion;
cv::RotatedRect supportRect;
float x_offset;
float y_offset;
float r_offset;
std::vector<cv::Point> handleRegion;
cv::RotatedRect handleRect;
Base_Function_Support_Det()
{
@ -1320,21 +1322,24 @@ struct Base_Function_Support_Det
void Init()
{
bOpen = false;
region.clear();
region.erase(region.begin(), region.end());
supportRegion.clear();
supportRect = cv::RotatedRect();
x_offset = 0;
y_offset = 0;
r_offset = 0;
handleRegion.clear();
handleRect = cv::RotatedRect();
}
void copy(Base_Function_Support_Det tem)
{
this->bOpen = tem.bOpen;
this->region.assign(tem.region.begin(), tem.region.end());
this->supportRegion.assign(tem.supportRegion.begin(), tem.supportRegion.end());
this->supportRect = tem.supportRect;
this->x_offset = tem.x_offset;
this->y_offset = tem.y_offset;
this->r_offset = tem.r_offset;
this->handleRegion.assign(tem.handleRegion.begin(), tem.handleRegion.end());
this->handleRect = tem.handleRect;
}
void print(std::string str)
{
@ -1370,6 +1375,7 @@ struct BaseCheckFunction
edgeDet.Init();
saveImg.Init();
bigNG.Init();
supportDet.Init();
}
void copy(BaseCheckFunction tem)
{
@ -1377,6 +1383,7 @@ struct BaseCheckFunction
this->edgeDet.copy(tem.edgeDet);
this->saveImg.copy(tem.saveImg);
this->bigNG.copy(tem.bigNG);
this->supportDet.copy(tem.supportDet);
}
void print(std::string str)
{
@ -1385,6 +1392,7 @@ struct BaseCheckFunction
edgeDet.print("edgeDet");
saveImg.print("saveImg");
bigNG.print("bigNG");
supportDet.print("supportDet");
}
std::string GetInfo(std::string str)
{
@ -1393,6 +1401,7 @@ struct BaseCheckFunction
str123 += edgeDet.GetInfo("edgeDet");
str123 += saveImg.GetInfo("saveImg");
str123 += bigNG.GetInfo("bigNG");
str123 += supportDet.GetInfo("supportDet");
// str123 += "\n";
return str123;
}

@ -857,7 +857,7 @@ int BaseFuntonConfigJson::GetFunction(Json::Value value)
_config.supportDet.bOpen = value_f["isOpen"].asBool();
if (_config.supportDet.bOpen)
{
// 支架参数
{
auto value_region = value_f["form"]["support_param"]["support_region"];
if (value_region.isArray())
@ -868,11 +868,11 @@ int BaseFuntonConfigJson::GetFunction(Json::Value value)
p.x = value_region[idx][0].asInt();
p.y = value_region[idx][1].asInt();
_config.supportDet.region.emplace_back(p);
_config.supportDet.supportRegion.emplace_back(p);
}
if (_config.supportDet.region.size() > 0)
if (_config.supportDet.supportRegion.size() > 0)
{
_config.supportDet.supportRect = minAreaRect(_config.supportDet.region);
_config.supportDet.supportRect = minAreaRect(_config.supportDet.supportRegion);
}
}
}
@ -888,6 +888,26 @@ int BaseFuntonConfigJson::GetFunction(Json::Value value)
{
_config.supportDet.r_offset = value_f["form"]["support_param"]["r_offset"].asFloat();
}
// 把手参数
{
auto value_region = value_f["form"]["handle_param"]["handle_region"];
if (value_region.isArray())
{
for (int idx = 0; idx < value_region.size(); idx++)
{
cv::Point p;
p.x = value_region[idx][0].asInt();
p.y = value_region[idx][1].asInt();
_config.supportDet.handleRegion.emplace_back(p);
}
if (_config.supportDet.handleRegion.size() > 0)
{
_config.supportDet.handleRect = minAreaRect(_config.supportDet.handleRegion);
}
}
}
}
else
{

@ -459,7 +459,7 @@ int deal::preCheck()
std::shared_ptr<CheckResult> checkResult;
int re = m_pALLImgCheckAnalysisy->GetCheckReuslt(checkResult);
saveImg("/home/aidlux/BOE/ZB_PLATE/testresult/", checkResult);
saveImg("/home/aidlux/BOE/ZB_BACKPLATE/testresult/", checkResult);
getresultNum++;
if (getresultNum >= m_nPushImgCount)
{
@ -805,14 +805,14 @@ void deal::ResultThread(int id)
// 存图
// std::string savepath = "/home/aidlux/BOE/Detsave/" + runConfig.filePath + "/";
// saveImg(savepath, dealResult);
saveImg("/home/aidlux/BOE/ZB_PLATE/Detsave/", dealResult);
saveImg("/home/aidlux/BOE/ZB_BACKPLATE/Detsave/", dealResult);
}
{
// 存 检测统计 日志
mutex_DetResult_.lock();
m_DetResult.print(false);
std::string strlog = "/home/aidlux/BOE/ZB_PLATE/ResultImg/";
std::string strlog = "/home/aidlux/BOE/ZB_BACKPLATE/ResultImg/";
if (m_strCurDate != "")
{
strlog += m_strCurDate;

Loading…
Cancel
Save