@ -210,6 +210,13 @@ int ImgCheckAnalysisy::creatsavedir()
return 0 ;
return 0 ;
}
}
void ImgCheckAnalysisy : : SetTplInfo ( const cv : : RotatedRect & outerRect ,
const std : : vector < std : : vector < cv : : Point > > & pinContours )
{
m_tplOuterRect = outerRect ;
m_tplPinContours = pinContours ;
}
int ImgCheckAnalysisy : : LoadRunConfig ( void * p )
int ImgCheckAnalysisy : : LoadRunConfig ( void * p )
{
{
if ( p = = NULL )
if ( p = = NULL )
@ -363,241 +370,45 @@ cv::Scalar ImgCheckAnalysisy::calc_blob_info_withstats(cv::Mat &img, const cv::M
return cv : : Scalar ( worb , energy , hj ) ;
return cv : : Scalar ( worb , energy , hj ) ;
}
}
Point2f GetCoorPoint ( Point2f point , Mat img_mat )
int ImgCheckAnalysisy : : Adapt_Config ( RotatedRect tplOuterRect , RotatedRect curOuterRect , Mat & det_img ) {
{
vector < cv : : Point2f > cur_vertices = CheckUtil : : sort_vertices ( curOuterRect ) ;
// 越界判定
vector < cv : : Point2f > tpl_vertices = CheckUtil : : sort_vertices ( tplOuterRect ) ;
int coor_img_rect_x = point . x - 400 ;
int coor_img_rect_y = point . y - 400 ;
int coor_img_rect_w = 800 ;
int coor_img_rect_h = 800 ;
if ( coor_img_rect_x < 0 )
{
coor_img_rect_x = 0 ;
coor_img_rect_w = min ( 400 , img_mat . cols ) ;
}
if ( coor_img_rect_y < 0 )
{
coor_img_rect_y = 0 ;
coor_img_rect_h = min ( 400 , img_mat . rows ) ;
}
if ( coor_img_rect_x + coor_img_rect_w > img_mat . cols )
{
coor_img_rect_w = img_mat . cols - coor_img_rect_x ;
}
if ( coor_img_rect_y + coor_img_rect_h > img_mat . rows )
{
coor_img_rect_h = img_mat . rows - coor_img_rect_y ;
}
if ( coor_img_rect_x < 0 | | coor_img_rect_y < 0 | | coor_img_rect_x + coor_img_rect_w > img_mat . cols | | coor_img_rect_y + coor_img_rect_h > img_mat . rows )
{
return point ;
}
Mat coor_img_mat = img_mat ( Rect ( coor_img_rect_x , coor_img_rect_y , coor_img_rect_w , coor_img_rect_h ) ) ;
Mat coor_img_bin ;
threshold ( coor_img_mat , coor_img_bin , 50 , 255 , THRESH_BINARY ) ;
// 6. 查找轮廓
std : : vector < std : : vector < cv : : Point > > contours ;
cv : : findContours ( coor_img_bin , contours , cv : : RETR_EXTERNAL , cv : : CHAIN_APPROX_SIMPLE ) ;
if ( contours . empty ( ) )
{
return point ;
}
double maxArea = 0 ;
int maxAreaIdx = - 1 ;
for ( size_t i = 0 ; i < contours . size ( ) ; + + i )
{
double area = cv : : contourArea ( contours [ i ] ) ;
if ( area > maxArea )
{
maxArea = area ;
maxAreaIdx = i ;
}
}
if ( maxAreaIdx < 0 | | maxArea < 100 )
{
return point ;
}
cv : : RotatedRect rect = cv : : minAreaRect ( contours [ maxAreaIdx ] ) ;
Point2f vertices [ 4 ] ;
rect . points ( vertices ) ;
int cornerIdx = 0 ;
float minDist = FLT_MAX ;
for ( int i = 0 ; i < 4 ; i + + )
{
float dist = std : : pow ( vertices [ i ] . x - 400 , 2 ) + std : : pow ( vertices [ i ] . y - 400 , 2 ) ;
if ( dist < minDist )
{
minDist = dist ;
cornerIdx = i ;
}
}
Point2f new_point ;
new_point . x = vertices [ cornerIdx ] . x + coor_img_rect_x ;
new_point . y = vertices [ cornerIdx ] . y + coor_img_rect_y ;
new_point . x = std : : max ( 0.0f , std : : min ( new_point . x , static_cast < float > ( img_mat . cols - 1 ) ) ) ;
cv : : Point2f src_pts [ 3 ] = {
new_point . y = std : : max ( 0.0f , std : : min ( new_point . y , static_cast < float > ( img_mat . rows - 1 ) ) ) ;
cur_vertices [ 0 ] , // 对应左上
cur_vertices [ 1 ] , // 对应右上
cur_vertices [ 2 ] // 对应左下
} ;
cv : : Point2f dst_pts [ 3 ] = {
tpl_vertices [ 0 ] , // 左上
tpl_vertices [ 1 ] , // 右上
tpl_vertices [ 2 ] // 左下
} ;
cv : : Mat affine_mat = cv : : getAffineTransform ( src_pts , dst_pts ) ;
return new_point ;
// 仿射变换
}
cv : : warpAffine ( det_img , det_img , affine_mat , det_img . size ( ) ) ;
int GetEdgeRoi ( Mat img , Rect & new_roi , float scale_x , float scale_y ) {
// 将m_outer_rroi和m_inner_rroi变换到模板图像坐标系下
if ( img . empty ( ) )
auto transformRotatedRect = [ & affine_mat ] ( cv : : RotatedRect & rrect )
{
{
return 1 ;
const double * M = affine_mat . ptr < double > ( 0 ) ;
}
// 缩小,减少耗时
Mat r_img ;
int resize_width = static_cast < int > ( img . cols / scale_x ) ;
cv : : Point2f pts [ 4 ] ;
int resize_height = static_cast < int > ( img . rows / scale_y ) ;
rrect . points ( pts ) ;
resize ( img , r_img , Size ( resize_width , resize_height ) , 0 , 0 , INTER_LINEAR ) ;
// 二值化找最大连通域
std : : vector < cv : : Point2f > transformed_pts ( 4 ) ;
Mat r_img_bin ;
for ( int i = 0 ; i < 4 ; i + + )
threshold ( r_img , r_img_bin , 15 , 255 , THRESH_BINARY ) ;
std : : vector < std : : vector < cv : : Point > > contours ;
cv : : findContours ( r_img_bin , contours , cv : : RETR_EXTERNAL , cv : : CHAIN_APPROX_SIMPLE ) ;
if ( contours . empty ( ) )
{
return 2 ;
}
double maxArea = 0 ;
int maxAreaIdx = - 1 ;
for ( size_t i = 0 ; i < contours . size ( ) ; + + i )
{
double area = cv : : contourArea ( contours [ i ] ) ;
if ( area > maxArea )
{
maxArea = area ;
maxAreaIdx = i ;
}
}
if ( maxAreaIdx < 0 )
{
{
return 3 ;
float x = static_cast < float > ( M [ 0 ] * pts [ i ] . x + M [ 1 ] * pts [ i ] . y + M [ 2 ] ) ;
float y = static_cast < float > ( M [ 3 ] * pts [ i ] . x + M [ 4 ] * pts [ i ] . y + M [ 5 ] ) ;
transformed_pts [ i ] = cv : : Point2f ( x , y ) ;
}
}
rrect = cv : : minAreaRect ( transformed_pts ) ;
} ;
cv : : Rect small_roi = cv : : boundingRect ( contours [ maxAreaIdx ] ) ;
transformRotatedRect ( m_outer_rroi ) ;
Rect roi ;
transformRotatedRect ( m_inner_rroi ) ;
roi . x = static_cast < int > ( small_roi . x * scale_x ) ;
roi . y = static_cast < int > ( small_roi . y * scale_y ) ;
roi . width = static_cast < int > ( small_roi . width * scale_x ) ;
roi . height = static_cast < int > ( small_roi . height * scale_y ) ;
roi . x = std : : max ( 0 , roi . x ) ;
roi . y = std : : max ( 0 , roi . y ) ;
roi . width = std : : min ( roi . width , img . cols - roi . x ) ;
roi . height = std : : min ( roi . height , img . rows - roi . y ) ;
new_roi = roi ;
return 0 ;
}
int ImgCheckAnalysisy : : Adapt_Config ( Mat img , Rect cur_roi , bool b_update ) {
if ( img . empty ( ) ) {
std : : cerr < < " Error: Input image 'img' is empty! " < < std : : endl ;
return - 1 ;
}
if ( ! b_update ) {
return 1 ;
}
int get_edge_roi = GetEdgeRoi ( img , cur_roi , 20 , 20 ) ;
if ( get_edge_roi ! = 0 ) {
return 2 ;
}
m_pdetlog - > AddCheckstr ( PrintLevel_0 , " Adapt_Config " , " -------------------start-------------- " ) ;
/*计算xy偏移, 缩放比例*/
// 拷贝原始数据
if ( m_old_productROI . width = = 0 | | m_old_productROI . height = = 0 ) {
m_old_productROI = m_AnalysisyConfig . baseFunction . markLine . productROI ;
m_old_cur_edgeDet_region = m_AnalysisyConfig . baseFunction . edgeDet . region ;
m_old_cur_markLine_region = m_AnalysisyConfig . baseFunction . markLine . region ;
m_old_cur_markLine_mark1 = m_AnalysisyConfig . baseFunction . markLine . mark_local_1 ;
m_old_cur_markLine_mark2 = m_AnalysisyConfig . baseFunction . markLine . mark_local_2 ;
m_old_cur_regionConfigArr = m_AnalysisyConfig . commonCheckConfig . nodeConfigArr [ 0 ] . regionConfigArr ;
}
Rect old_roi = m_old_productROI ;
Point old_center ( old_roi . x + old_roi . width / 2 , old_roi . y + old_roi . height / 2 ) ;
Point new_center ( cur_roi . x + cur_roi . width / 2 , cur_roi . y + cur_roi . height / 2 ) ;
int x_offset = new_center . x - old_center . x ;
int y_offset = new_center . y - old_center . y ;
float scale_x = ( float ) cur_roi . width / ( float ) old_roi . width ;
float scale_y = ( float ) cur_roi . height / ( float ) old_roi . height ;
m_pdetlog - > AddCheckstr ( PrintLevel_0 , " Adapt_Config " , " old_roi = %d %d %d %d " , old_roi . x , old_roi . y , old_roi . width , old_roi . height ) ;
m_pdetlog - > AddCheckstr ( PrintLevel_0 , " Adapt_Config " , " cur_roi = %d %d %d %d " , cur_roi . x , cur_roi . y , cur_roi . width , cur_roi . height ) ;
m_pdetlog - > AddCheckstr ( PrintLevel_0 , " Adapt_Config " , " x_offset = %d y_offset = %d " , x_offset , y_offset ) ;
m_pdetlog - > AddCheckstr ( PrintLevel_0 , " Adapt_Config " , " scale_x = %f scale_y = %f " , scale_x , scale_y ) ;
if ( abs ( x_offset ) < 50 & & abs ( y_offset ) < 50 & & abs ( scale_x - 1 ) < 0.0001 & & abs ( scale_y - 1 ) < 0.0001 ) {
return 3 ;
}
/*获取待修改的region引用*/
std : : vector < cv : : Point > & cur_edgeDet_region = m_AnalysisyConfig . baseFunction . edgeDet . region ;
std : : vector < cv : : Point > & cur_markLine_region = m_AnalysisyConfig . baseFunction . markLine . region ;
cv : : Point & cur_markLine_mark1 = m_AnalysisyConfig . baseFunction . markLine . mark_local_1 ;
cv : : Point & cur_markLine_mark2 = m_AnalysisyConfig . baseFunction . markLine . mark_local_2 ;
std : : vector < RegionConfigST > & cur_regionConfigArr = m_AnalysisyConfig . commonCheckConfig . nodeConfigArr [ 0 ] . regionConfigArr ;
/*进行修改*/
// rect
m_AnalysisyConfig . baseFunction . markLine . productROI = cur_roi ;
// point
cur_markLine_mark1 . x = m_old_cur_markLine_mark1 . x + x_offset ;
cur_markLine_mark1 . y = m_old_cur_markLine_mark1 . y + y_offset ;
cur_markLine_mark1 = Point ( ( cur_markLine_mark1 . x - new_center . x ) * scale_x + new_center . x , ( cur_markLine_mark1 . y - new_center . y ) * scale_y + new_center . y ) ;
cur_markLine_mark2 . x = m_old_cur_markLine_mark2 . x + x_offset ;
cur_markLine_mark2 . y = m_old_cur_markLine_mark2 . y + y_offset ;
cur_markLine_mark2 = Point ( ( cur_markLine_mark2 . x - new_center . x ) * scale_x + new_center . x , ( cur_markLine_mark2 . y - new_center . y ) * scale_y + new_center . y ) ;
// region
for ( int i = 0 ; i < cur_edgeDet_region . size ( ) ; i + + ) {
cur_edgeDet_region [ i ] . x = m_old_cur_edgeDet_region [ i ] . x + x_offset ;
cur_edgeDet_region [ i ] . y = m_old_cur_edgeDet_region [ i ] . y + y_offset ;
cur_edgeDet_region [ i ] = Point ( ( cur_edgeDet_region [ i ] . x - new_center . x ) * scale_x + new_center . x , ( cur_edgeDet_region [ i ] . y - new_center . y ) * scale_y + new_center . y ) ;
}
for ( int i = 0 ; i < cur_markLine_region . size ( ) ; i + + ) {
cur_markLine_region [ i ] . x = m_old_cur_markLine_region [ i ] . x + x_offset ;
cur_markLine_region [ i ] . y = m_old_cur_markLine_region [ i ] . y + y_offset ;
cur_markLine_region [ i ] = Point ( ( cur_markLine_region [ i ] . x - new_center . x ) * scale_x + new_center . x , ( cur_markLine_region [ i ] . y - new_center . y ) * scale_y + new_center . y ) ;
}
for ( int i = 0 ; i < cur_regionConfigArr . size ( ) ; i + + ) {
for ( int j = 0 ; j < cur_regionConfigArr [ i ] . basicInfo . pointArry . size ( ) ; j + + ) {
cur_regionConfigArr [ i ] . basicInfo . pointArry [ j ] . x = m_old_cur_regionConfigArr [ i ] . basicInfo . pointArry [ j ] . x + x_offset ;
cur_regionConfigArr [ i ] . basicInfo . pointArry [ j ] . y = m_old_cur_regionConfigArr [ i ] . basicInfo . pointArry [ j ] . y + y_offset ;
cur_regionConfigArr [ i ] . basicInfo . pointArry [ j ] = Point ( ( cur_regionConfigArr [ i ] . basicInfo . pointArry [ j ] . x - new_center . x ) * scale_x + new_center . x , ( cur_regionConfigArr [ i ] . basicInfo . pointArry [ j ] . y - new_center . y ) * scale_y + new_center . y ) ;
}
}
/*show*/
// Mat show_img = img.clone();
// cv::rectangle(show_img, m_AnalysisyConfig.baseFunction.markLine.productROI, Scalar(255), 5);
// if(cur_edgeDet_region.size() >=2){
// for(int i = 0 ; i < cur_edgeDet_region.size() - 1; i++){
// cv::line(show_img, cur_edgeDet_region[i], cur_edgeDet_region[i+1], Scalar(255), 20);
// }
// }
// if(cur_markLine_region.size() >=2){
// for(int i = 0 ; i < cur_markLine_region.size() - 1; i++){
// cv::line(show_img, cur_markLine_region[i], cur_markLine_region[i+1], Scalar(255), 20);
// }
// }
// if(cur_regionConfigArr.size() >=2){
// for(int i = 0 ; i < cur_regionConfigArr.size(); i++){
// for(int j = 0; j < cur_regionConfigArr[i].basicInfo.pointArry.size()-1; j++){
// cv::line(show_img, cur_regionConfigArr[i].basicInfo.pointArry[j], cur_regionConfigArr[i].basicInfo.pointArry[j+1], Scalar(255), 20);
// }
// }
// }
// imwrite(m_AnalysisyConfig.commonCheckConfig.baseConfig.strCamearName +"_show_img.tiff", show_img);
return 0 ;
return 0 ;
}
}
@ -646,11 +457,8 @@ int ImgCheckAnalysisy::CheckRun()
long time_edge_s = CheckUtil : : getcurTime ( ) ;
long time_edge_s = CheckUtil : : getcurTime ( ) ;
/*AI 边缘定位(内外边缘)*/
/*AI 边缘定位(内外边缘)*/
cv : : RotatedRect outer_roi ;
cv : : RotatedRect inner_roi ;
// 模型定位内外边缘
// 模型定位内外边缘
int reedge = AI_Edge ( m_CheckResult_shareP - > in_shareImage - > img , outer_roi , inner_roi ) ;
int reedge = AI_Edge ( m_CheckResult_shareP - > in_shareImage - > img , m_outer_rroi , m_inner_rroi ) ;
m_outer_roi = outer_roi . boundingRect ( ) ;
if ( reedge ! = 0 )
if ( reedge ! = 0 )
{
{
m_pdetlog - > AddCheckstr ( PrintLevel_0 , " Error " , " AI_Edge is error type = %d " , reedge ) ;
m_pdetlog - > AddCheckstr ( PrintLevel_0 , " Error " , " AI_Edge is error type = %d " , reedge ) ;
@ -662,20 +470,96 @@ int ImgCheckAnalysisy::CheckRun()
m_pdetlog - > AddCheckstr ( PrintLevel_0 , " 2、pre detect " , " -------------------------AI_Edge------------succ---time %ld---- \n " , time_edge_e - time_edge_s ) ;
m_pdetlog - > AddCheckstr ( PrintLevel_0 , " 2、pre detect " , " -------------------------AI_Edge------------succ---time %ld---- \n " , time_edge_e - time_edge_s ) ;
// 计算内外边缘夹角
// 计算内外边缘夹角
float aouter = CheckUtil : : getLongAxisAngle ( outer_roi) ;
float aouter = CheckUtil : : getLongAxisAngle ( m_ outer_r roi) ;
float ainner = CheckUtil : : getLongAxisAngle ( inner_roi) ;
float ainner = CheckUtil : : getLongAxisAngle ( m_ inner_r roi) ;
float diff_align = std : : fabs ( aouter - ainner ) ;
float diff_align = std : : fabs ( aouter - ainner ) ;
diff_align = std : : fmod ( diff_align , 180.0f ) ; // 模 180 度
diff_align = std : : fmod ( diff_align , 180.0f ) ; // 模 180 度
/*投影对齐模板*/
// 两条直线的夹角取锐角: min(diff, 180 - diff)
Adapt_Config ( m_CheckResult_shareP - > in_shareImage - > img , m_outer_roi , m_pbaseCheckFunction - > markLine . badapt_region ) ;
if ( diff_align > 90.0f )
{
diff_align = 180.0f - diff_align ;
}
// 1. 使用 ALign_Config.angle_diff 卡控内外边缘夹角(未配置时默认 10 度)
float angleTh = 10.0f ;
if ( m_pbaseCheckFunction ! = NULL & & m_pbaseCheckFunction - > ALign_Config . angle_diff > 0.0f )
{
angleTh = m_pbaseCheckFunction - > ALign_Config . angle_diff ;
}
// 2. 使用 ALign_Config.x_offset / y_offset (mm) 卡控内外边缘中心偏移( mm 转像素)
float offX_px = 0.0f ;
float offY_px = 0.0f ;
if ( m_pbaseCheckFunction ! = NULL )
{
if ( m_fImgage_Scale_X > 0.0f )
{
offX_px = m_pbaseCheckFunction - > ALign_Config . x_offset / m_fImgage_Scale_X ;
}
if ( m_fImgage_Scale_Y > 0.0f )
{
offY_px = m_pbaseCheckFunction - > ALign_Config . y_offset / m_fImgage_Scale_Y ;
}
}
// 3. 内外边缘中心坐标偏移(像素)
float dx_px = std : : fabs ( m_outer_rroi . center . x - m_inner_rroi . center . x ) ;
float dy_px = std : : fabs ( m_outer_rroi . center . y - m_inner_rroi . center . y ) ;
bool bAngleErr = diff_align > angleTh ;
bool bOffsetXErr = ( offX_px > 0.0f ) & & ( dx_px > offX_px ) ;
bool bOffsetYErr = ( offY_px > 0.0f ) & & ( dy_px > offY_px ) ;
bool bOffsetErr = bOffsetXErr | | bOffsetYErr ;
// 角度超差或中心偏移超差 -> 添加到缺陷列表
if ( bAngleErr | | bOffsetErr )
{
QX_ERROR_INFO_ alignErr ;
alignErr . Idx = static_cast < int > ( m_pDetResult - > pQx_ErrorList - > size ( ) ) ;
// roi 用整张检测图区域( detImg 坐标系)
cv : : Rect tplRect = m_tplOuterRect . boundingRect ( ) ;
alignErr . roi = cv : : Rect ( 0 , 0 , tplRect . width , tplRect . height ) ;
alignErr . area = alignErr . roi . width * alignErr . roi . height ;
alignErr . JudgArea = alignErr . area * m_fImgage_Scale_X * m_fImgage_Scale_Y ;
alignErr . flen = tplRect . width * m_fImgage_Scale_X ;
alignErr . fbreadth = tplRect . height * m_fImgage_Scale_Y ;
alignErr . nconfig_qx_type = CONFIG_QX_NAME_other ;
alignErr . qx_name = CONFIG_QX_NAME_Names [ CONFIG_QX_NAME_other ] ;
alignErr . grayDis = diff_align ; // 记录内外边缘夹角(度)
alignErr . detRegionidxList . push_back ( 0 ) ;
alignErr . detlog - > AddCheckstr ( PrintLevel_1 , DET_LOG_LEVEL_3 , " Align Check " ,
" outer-inner angle diff %.2f deg " , diff_align ) ;
m_pDetResult - > pQx_ErrorList - > push_back ( alignErr ) ;
if ( bAngleErr )
{
m_pdetlog - > AddCheckstr ( PrintLevel_0 , " Align Check " , " angle diff %.2f deg > %.2f " , diff_align , angleTh ) ;
}
if ( bOffsetXErr )
{
m_pdetlog - > AddCheckstr ( PrintLevel_0 , " Align Check " , " center offset dx %.1f px > %.1f px " ,
dx_px , offX_px ) ;
}
if ( bOffsetYErr )
{
m_pdetlog - > AddCheckstr ( PrintLevel_0 , " Align Check " , " center offset dy %.1f px > %.1f px " ,
dy_px , offY_px ) ;
}
}
/*投影对齐模板*/
Adapt_Config ( m_tplOuterRect , m_outer_rroi , m_CheckResult_shareP - > in_shareImage - > img ) ;
m_outer_roi = m_tplOuterRect . boundingRect ( ) ;
m_Crop_Roi_paramImg = m_outer_roi ;
m_Crop_Roi_paramImg = m_outer_roi ;
m_pImageAllResult - > pDetResult - > CutRoi = m_outer_roi ;
m_pImageAllResult - > pDetResult - > CutRoi = m_outer_roi ;
m_pImageAllResult - > pDetResult - > Param_CropRoi = m_Crop_Roi_paramImg ;
m_pImageAllResult - > pDetResult - > Param_CropRoi = m_Crop_Roi_paramImg ;
long time_calan_e = CheckUtil : : getcurTime ( ) ;
long time_calan_e = CheckUtil : : getcurTime ( ) ;
m_pdetlog - > AddCheckstr ( PrintLevel_0 , " 2.1、pre detect " , " -------------------------CalAn------------succ---time %ld---- \n " , time_calan_e - time_edge_s ) ;
m_pdetlog - > AddCheckstr ( PrintLevel_0 , " 2.1、pre detect " , " -------------------------CalAn dAffine ------------succ---time %ld----\n " , time_calan_e - time_edge_s ) ;
/*生成 检测的图片*/
/*生成 检测的图片*/
cv : : Mat image ;
cv : : Mat image ;
@ -696,7 +580,7 @@ int ImgCheckAnalysisy::CheckRun()
ImgPreDet ( ) ;
ImgPreDet ( ) ;
/*更新检测区域*/
/*更新检测区域*/
Update_DetRoiList ( ) ;
// Update_DetRoiList();
m_pdetlog - > AddCheckstr ( PrintLevel_0 , " 3、pre detect " , " -------------------------pre Det--------------- \n " ) ;
m_pdetlog - > AddCheckstr ( PrintLevel_0 , " 3、pre detect " , " -------------------------pre Det--------------- \n " ) ;
@ -1457,12 +1341,10 @@ int ImgCheckAnalysisy::ConfigCheck(cv::Mat img)
int ImgCheckAnalysisy : : AI_Detect_Thread ( const cv : : Mat & img , cv : : Mat & ResultImg )
int ImgCheckAnalysisy : : AI_Detect_Thread ( const cv : : Mat & img , cv : : Mat & ResultImg )
{
{
std : : shared_ptr < AIModel_Base > pAIDet ;
// 依次使用多个检测模型,各模型输出 mask 取并集作为最终 outmask
// printf("=====>>>>AI_Detect_Thread m_strCurDetChannel %s \n", m_strCurDetChannel.c_str());
std : : vector < std : : shared_ptr < AIModel_Base > > pAIDetList ;
{
pAIDetList . push_back ( AI_Factory - > Defect ) ;
// printf("=====>>>>AI_Detect_Thread USE CA %s \n", m_strCurDetChannel.c_str());
pAIDetList . push_back ( AI_Factory - > Defect_QueXi ) ;
pAIDet = AI_Factory - > Defect ;
}
std : : string strBaseLog = " AI_Detect " ;
std : : string strBaseLog = " AI_Detect " ;
@ -1478,8 +1360,8 @@ int ImgCheckAnalysisy::AI_Detect_Thread(const cv::Mat &img, cv::Mat &ResultImg)
cutRoi . width = img . cols - 0 ;
cutRoi . width = img . cols - 0 ;
cutRoi . height = img . rows - 0 ;
cutRoi . height = img . rows - 0 ;
int deal_image_width = pAIDet - > input_0 . width ;
int deal_image_width = pAIDet List[ 0 ] - > input_0 . width ;
int deal_image_height = pAIDet - > input_0 . height ;
int deal_image_height = pAIDet List[ 0 ] - > input_0 . height ;
int re = CheckUtil : : cutSmallImg ( img , SmallRoiList , cutRoi , deal_image_width , deal_image_height , 0 , 0 ) ;
int re = CheckUtil : : cutSmallImg ( img , SmallRoiList , cutRoi , deal_image_width , deal_image_height , 0 , 0 ) ;
@ -1515,19 +1397,24 @@ int ImgCheckAnalysisy::AI_Detect_Thread(const cv::Mat &img, cv::Mat &ResultImg)
ResultImg = cv : : Mat : : zeros ( img . size ( ) , CV_8UC1 ) ;
ResultImg = cv : : Mat : : zeros ( img . size ( ) , CV_8UC1 ) ;
const int totalTasks = SmallRoiList . size ( ) ;
const int totalTasks = SmallRoiList . size ( ) ;
int submitted = 0 ;
int completed = 0 ;
// std::string str_Root = m_strRootPath + pDetConfig->strProductID + "_" + pDetConfig->strchannel + "_";
// std::string str_Root = m_strRootPath + pDetConfig->strProductID + "_" + pDetConfig->strchannel + "_";
t2 = CheckUtil : : getcurTime ( ) ;
t2 = CheckUtil : : getcurTime ( ) ;
// 依次用多个模型做检测,所有模型输出的 mask 取并集作为最终 outmask
for ( size_t m = 0 ; m < pAIDetList . size ( ) ; m + + )
{
std : : shared_ptr < AIModel_Base > pAIDet = pAIDetList [ m ] ;
int submitted = 0 ;
int completed = 0 ;
while ( completed < totalTasks )
while ( completed < totalTasks )
{
{
// 如果任务还没提交完,且当前处理任务数 < 2, 提交新任务
// 如果任务还没提交完,且当前处理任务数 < 10 ,提交新任务
if ( submitted < totalTasks & & runner - > GetProcessingCount ( ) < 10 )
if ( submitted < totalTasks & & runner - > GetProcessingCount ( ) < 10 )
{
{
std : : shared_ptr < AIMulThreadRunBase : : AITask > task = std : : make_shared < AIMulThreadRunBase : : AITask > ( ) ;
std : : shared_ptr < AIMulThreadRunBase : : AITask > task = std : : make_shared < AIMulThreadRunBase : : AITask > ( ) ;
task - > id = comple ted;
task - > id = submit ted;
task - > roi = SmallRoiList . at ( submitted ) ;
task - > roi = SmallRoiList . at ( submitted ) ;
task - > input = img ( SmallRoiList . at ( submitted ) ) . clone ( ) ;
task - > input = img ( SmallRoiList . at ( submitted ) ) . clone ( ) ;
task - > output = std : : make_shared < cv : : Mat > ( ) ;
task - > output = std : : make_shared < cv : : Mat > ( ) ;
@ -1550,13 +1437,28 @@ int ImgCheckAnalysisy::AI_Detect_Thread(const cv::Mat &img, cv::Mat &ResultImg)
cv : : Mat & outimg = * ( result - > output ) ;
cv : : Mat & outimg = * ( result - > output ) ;
if ( ! outimg . empty ( ) )
if ( ! outimg . empty ( ) )
{
{
outimg . copyTo ( ResultImg ( result - > roi ) , outimg ) ;
// 多个模型的结果取并集
cv : : Mat roiMat = ResultImg ( result - > roi ) ;
cv : : bitwise_or ( roiMat , outimg , roiMat ) ;
}
// 同一 roi 的多个模型结果取并集后存入 AI_Qx_MaskList
bool bFind = false ;
for ( auto & item : m_pImageAllResult - > AI_Qx_MaskList )
{
if ( item - > roi = = result - > roi )
{
cv : : bitwise_or ( item - > AI_mask , outimg , item - > AI_mask ) ;
bFind = true ;
break ;
}
}
}
if ( ! bFind )
{
{
std : : shared_ptr < ImageAllResult : : AI_Det_MaskImg > temAIresult = std : : make_shared < ImageAllResult : : AI_Det_MaskImg > ( ) ;
std : : shared_ptr < ImageAllResult : : AI_Det_MaskImg > temAIresult = std : : make_shared < ImageAllResult : : AI_Det_MaskImg > ( ) ;
temAIresult - > roi = result - > roi ;
temAIresult - > roi = result - > roi ;
temAIresult - > AI_inImg = result - > input ;
temAIresult - > AI_inImg = result - > input ;
temAIresult - > AI_mask = outimg ;
temAIresult - > AI_mask = outimg . clone ( ) ;
m_pImageAllResult - > AI_Qx_MaskList . push_back ( temAIresult ) ;
m_pImageAllResult - > AI_Qx_MaskList . push_back ( temAIresult ) ;
}
}
completed + + ;
completed + + ;
@ -1566,9 +1468,10 @@ int ImgCheckAnalysisy::AI_Detect_Thread(const cv::Mat &img, cv::Mat &ResultImg)
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 1 ) ) ;
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 1 ) ) ;
}
}
}
}
}
t3 = CheckUtil : : getcurTime ( ) ;
t3 = CheckUtil : : getcurTime ( ) ;
float mean_AI = ( t3 - t2 ) / SmallRoiList . size ( ) ;
float mean_AI = ( t3 - t2 ) / ( SmallRoiList . size ( ) * pAIDetList . size ( ) ) ;
m_pdetlog - > AddCheckstr ( PrintLevel_1 , DET_LOG_LEVEL_3 , strBaseLog , " AI Run Time: sum %ld pre %ld Run %ld mean One Small Img %f " , t3 - t1 , t2 - t1 , t3 - t2 , mean_AI ) ;
m_pdetlog - > AddCheckstr ( PrintLevel_1 , DET_LOG_LEVEL_3 , strBaseLog , " AI Run Time: sum %ld pre %ld Run %ld mean One Small Img %f " , t3 - t1 , t2 - t1 , t3 - t2 , mean_AI ) ;
m_pdetlog - > AddCheckstr ( PrintLevel_0 , DET_LOG_LEVEL_3 , strBaseLog , " AI_Detect End " ) ;
m_pdetlog - > AddCheckstr ( PrintLevel_0 , DET_LOG_LEVEL_3 , strBaseLog , " AI_Detect End " ) ;
@ -1613,7 +1516,7 @@ int ImgCheckAnalysisy::AI_QX_Class_Thread()
ERROR_DOTS_BLOB_DATA * pblob = & blobs . blobTab [ submitted ] ;
ERROR_DOTS_BLOB_DATA * pblob = & blobs . blobTab [ submitted ] ;
if ( pblob - > ErrType = = ERR_TYPE_2 )
if ( pblob - > ErrType = = ERR_TYPE_2 )
{
{
pblob - > AIclasstype = CONFIG_QX_NAME_ cell_ymhs ;
pblob - > AIclasstype = CONFIG_QX_NAME_ YiWu ;
submitted + + ;
submitted + + ;
completed + + ;
completed + + ;
continue ;
continue ;
@ -1660,47 +1563,39 @@ int ImgCheckAnalysisy::AI_QX_Class_Thread()
switch ( temClass )
switch ( temClass )
{
{
case 0 :
case 0 :
cls_num = AI_CLass_QX_NAME_ aotudia n;
cls_num = AI_CLass_QX_NAME_ PIN_PoSu n;
break ;
break ;
case 1 :
case 1 :
cls_num = AI_CLass_QX_NAME_ other ;
cls_num = AI_CLass_QX_NAME_ PIN_QueShi ;
break ;
break ;
case 2 :
case 2 :
cls_num = AI_CLass_QX_NAME_ lin e;
cls_num = AI_CLass_QX_NAME_ BTB_DuanLi e;
break ;
break ;
case 3 :
case 3 :
cls_num = AI_CLass_QX_NAME_ zangwu ;
cls_num = AI_CLass_QX_NAME_ LianXi ;
break ;
break ;
case 4 :
case 4 :
cls_num = AI_CLass_QX_NAME_ dianzhuang ;
cls_num = AI_CLass_QX_NAME_ QueXi ;
break ;
break ;
case 5 :
case 5 :
cls_num = AI_CLass_QX_NAME_ posun ;
cls_num = AI_CLass_QX_NAME_ YiWu ;
break ;
break ;
case 6 :
case 6 :
cls_num = AI_CLass_QX_NAME_ xianwei ;
cls_num = AI_CLass_QX_NAME_ C_BianXing ;
break ;
break ;
case 7 :
case 7 :
cls_num = AI_CLass_QX_NAME_shuizi ;
cls_num = AI_CLass_QX_NAME_other ;
break ;
case 8 :
cls_num = AI_CLass_QX_NAME_danban ;
break ;
case 9 :
cls_num = AI_CLass_QX_NAME_fuchen ;
break ;
break ;
default :
default :
cls_num = AI_CLass_QX_NAME_ zangwu ;
cls_num = AI_CLass_QX_NAME_other ;
break ;
break ;
}
}
@ -1890,77 +1785,40 @@ int ImgCheckAnalysisy::DrawResult_Step_1()
float fs_resize_x = m_pImageAllResult - > resultImg . cols * 1.0f / m_pImageAllResult - > detImg . cols ;
float fs_resize_x = m_pImageAllResult - > resultImg . cols * 1.0f / m_pImageAllResult - > detImg . cols ;
float fs_resize_y = m_pImageAllResult - > resultImg . rows * 1.0f / m_pImageAllResult - > detImg . rows ;
float fs_resize_y = m_pImageAllResult - > resultImg . rows * 1.0f / m_pImageAllResult - > detImg . rows ;
// 要绘制结果
// 绘制模板 pin 轮廓(绿色)与当前 pin 轮廓(红色)
if ( m_pbaseCheckFunction & & m_pbaseCheckFunction - > edgeDet . bDrawResult )
for ( const auto & contour : m_tplPinContours )
{
for ( const auto & r : m_Edge_DetConfig . pin_det_roi )
{
{
cv : : Rect droi ;
std : : vector < cv : : Point > draw_pts ;
droi . x = r . roi . x * fs_resize_x ;
draw_pts . reserve ( contour . size ( ) ) ;
droi . y = r . roi . y * fs_resize_y ;
for ( const auto & pt : contour )
droi . width = r . roi . width * fs_resize_x ;
droi . height = r . roi . height * fs_resize_y ;
cv : : rectangle ( m_CheckResult_shareP - > resultimg , droi , cv : : Scalar ( 255 , 0 , 255 ) , 1 ) ; // 黄色角点
}
if ( m_Edge_DetConfig . Det_region . size ( ) > 2 )
{
for ( int i = 0 ; i < m_Edge_DetConfig . Det_region . size ( ) - 1 ; i + + )
{
cv : : Point p1 ;
p1 . x = m_Edge_DetConfig . Det_region [ i ] . x * fs_resize_x ;
p1 . y = m_Edge_DetConfig . Det_region [ i ] . y * fs_resize_y ;
cv : : Point p2 ;
p2 . x = m_Edge_DetConfig . Det_region [ i + 1 ] . x * fs_resize_x ;
p2 . y = m_Edge_DetConfig . Det_region [ i + 1 ] . y * fs_resize_y ;
cv : : line ( m_CheckResult_shareP - > resultimg , p1 , p2 , cv : : Scalar ( 0 , 255 , 255 ) ) ;
}
{
{
cv : : Point p1 ;
draw_pts . emplace_back ( cvRound ( pt . x * fs_resize_x ) , cvRound ( pt . y * fs_resize_y ) ) ;
p1 . x = m_Edge_DetConfig . Det_region [ 0 ] . x * fs_resize_x ;
p1 . y = m_Edge_DetConfig . Det_region [ 0 ] . y * fs_resize_y ;
cv : : Point p2 ;
p2 . x = m_Edge_DetConfig . Det_region [ m_Edge_DetConfig . Det_region . size ( ) - 1 ] . x * fs_resize_x ;
p2 . y = m_Edge_DetConfig . Det_region [ m_Edge_DetConfig . Det_region . size ( ) - 1 ] . y * fs_resize_y ;
cv : : line ( m_CheckResult_shareP - > resultimg , p1 , p2 , cv : : Scalar ( 0 , 255 , 255 ) ) ;
}
}
cv : : polylines ( m_CheckResult_shareP - > resultimg , draw_pts , true , cv : : Scalar ( 255 , 255 , 0 ) , 1 ) ;
}
}
}
for ( const auto & contour : m_curPinContours )
if ( m_pbaseCheckFunction & & m_pbaseCheckFunction - > markLine . region . size ( ) > 1 )
{
{
std : : vector < cv : : Point > product_roi_show ;
std : : vector < cv : : Point > draw_pts ;
for ( const auto & pt : m_pbaseCheckFunction - > markLine . region )
draw_pts . reserve ( contour . size ( ) ) ;
for ( const auto & pt : contour )
{
{
cv : : Point draw_pt ;
draw_pts . emplace_back ( cvRound ( pt . x * fs_resize_x ) , cvRound ( pt . y * fs_resize_y ) ) ;
draw_pt . x = ( pt . x - m_Crop_Roi_paramImg . x ) * fs_resize_x ;
draw_pt . y = ( pt . y - m_Crop_Roi_paramImg . y ) * fs_resize_y ;
product_roi_show . push_back ( draw_pt ) ;
}
}
cv : : polylines ( m_CheckResult_shareP - > resultimg , draw_pts , true , cv : : Scalar ( 255 , 0 , 255 ) , 1 ) ;
cv : : polylines (
m_CheckResult_shareP - > resultimg ,
product_roi_show ,
true ,
cv : : Scalar ( 0 , 255 , 0 ) ,
1 ) ;
}
}
if ( m_pEdge_Align_Result . get ( ) ! = NULL )
{
if ( m_pbaseCheckFunction - > markLine . bDraw )
// 绘制m_inner_rroi( 蓝色)
{
for ( size_t i = 0 ; i < m_pEdge_Align_Result - > markresulList . size ( ) ; i + + )
{
{
// if (m_pEdge_Align_Result->markresulList[i].status == Mark_Result_Status_OK)
cv : : Point2f vertices [ 4 ] ;
m_inner_rroi . points ( vertices ) ;
std : : vector < cv : : Point > draw_pts ;
draw_pts . reserve ( 4 ) ;
for ( int i = 0 ; i < 4 ; i + + )
{
{
cv : : Point p ;
draw_pts . emplace_back ( cvRound ( ( vertices [ i ] . x - m_Crop_Roi_paramImg . x ) * fs_resize_x ) ,
p . x = m_pEdge_Align_Result - > markresulList [ i ] . det_Local_DetImg . x * fs_resize_x ;
cvRound ( ( vertices [ i ] . y - m_Crop_Roi_paramImg . y ) * fs_resize_y ) ) ;
p . y = m_pEdge_Align_Result - > markresulList [ i ] . det_Local_DetImg . y * fs_resize_y ;
cv : : circle ( m_CheckResult_shareP - > resultimg , p , 5 , cv : : Scalar ( 0 , 255 , 0 ) ) ;
}
}
}
}
cv : : polylines ( m_CheckResult_shareP - > resultimg , draw_pts , true , cv : : Scalar ( 255 , 0 , 0 ) , 1 ) ;
}
}
// cv::imwrite("sss.png", m_CheckResult_shareP->resultimg);
// cv::imwrite("sss.png", m_CheckResult_shareP->resultimg);
@ -1970,38 +1828,32 @@ int ImgCheckAnalysisy::DrawResult_Step_1()
int ImgCheckAnalysisy : : AIClassTypeToConfigType ( int nAIQXType )
int ImgCheckAnalysisy : : AIClassTypeToConfigType ( int nAIQXType )
{
{
int resultError_type = CONFIG_QX_NAME_ cell_aotudian ;
int resultError_type = CONFIG_QX_NAME_ other ;
switch ( nAIQXType )
switch ( nAIQXType )
{
{
case AI_CLass_QX_NAME_ aotudia n:
case AI_CLass_QX_NAME_ PIN_PoSu n:
resultError_type = CONFIG_QX_NAME_ cell_aotudia n;
resultError_type = CONFIG_QX_NAME_ PIN_PoSu n;
break ;
break ;
case AI_CLass_QX_NAME_other :
case AI_CLass_QX_NAME_PIN_QueShi :
resultError_type = CONFIG_QX_NAME_cell_other ;
resultError_type = CONFIG_QX_NAME_PIN_QueShi ;
break ;
case AI_CLass_QX_NAME_line :
resultError_type = CONFIG_QX_NAME_cell_line ;
break ;
break ;
case AI_CLass_QX_NAME_ zangwu :
case AI_CLass_QX_NAME_BTB_DuanLie :
resultError_type = CONFIG_QX_NAME_ cell_zangwu ;
resultError_type = CONFIG_QX_NAME_BTB_DuanLie ;
break ;
break ;
case AI_CLass_QX_NAME_ dianzhuang :
case AI_CLass_QX_NAME_ LianXi :
resultError_type = CONFIG_QX_NAME_ cell_dianzhuang ;
resultError_type = CONFIG_QX_NAME_ LianXi ;
break ;
break ;
case AI_CLass_QX_NAME_ posun :
case AI_CLass_QX_NAME_ QueXi :
resultError_type = CONFIG_QX_NAME_ cell_posun ;
resultError_type = CONFIG_QX_NAME_ QueXi ;
break ;
break ;
case AI_CLass_QX_NAME_ xianwei :
case AI_CLass_QX_NAME_ YiWu :
resultError_type = CONFIG_QX_NAME_ cell_xianwei ;
resultError_type = CONFIG_QX_NAME_ YiWu ;
break ;
break ;
case AI_CLass_QX_NAME_ shuizi :
case AI_CLass_QX_NAME_ C_BianXing :
resultError_type = CONFIG_QX_NAME_ cell_shuizi ;
resultError_type = CONFIG_QX_NAME_ C_BianXing ;
break ;
break ;
case AI_CLass_QX_NAME_danban :
case AI_CLass_QX_NAME_other :
resultError_type = CONFIG_QX_NAME_cell_danban ;
resultError_type = CONFIG_QX_NAME_other ;
break ;
case AI_CLass_QX_NAME_fuchen :
resultError_type = CONFIG_QX_NAME_cell_fuchen ;
break ;
break ;
default :
default :
break ;
break ;
@ -2036,76 +1888,171 @@ int ImgCheckAnalysisy::Pin_Qx_Det(const cv::Mat &img)
m_Edge_DetConfig . bSaveResultImg = true ;
m_Edge_DetConfig . bSaveResultImg = true ;
}
}
// m_pbaseCheckFunction->print("Pin_Qx_Det");
// m_pbaseCheckFunction->print("Pin_Qx_Det");
int re = m_Pin_QX_Det . Detect ( img , & m_Edge_DetConfig ) ;
Mat pin_mask ;
if ( re = = 0 )
int re = m_Pin_QX_Det . GetPinMask ( img , & m_Edge_DetConfig , pin_mask ) ;
// 统计tplPinMask的blob边缘点, 并绘制到tplImg上
vector < vector < Point > > pin_contours ;
vector < Vec4i > hierarchy ;
cv : : findContours ( pin_mask , pin_contours , hierarchy , cv : : RETR_EXTERNAL , cv : : CHAIN_APPROX_NONE ) ;
//缩放比例
const float pin_scale_x = ( pin_mask . cols > 0 ) ? static_cast < float > ( img . cols ) / pin_mask . cols : 0.0f ;
const float pin_scale_y = ( pin_mask . rows > 0 ) ? static_cast < float > ( img . rows ) / pin_mask . rows : 0.0f ;
// 将轮廓点从 mask 坐标系 映射回 tplImg 坐标系
m_curPinContours . clear ( ) ;
m_curPinContours . reserve ( pin_contours . size ( ) ) ;
for ( size_t i = 0 ; i < pin_contours . size ( ) ; i + + )
{
{
for ( const auto r : m_Edge_DetConfig . qx_result )
std : : vector < cv : : Point > mapped ;
mapped . reserve ( pin_contours [ i ] . size ( ) ) ;
for ( const auto & pt : pin_contours [ i ] )
{
{
QX_ERROR_INFO_ temerror ;
mapped . emplace_back ( cvRound ( pt . x * pin_scale_x ) ,
temerror . roi = r . roi_src ;
cvRound ( pt . y * pin_scale_y ) ) ;
temerror . Idx = m_pDetResult - > pQx_ErrorList - > size ( ) ;
}
temerror . area = r . area_pixel ;
m_curPinContours . push_back ( mapped ) ;
temerror . JudgArea = r . area_pixel * m_fImgage_Scale_X * m_fImgage_Scale_Y ;
}
temerror . JudgArea_second = temerror . JudgArea ;
temerror . energy = 99999999 ;
temerror . flen = std : : max ( r . roi_src . width , r . roi_src . height ) ;
temerror . fbreadth = std : : min ( r . roi_src . width , r . roi_src . height ) ;
temerror . nconfig_qx_type = CONFIG_QX_NAME_cell_edge ;
temerror . qx_name = CONFIG_QX_NAME_Names [ CONFIG_QX_NAME_cell_edge ] ;
temerror . maxValue = 0 ;
temerror . grayDis = 255 ;
temerror . density = 0 ;
temerror . fUpIou = 0 ;
// 根据模板Pin和当前Pin轮廓进行对比, 判断当前有无缺失和偏移
{
{
cv : : Point pCenter ;
// 计算轮廓中心点(外接矩形中心)
pCenter . x = temerror . roi . x + temerror . roi . width * 0.5 ;
auto getCenter = [ ] ( const std : : vector < cv : : Point > & contour ) - > cv : : Point2f
pCenter . y = temerror . roi . y + temerror . roi . height * 0.5 ;
int nmaxregionIdx = 0 ;
for ( int iregion = 0 ; iregion < m_DetRoiList . roiList_Src . size ( ) ; iregion + + )
{
{
const std : : vector < cv : : Point > & polygon = m_DetRoiList . roiList_Src [ iregion ] ;
cv : : Rect r = cv : : boundingRect ( contour ) ;
double result = cv : : pointPolygonTest ( polygon , pCenter , false ) ;
return cv : : Point2f ( r . x + r . width * 0.5f , r . y + r . height * 0.5f ) ;
if ( result < 0 )
} ;
const int nTpl = static_cast < int > ( m_tplPinContours . size ( ) ) ;
const int nCur = static_cast < int > ( m_curPinContours . size ( ) ) ;
if ( nTpl > 0 )
{
// 1、统计模板 pin 中心与外包矩形
std : : vector < cv : : Point2f > tplCenters ( nTpl ) ;
std : : vector < cv : : Rect > tplRects ( nTpl ) ;
for ( int i = 0 ; i < nTpl ; i + + )
{
tplCenters [ i ] = getCenter ( m_tplPinContours [ i ] ) ;
tplRects [ i ] = cv : : boundingRect ( m_tplPinContours [ i ] ) ;
}
// 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 , int nconfig_qx_type )
{
QX_ERROR_INFO_ pinErr ;
pinErr . Idx = static_cast < int > ( m_pDetResult - > pQx_ErrorList - > size ( ) ) ;
cv : : Rect r = cv : : boundingRect ( m_tplPinContours [ pinIdx ] ) ;
pinErr . roi = r ;
pinErr . area = static_cast < int > ( cv : : contourArea ( m_tplPinContours [ pinIdx ] ) ) ;
pinErr . JudgArea = pinErr . area * m_fImgage_Scale_X * m_fImgage_Scale_Y ;
int longSide = ( r . width > r . height ) ? r . width : r . height ;
int shortSide = ( r . width < r . height ) ? r . width : r . height ;
pinErr . flen = longSide * m_fImgage_Scale_X ;
pinErr . fbreadth = shortSide * m_fImgage_Scale_Y ;
pinErr . nconfig_qx_type = nconfig_qx_type ;
pinErr . qx_name = CONFIG_QX_NAME_Names [ nconfig_qx_type ] ;
pinErr . detRegionidxList . push_back ( 0 ) ;
pinErr . detlog - > AddCheckstr ( PrintLevel_1 , DET_LOG_LEVEL_3 , " Pin Check " ,
" pin %d center(%d,%d) %s " ,
pinIdx , static_cast < int > ( tplCenter . x ) , static_cast < int > ( tplCenter . y ) ,
reason . c_str ( ) ) ;
m_pDetResult - > pQx_ErrorList - > push_back ( pinErr ) ;
} ;
int nMiss = 0 ;
int nOffset = 0 ;
// 4、逐个模板 pin 找与其相交且未被占用的当前 pin
for ( int i = 0 ; i < nTpl ; i + + )
{
int bestIdx = - 1 ;
double bestDist = 1e12 ;
for ( int j = 0 ; j < nCur ; j + + )
{
if ( curUsed [ j ] )
{
{
continue ;
continue ;
}
}
nmaxregionIdx = iregion ;
// 完全与模板没有相交 -> 不算候选
cv : : Rect inter = tplRects [ i ] & curRects [ j ] ;
if ( inter . width < = 0 | | inter . height < = 0 )
{
continue ;
}
}
temerror . detRegionidxList . push_back ( nmaxregionIdx ) ;
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 ) ;
if ( d < bestDist )
{
bestDist = d ;
bestIdx = j ;
}
}
}
// {
// 没有相交的当前 pin -> 缺失
// cv::Point pCenter;
if ( bestIdx < 0 )
// pCenter.x = temerror.roi.x + temerror.roi.width * 0.5;
{
// pCenter.y = temerror.roi.y + temerror.roi.height * 0.5;
nMiss + + ;
// int nmaxregionIdx = 0;
reportPinError ( i , tplCenters [ i ] , " miss " , CONFIG_QX_NAME_PIN_QueShi ) ;
// for (int iregion = 0; iregion < m_DetRoiList.roiList_Src.size(); iregion++)
m_pdetlog - > AddCheckstr ( PrintLevel_0 , " Pin Check " , " pin %d MISS " , i ) ;
// {
continue ;
// const std::vector<cv::Point> &polygon = m_DetRoiList.roiList_Src[iregion];
}
// double result = cv::pointPolygonTest(polygon, pCenter, false);
// if (result < 0)
// {
// continue;
// }
// temerror.detRegionidxList.push_back(iregion);
// }
// if (temerror.detRegionidxList.size() <= 0)
// {
// temerror.detRegionidxList.push_back(0);
// }
// }
m_pDetResult - > pQx_ErrorList - > push_back ( temerror ) ;
curUsed [ bestIdx ] = true ;
// 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 dx %.1f dy %.1f " , absDx , absDy ) ;
reportPinError ( i , tplCenters [ i ] , buf , CONFIG_QX_NAME_PIN_PianYi ) ;
m_pdetlog - > AddCheckstr ( PrintLevel_0 , " Pin Check " , " pin %d OFFSET dx %.1f dy %.1f " , i , absDx , absDy ) ;
}
}
}
m_pdetlog - > AddCheckstr ( PrintLevel_1 , " Pin_Qx_Det " , " succ qx num %ld " , m_Edge_DetConfig . qx_result . size ( ) ) ;
m_pdetlog - > AddCheckstr ( PrintLevel_0 , " Pin Check " , " tpl %d cur %d miss %d offset %d " , nTpl , nCur , nMiss , nOffset ) ;
// printf("- %s idx %d a %f v %d h %f l %f\n", DetImgInfo_shareP->strChannel.c_str(), i, JudgArea, blobs.blobTab[i].maxValue, blobs.blobTab[i].grayDis, flen);
}
}
else
}
if ( m_Edge_DetConfig . bSaveResultImg )
{
{
m_pdetlog - > AddCheckstr ( PrintLevel_1 , " Pin_Qx_Det " , " error %d " , re ) ;
Mat showimg ;
cv : : cvtColor ( img , showimg , cv : : COLOR_GRAY2BGR ) ;
cv : : drawContours ( showimg , m_curPinContours , - 1 , cv : : Scalar ( 0 , 0 , 255 ) , 1 ) ;
cv : : drawContours ( showimg , m_tplPinContours , - 1 , cv : : Scalar ( 0 , 255 , 0 ) , 1 ) ;
imwrite ( " pin_contours.png " , showimg ) ;
}
}
return 0 ;
return 0 ;