Compare commits

..

6 Commits

@ -64,6 +64,8 @@ public:
cv::Mat detImg; cv::Mat detImg;
// 裁剪后的彩色检测图(保留原图通道,供裁剪图 _RE_CutImg 输出;灰度源图时为空) // 裁剪后的彩色检测图(保留原图通道,供裁剪图 _RE_CutImg 输出;灰度源图时为空)
cv::Mat detColorImg; cv::Mat detColorImg;
// 只做"裁剪"、不叠加任何 mask 的检测图(同 detImg 尺寸/坐标系)
cv::Mat detImgNoMask;
// AI 推理的mask图片 // AI 推理的mask图片
cv::Mat AIMaskImg; cv::Mat AIMaskImg;
// 结果图片 // 结果图片

@ -273,12 +273,24 @@ int AI_Edge_Algin::Detect(const cv::Mat &img, DetConfig *pDetConfig, std::shared
} }
if (re1 != 0) if (re1 != 0)
{ {
m_pdetlog->AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "AI_Edge_Algin ", "AICheck_Edge_Small----error %d ", re1); // Align_Inner(支架)未检出有效轮廓(4=无轮廓 / 6=轮廓点太少):
if (m_pDetConfig->IsSaveProcessImg()) // 支架检测开启时不视为定位失败,继续带 smallmask(可能为空/全零) 返回,
// 由后续"支架缺失"判定(support_min_area)上报 ZJ_QueShi NG
bool bSupportDetOn = (pDetConfig->pBaseCheckFunction != NULL && pDetConfig->pBaseCheckFunction->supportDet.bDetSupport);
if (bSupportDetOn && (re1 == 4 || re1 == 6))
{ {
cv::imwrite(str_error, img); m_pdetlog->AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "AI_Edge_Algin ", "AICheck_Edge_Small no contour(%d), treat as support missing ", re1);
re1 = 0;
}
else
{
m_pdetlog->AddCheckstr(PrintLevel_2, DET_LOG_LEVEL_3, "AI_Edge_Algin ", "AICheck_Edge_Small----error %d ", re1);
if (m_pDetConfig->IsSaveProcessImg())
{
cv::imwrite(str_error, img);
}
return re1;
} }
return re1;
} }
if (re2 != 0) if (re2 != 0)
{ {

File diff suppressed because it is too large Load Diff

@ -924,12 +924,25 @@ struct Function_Support_Det
// 支架参数(Support_Detect) // 支架参数(Support_Detect)
bool bDetSupport; // 支架偏位检测开关(Support_Detect.isOpen) bool bDetSupport; // 支架偏位检测开关(Support_Detect.isOpen)
bool bDrawSupport; // 支架绘制开关(Support_Detect.form.support_param.bDrawSupport):是否绘制支架中心十字/距离线 bool bDrawSupport; // 支架绘制开关(Support_Detect.form.support_param.bDrawSupport):是否绘制支架中心十字/距离线
bool bUseTraditionEdge; // 传统算法搜边开关(Support_Detect.form.support_param.bUseTraditionEdge):
// true=产品边缘用裁剪图(detImg)转灰度、二值化后搜边(不依赖定位模型 bigmask);false=用定位模型 bigmask
float x_standard; // 水平方向标准距离(left/right 用) float x_standard; // 水平方向标准距离(left/right 用)
float y_standard; // 垂直方向标准距离(up/down 用) float y_standard; // 垂直方向标准距离(up/down 用)
std::vector<std::string> edge_select; // 参与计算的方向:up/down/left/right std::vector<std::string> edge_select; // 参与计算的方向:up/down/left/right
float x_offset; float x_offset;
float y_offset; float y_offset;
float r_offset; float r_offset; // 支架旋转偏移阈值(度):支架旋转矩形长轴(对应左/右边缘)与产品左/右边缘夹角超过该值判偏移;<=0 不判定
float support_min_area; // 支架缺失判定:支架面积阈值(单位 mm²)。支架由 Align_Inner 模型(smallmask)检出,支架面积 < 该值判缺失;<=0 不判定
// 支架边缘原图精细化(Support_Detect.form.support_param,均可选;仅对 edge_select 选中的边缘生效):
// 沿边缘按步长采样,从边缘向产品内侧逐像素找第一个灰度 >= 阈值的像素作为新边缘点,再重新拟合边缘线
float edge_refine_search; // edge_refine_search:最多向内搜索的像素数;<=0=未配置(默认 80)
float edge_refine_step; // edge_refine_step:沿边采样步长(像素,不需要每个点都找);<=0=未配置(默认 40)
float edge_refine_gray; // edge_refine_gray:边缘点灰度阈值(0~255,灰度 >= 该值视为产品边缘);<=0=未配置(默认 240)
// 支架方向精细化(Support_Detect.form.support_param,均可选):模型 smallmask 精度低
// (1696×800 上采样回原图),minAreaRect 求支架方向角误差大;改为在原图(detImg)上拟合支架长边求方向角
float support_refine_search; // support_refine_search:取模型支架外接矩形最外侧多少列作为边缘搜索带;<=0=未配置(默认 30)
float support_refine_step; // support_refine_step:沿支架长边采样步长(像素);<=0=未配置(默认 20)
float support_refine_segments; // support_refine_segments:采样点分段数(每段稳健拟合一条线取角度中位数);<=0=未配置(默认 6)
// 把手参数(Handle_Detect) // 把手参数(Handle_Detect)
bool bDetHandle; // 把手缺失检测开关(Handle_Detect.isOpen) bool bDetHandle; // 把手缺失检测开关(Handle_Detect.isOpen)
// 把手区域(最多 HANDLE_REGION_MAX_NUM 个,只保存非空的;区域宽高用于把手卡控) // 把手区域(最多 HANDLE_REGION_MAX_NUM 个,只保存非空的;区域宽高用于把手卡控)
@ -960,12 +973,20 @@ struct Function_Support_Det
{ {
bDetSupport = false; bDetSupport = false;
bDrawSupport = false; bDrawSupport = false;
bUseTraditionEdge = false;
x_standard = 0; x_standard = 0;
y_standard = 0; y_standard = 0;
edge_select.clear(); edge_select.clear();
x_offset = 0; x_offset = 0;
y_offset = 0; y_offset = 0;
r_offset = 0; r_offset = 0;
support_min_area = 0;
edge_refine_search = 0;
edge_refine_step = 0;
edge_refine_gray = 0;
support_refine_search = 0;
support_refine_step = 0;
support_refine_segments = 0;
bDetHandle = false; bDetHandle = false;
handleRegions.clear(); handleRegions.clear();
handleBoxes.clear(); handleBoxes.clear();
@ -987,12 +1008,20 @@ struct Function_Support_Det
{ {
this->bDetSupport = tem.bDetSupport; this->bDetSupport = tem.bDetSupport;
this->bDrawSupport = tem.bDrawSupport; this->bDrawSupport = tem.bDrawSupport;
this->bUseTraditionEdge = tem.bUseTraditionEdge;
this->x_standard = tem.x_standard; this->x_standard = tem.x_standard;
this->y_standard = tem.y_standard; this->y_standard = tem.y_standard;
this->edge_select.assign(tem.edge_select.begin(), tem.edge_select.end()); this->edge_select.assign(tem.edge_select.begin(), tem.edge_select.end());
this->x_offset = tem.x_offset; this->x_offset = tem.x_offset;
this->y_offset = tem.y_offset; this->y_offset = tem.y_offset;
this->r_offset = tem.r_offset; this->r_offset = tem.r_offset;
this->support_min_area = tem.support_min_area;
this->edge_refine_search = tem.edge_refine_search;
this->edge_refine_step = tem.edge_refine_step;
this->edge_refine_gray = tem.edge_refine_gray;
this->support_refine_search = tem.support_refine_search;
this->support_refine_step = tem.support_refine_step;
this->support_refine_segments = tem.support_refine_segments;
this->bDetHandle = tem.bDetHandle; this->bDetHandle = tem.bDetHandle;
this->handleRegions.assign(tem.handleRegions.begin(), tem.handleRegions.end()); this->handleRegions.assign(tem.handleRegions.begin(), tem.handleRegions.end());
this->handleBoxes.assign(tem.handleBoxes.begin(), tem.handleBoxes.end()); this->handleBoxes.assign(tem.handleBoxes.begin(), tem.handleBoxes.end());
@ -1011,16 +1040,16 @@ struct Function_Support_Det
} }
void print(std::string str) void print(std::string str)
{ {
printf("%s>>bDetSupport %d bDrawSupport %d bDetHandle %d bDetTag %d x_standard %f y_standard %f x_offset %f y_offset %f r_offset %f edge num %ld handleRegion num %ld handle_diff %f handleRange[size %.2f~%.2f search %.1f depth %.1f area %.1f margin %.1f(0=自动,<0=默认)] BQ[area %f energy %f len %f hj %f]\n", printf("%s>>bDetSupport %d bDrawSupport %d bUseTraditionEdge %d bDetHandle %d bDetTag %d x_standard %f y_standard %f x_offset %f y_offset %f r_offset %f support_min_area %f edgeRefine[search %.0f step %.0f gray %.0f] supportRefine[search %.0f step %.0f seg %.0f] edge num %ld handleRegion num %ld handle_diff %f handleRange[size %.2f~%.2f search %.1f depth %.1f area %.1f margin %.1f(0=自动,<0=默认)] BQ[area %f energy %f len %f hj %f]\n",
str.c_str(), bDetSupport, bDrawSupport, bDetHandle, bDetTag, x_standard, y_standard, x_offset, y_offset, r_offset, edge_select.size(), handleRegions.size(), handle_diff, str.c_str(), bDetSupport, bDrawSupport, bUseTraditionEdge, bDetHandle, bDetTag, x_standard, y_standard, x_offset, y_offset, r_offset, support_min_area, edge_refine_search, edge_refine_step, edge_refine_gray, support_refine_search, support_refine_step, support_refine_segments, edge_select.size(), handleRegions.size(), handle_diff,
handle_size_min_ratio, handle_size_max_ratio, handle_search_ratio, handle_min_depth_coef, handle_min_area_coef, handle_edge_margin_coef, handle_size_min_ratio, handle_size_max_ratio, handle_search_ratio, handle_min_depth_coef, handle_min_area_coef, handle_edge_margin_coef,
BQ_area, BQ_energy, BQ_len, BQ_hj); BQ_area, BQ_energy, BQ_len, BQ_hj);
} }
std::string GetInfo(std::string str) std::string GetInfo(std::string str)
{ {
char buffer[1024]; char buffer[1024];
sprintf(buffer, "%s>>bDetSupport %d bDrawSupport %d bDetHandle %d bDetTag %d x_standard %f y_standard %f x_offset %f y_offset %f r_offset %f edge num %ld handleRegion num %ld handle_diff %f handleRange[size %.2f~%.2f search %.1f depth %.1f area %.1f margin %.1f(0=自动,<0=默认)] BQ[area %f energy %f len %f hj %f]\n", sprintf(buffer, "%s>>bDetSupport %d bDrawSupport %d bUseTraditionEdge %d bDetHandle %d bDetTag %d x_standard %f y_standard %f x_offset %f y_offset %f r_offset %f support_min_area %f edgeRefine[search %.0f step %.0f gray %.0f] supportRefine[search %.0f step %.0f seg %.0f] edge num %ld handleRegion num %ld handle_diff %f handleRange[size %.2f~%.2f search %.1f depth %.1f area %.1f margin %.1f(0=自动,<0=默认)] BQ[area %f energy %f len %f hj %f]\n",
str.c_str(), bDetSupport, bDrawSupport, bDetHandle, bDetTag, x_standard, y_standard, x_offset, y_offset, r_offset, edge_select.size(), handleRegions.size(), handle_diff, str.c_str(), bDetSupport, bDrawSupport, bUseTraditionEdge, bDetHandle, bDetTag, x_standard, y_standard, x_offset, y_offset, r_offset, support_min_area, edge_refine_search, edge_refine_step, edge_refine_gray, support_refine_search, support_refine_step, support_refine_segments, edge_select.size(), handleRegions.size(), handle_diff,
handle_size_min_ratio, handle_size_max_ratio, handle_search_ratio, handle_min_depth_coef, handle_min_area_coef, handle_edge_margin_coef, handle_size_min_ratio, handle_size_max_ratio, handle_search_ratio, handle_min_depth_coef, handle_min_area_coef, handle_edge_margin_coef,
BQ_area, BQ_energy, BQ_len, BQ_hj); BQ_area, BQ_energy, BQ_len, BQ_hj);
std::string str123 = buffer; std::string str123 = buffer;

@ -930,6 +930,11 @@ int BaseFuntonConfigJson::GetFunction(Json::Value value)
{ {
_config.supportDet.bDrawSupport = value_param["bDrawSupport"].asBool(); _config.supportDet.bDrawSupport = value_param["bDrawSupport"].asBool();
} }
// 传统算法搜边开关
if (value_param["bUseTraditionEdge"].isBool())
{
_config.supportDet.bUseTraditionEdge = value_param["bUseTraditionEdge"].asBool();
}
if (value_param["x_standard"]) if (value_param["x_standard"])
{ {
@ -952,6 +957,46 @@ int BaseFuntonConfigJson::GetFunction(Json::Value value)
_config.supportDet.r_offset = value_param["r_offset"].asFloat(); _config.supportDet.r_offset = value_param["r_offset"].asFloat();
} }
if (value_param["support_min_area"])
{
_config.supportDet.support_min_area = value_param["support_min_area"].asFloat();
}
// 支架边缘原图精细化(可选):沿边缘采样,从边缘向内找第一个灰度 >= 阈值的像素作为新边缘点,
// edge_refine_search:最多向内搜索像素数(未配置默认 80)
// edge_refine_step :沿边采样步长(像素)(未配置默认 40,不需要每个点都找)
// edge_refine_gray :边缘点灰度阈值(0~255,灰度 >= 该值视为产品边缘)(未配置默认 240)
if (value_param["edge_refine_search"])
{
_config.supportDet.edge_refine_search = value_param["edge_refine_search"].asFloat();
}
if (value_param["edge_refine_step"])
{
_config.supportDet.edge_refine_step = value_param["edge_refine_step"].asFloat();
}
if (value_param["edge_refine_gray"])
{
_config.supportDet.edge_refine_gray = value_param["edge_refine_gray"].asFloat();
}
// 支架方向精细化(可选):模型 smallmask 精度低(1696×800 上采样回原图),
// minAreaRect 求支架方向角误差大,改为在 detImg 灰度原图上拟合支架长边求方向角。
// support_refine_search :取模型支架外接矩形最外侧多少列作为边缘搜索带(未配置默认 30)
// support_refine_step :沿支架长边采样步长(像素)(未配置默认 20)
// support_refine_segments:采样点分段数(每段稳健拟合一条线取角度中位数,未配置默认 6)
if (value_param["support_refine_search"])
{
_config.supportDet.support_refine_search = value_param["support_refine_search"].asFloat();
}
if (value_param["support_refine_step"])
{
_config.supportDet.support_refine_step = value_param["support_refine_step"].asFloat();
}
if (value_param["support_refine_segments"])
{
_config.supportDet.support_refine_segments = value_param["support_refine_segments"].asFloat();
}
auto value_qx = value_param["edge_select"]; auto value_qx = value_param["edge_select"];
if (value_qx.isArray()) if (value_qx.isArray())
{ {

@ -391,19 +391,33 @@ struct Det_File_Result_Info
} }
for (size_t i = 0; i < qx_result_list.size(); i++) for (size_t i = 0; i < qx_result_list.size(); i++)
{ {
float fr = qx_result_list.at(i).num * 1.0 / qx_all_num * 100; // 除零保护:没有任何缺陷统计时百分比按 0 处理
float fr = (qx_all_num > 0) ? (qx_result_list.at(i).num * 100.0f / qx_all_num) : 0.0f;
std::string str_qx = ""; std::string str_qx = "";
// printf("len %d \n", qx_result_list.at(i).qx_name.length()); // 名称补空格对齐到 20 字节。
for (int k = 0; k < (20 - qx_result_list.at(i).qx_name.length()); k++) // 注意:qx_name.length() 返回 size_t(无符号),若写成 20 - length(),
// 当名称超过 20 字节时(中文缺陷名如"铜箔面不良标签"为 21 字节)会下溢成
// 巨大无符号值,导致循环近似死循环(-f 批量卡住的根因)。
size_t nNameLen = qx_result_list.at(i).qx_name.length();
if (nNameLen < 20)
{ {
str_qx += " "; str_qx.append(20 - nNameLen, ' ');
} }
str_qx += qx_result_list.at(i).qx_name; str_qx += qx_result_list.at(i).qx_name;
char buffer123[64]; char buffer123[64];
sprintf(buffer123, ":%d %.1f%% ", qx_result_list.at(i).num, fr); sprintf(buffer123, ":%d %.1f%% ", qx_result_list.at(i).num, fr);
std::string st1 = buffer123; std::string st1 = buffer123;
str_qx += st1; str_qx += st1;
int nlen = fr; // 百分比条长度限制在 [0,100],避免异常值造成超长字符串
int nlen = static_cast<int>(fr);
if (nlen < 0)
{
nlen = 0;
}
if (nlen > 100)
{
nlen = 100;
}
for (int j = 0; j < nlen; j++) for (int j = 0; j < nlen; j++)
{ {

Loading…
Cancel
Save