目录
一、场景需求
1、检测手机摄像头中框各部分宽度是否在规格允许范围内。
2、检测中框各部分是否有磕碰等异常瑕疵。
二、源码解析
* 设置边框宽度规格最大最小值
MinWidth := 30
MaxWidth := 35
* 设置边缘缺陷提取阈值
SmoothnessTolerance := .2
* 显示初始化
dev_update_off ()
dev_close_window ()
read_image (Image, 'plastic_parts/phone_camera_frame_01')
dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle)
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
Colors := ['white', 'green', 'yellow', 'orange', 'red']
Legend := 'Legend:'
Legend[1] := 'Extracted contours'
Legend[2] := 'Frame too narrow'
Legend[3] := 'Frame too wide'
Legend[4] := 'Contour defect'
* 主程序
NumImages := 2
for I := 1 to NumImages by 1
read_image (Image, 'plastic_parts/phone_camera_frame_' + I$'02')
*阈值分割
threshold (Image, Region, 100, 255)
* 区域膨胀获得检测ROI区域
dilation_rectangle1 (Region, RegionDilation, 15, 15)
* 修改图像定义域,检测范围限制在ROI区域内
reduce_domain (Image, RegionDilation, ImageReduced)
* 提取亚像素边缘轮廓xld,提取中框内外边界
edges_sub_pix (ImageReduced, Edges, 'canny', 0.7, 10, 60)
* 合并连通xld轮廓
union_adjacent_contours_xld (Edges, UnionContours, 7, 7, 'attr_keep')
*筛选长度在700-99999之间的轮廓,确定中框内外轮廓
select_shape_xld (UnionContours, SelectedContours, 'contlength', 'and', 700, 99999)
* 计算各轮廓长度,供后续筛选
length_xld (SelectedContours, Length)
* 对xld按照长度重排序
tuple_sort_index (Length, Indices)
* 选择最内、最外轮廓
select_obj (SelectedContours, InnerContour, Indices[0] + 1)
select_obj (SelectedContours, OuterContour, Indices[3] + 1)
* 计算内外轮廓之间的宽度,作为外轮廓宽度
distance_contours_xld (InnerContour, OuterContour, OuterContourWithWidth, 'point_to_segment')
* 从带宽度属性的外轮廓中分割出小于最小宽度的轮廓段
segment_contour_attrib_xld (OuterContourWithWidth, OuterContourPartToNarrow, 'distance', 'or', 0, MinWidth)
* 从带宽度属性的外轮廓中分割出大于最大宽度的轮廓段
segment_contour_attrib_xld (OuterContourWithWidth, OuterContourPartToWide, 'distance', 'or', MaxWidth, 10000)
* 平滑内外轮廓线,作为缺陷检测参考基准轮廓线(若有缺陷则会被平滑掉)
smooth_contours_xld (OuterContour, OuterContourSmooth, 11)
smooth_contours_xld (InnerContour, InnerContourSmooth, 11)
* 计算平滑后的轮廓线与平滑前轮廓线的距离
distance_contours_xld (OuterContour, OuterContourSmooth, OuterContourWithDistance, 'point_to_segment')
distance_contours_xld (InnerContour, InnerContourSmooth, InnerContourWithDistance, 'point_to_segment')
* 分割出大于SmoothnessTolerance阈值的轮廓段即为瑕疵段
segment_contour_attrib_xld (OuterContourWithDistance, OuterContourDefect, 'distance', 'or', SmoothnessTolerance, 100)
segment_contour_attrib_xld (InnerContourWithDistance, InnerContourDefect, 'distance', 'or', SmoothnessTolerance, 100)
* 距离可视化调试
get_contour_attrib_xld (OuterContourWithWidth, 'distance', FrameWidth)
get_contour_attrib_xld (OuterContourWithDistance, 'distance', InnerDistances)
get_contour_attrib_xld (InnerContourWithDistance, 'distance', OuterDistances)
* 结果显示
dev_display (Image)
disp_message (WindowHandle, 'Inspect frame of phone camera (image ' + I + '/' + NumImages + ')', 'window', 12, 12, 'black', 'true')
count_obj (OuterContourPartToNarrow, NumTooNarrow)
count_obj (OuterContourPartToWide, NumTooWide)
count_obj (OuterContourDefect, NumInnerDefects)
count_obj (InnerContourDefect, NumOuterDefects)
if (NumTooNarrow + NumTooWide + NumInnerDefects + NumOuterDefects == 0)
OK := 1
disp_message (WindowHandle, 'Frame OK', 'window', 50, 12, 'forest green', 'true')
else
OK := 0
disp_message (WindowHandle, 'Frame not OK', 'window', 50, 12, 'red', 'true')
endif
*
dev_set_line_width (1)
dev_set_color (Colors[1])
dev_display (OuterContour)
dev_display (InnerContour)
dev_set_line_width (5)
dev_set_color (Colors[2])
dev_display (OuterContourPartToNarrow)
dev_set_color (Colors[3])
dev_display (OuterContourPartToWide)
dev_set_color (Colors[4])
dev_display (OuterContourDefect)
dev_set_color (Colors[4])
dev_display (InnerContourDefect)
disp_message (WindowHandle, Legend, 'window', 500, 12, Colors, 'false')
if (I < NumImages)
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
endif
endfor
三、核心算子
1、distance_contours_xld:计算两个xld轮廓之间的距离,并生成带宽度属性的xld。
2、segment_contour_attrib_xld:按参数属性分割出满足参数范围的轮廓段。
四、技巧思路
1、使用Blob分析确定检测ROI区域,缩小图像定义域。
2、将xld按长度排序,按索引确定轮廓的内外位置关系。
3、使用xld平滑作为边缘瑕疵检测的基准参考线,通过计算原xld与平滑后的参考xld的距离从而检测出边缘缺陷,