开发环境:
基本思路:
灰度阈值处理+特征提取
ps:思考:如何通过阈值处理后,后续缩小检测目标范围?
二值化、梯度阈值、自适应阈值等方法来增强图像的对比度,从而突出目标特征,进一步缩小检测目标范围。
实例
检测红色圆片的个数
代码实现:
read_image (Image1, 'D:/视觉图片/1.圆片.jpg')
decompose3 (Image1, Image11, Image2, Image3)
threshold (Image11, Regions, 223, 255)
fill_up (Regions, RegionFillUp)
connection (RegionFillUp, ConnectedRegions)
select_shape (ConnectedRegions,SelectedRegions, 'area', 'and', 5000, 200000)
count_obj (SelectedRegions, Number1)
area_center (SelectedRegions, Area, Row, Column)
dev_set_color ('green')
gen_cross_contour_xld (Cross, Row, Column, 100, 0)
smallest_circle (SelectedRegions, Row1, Column1, Radius)
gen_circle_contour_xld (circle, Row1, Column1, Radius, 0, 6.28318, 'positive', 1)
dev_display (Image1)
dev_set_line_width (2)
dev_set_color ('green')
dev_display (Cross)
dev_display (circle)
count_obj (circle, Number)
dev_get_window (WindowHandle)
msg:='红色目标数量: '+Number
disp_message (WindowHandle, msg, 'image', 12, 12, 'black', 'true')
disp_message (WindowHandle, '智能制造-蒋达', 'window', 50, 50, 'black', 'true')
运行结果:
单骰子点数
方法一:
基本思路:通过阈值处理操作(0-40)将点数和背景检测出,再通过特征处理将“圆形”的点数筛选出,然后计数即可。
代码实现:
read_image (Image1, 'D:/视觉图片/2.筛子.jpg')
decompose3 (Image1, Image11, Image2, Image3)
threshold (Image11, Regions, 0, 40)
connection (Regions, Connection)
select_shape (Connection, SelectedRegions, 'circularity', 'and', 0.47685, 0.94722)
count_obj (SelectedRegions, Number1)
area_center (SelectedRegions, Area, Row, Column)
dev_set_color ('green')
gen_cross_contour_xld (Cross, Row, Column, 20, 0.785398)
smallest_circle (SelectedRegions, Row1, Column1, Radius)
gen_circle_contour_xld (circle, Row1, Column1, Radius, 0, 6.28318, 'positive', 1)
dev_display (Image1)
dev_set_line_width (2)
dev_set_color ('green')
dev_display (Cross)
dev_display (circle)
count_obj (circle, Number)
dev_get_window (WindowHandle)
msg:='筛子点数为: '+Number
disp_message (WindowHandle, msg, 'image', 12, 12, 'black', 'true')
disp_message (WindowHandle, '智能制造-蒋达', 'window', 50, 50, 'black', 'true')
运行结果:
方法二:
基础思路:通过阈值处理等操作将整个骰子筛选出来,再通过定位和缩小范围将点数筛选出来,再计数即可。
代码实现:
read_image (Image2, 'D:/视觉图片/2.筛子.jpg')
decompose3 (Image2, ImageR, ImageG, ImageB)
threshold (ImageG, Regions, 87, 167)
*填充孔洞
fill_up (Regions, RegionFillUp)
*特征筛选,使用面积过滤小的干扰
select_shape (RegionFillUp, SelectedRegions, 'area', 'and', 30000, 34000)
count_obj (SelectedRegions, Number1)
* 求中心
area_center (SelectedRegions, Area, Row, Column)
*生成十字
gen_cross_contour_xld (Cross, Row, Column, 30, 0.785398)
*包围框
smallest_rectangle2 (SelectedRegions, Row1, Column1, Phi, Length1, Length2)
gen_rectangle2_contour_xld (Rectangle, Row1, Column1, Phi, Length1, Length2)
dev_display (Image2)
dev_set_line_width (2)
dev_display (Cross)
dev_display (Rectangle)
stop ()
* 定位到的筛子区域也就是点的ROI
* 缩小检测范围到ROI
reduce_domain (ImageG, SelectedRegions, ImageReduced)
threshold (ImageReduced, Regions1, 0, 90)
connection (Regions1, ConnectedRegions)
select_shape (ConnectedRegions, SelectedRegions1, 'area', 'and', 1211.06, 1410.05)
* 计数
count_obj (SelectedRegions1, Number)
dev_display (Image2)
dev_set_line_width (2)
dev_display (Cross)
dev_display (Rectangle)
msg:='筛子点数为: '+Number
dev_get_window (WindowHandle)
disp_message (WindowHandle, msg, 'image', 12, 12, 'black', 'true')
disp_message (WindowHandle, '智能制造-蒋达', 'window', 50, 50, 'black', 'true')
运行结果:
多骰子点数
基本思路:将各个骰子筛选(除背景)出来,通过循环遍历对每个单骰子进行处理和计数,即在循环中用上述单骰子的操作。
代码实现:
* 获取窗口标识符
dev_get_window (WindowHandle)
read_image (Image3, 'D:/视觉图片/3.多筛子.bmp')
decompose3 (Image3, Image1, Image2, Image31)
*分割筛子
threshold (Image2, Regions, 70, 167)
*填充孔洞,避免丢掉点
fill_up (Regions, RegionFillUp)
connection (RegionFillUp, ConnectedRegions)
*特征筛选
select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 20528.7, 23394.3)
*画框
smallest_rectangle2 (SelectedRegions, Row, Column, Phi, Length1, Length2)
gen_rectangle2_contour_xld (Rectangle, Row, Column, Phi, Length1, Length2)
*计算共有几个筛子
count_obj (SelectedRegions, Number)
dev_update_window ('off') //关闭窗口自动刷新
dev_display (Image3)
dev_set_line_width (2)
dev_display (Rectangle)
for Index1 := 1 to Number by 1
select_obj (SelectedRegions, Obj, Index1)
reduce_domain (Image2, Obj, ImageReduced)
threshold (ImageReduced, Regions1, 0, 74)
fill_up (Regions1, RegionFillUp1)
connection (RegionFillUp1, ConnectedRegions1)
select_shape (ConnectedRegions1, SelectedRegions1, 'area', 'and', 700, 4440)
count_obj (SelectedRegions1, Number1)
area_center (Obj, Area, Row1, Column1)
dev_set_window (WindowHandle)
disp_message (WindowHandle, Number1, 'image', Row1, Column1, 'black', 'true')
stop()
endfor
运行结果:
物块集正反面检测
物块集:
基本思路:其实就是遍历中增加了判断,对某一次循环的图片进行阈值处理和特征处理并计数,通过数量(0 or 1)来判断有无(正反面)。
代码实现:
* Image Acquisition 01: Code generated by Image Acquisition 01
list_files ('D:/物块', ['files','follow_links','recursive'], ImageFiles)
tuple_regexp_select (ImageFiles, ['\\.(tif|tiff|gif|bmp|jpg|jpeg|jp2|png|pcx|pgm|ppm|pbm|xwd|ima|hobj)$','ignore_case'], ImageFiles)
for Index := 0 to |ImageFiles| - 1 by 1
read_image (Image, ImageFiles[Index])
* Image Acquisition 01: Do something
decompose3 (Image, ImageR, ImageG, ImageB)
threshold (ImageR, Regions, 79, 199)
fill_up (Regions, RegionFillUp)
* 打散
connection (RegionFillUp, ConnectedRegions)
select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 230406, 374929)
count_obj (SelectedRegions, Number)
dev_display (Image)
if (Number==0)
* 反面
result:='NG'
color:='red'
else
* 正面
result:='OK'
color:='green'
dev_set_color (color)
area_center (SelectedRegions, Area, Row, Column)
gen_cross_contour_xld (Cross, Row, Column, 100, 0.785398)
smallest_rectangle2 (SelectedRegions, Row1, Column1, Phi, Length1, Length2)
gen_rectangle2_contour_xld (Rectangle, Row1, Column1, Phi, Length1, Length2)
dev_display (Cross)
dev_display (Rectangle)
endif
dev_get_window (WindowHandle)
disp_message (WindowHandle, result, 'image', 60, 60, color, 'true')
stop ()
endfor
运行结果:
正面
反面
铭牌字符识别(水平)
基本思路:先阈值操作,提取出铭牌(除背景,但还是有一些存在),再特征处理将字符都分割出来,因为字符识别需要“白纸黑字”,需要反色处理(黑白翻转),再识别。
代码实现:
read_image (Image1Gongjian, 'D:/视觉图片/1.gongjian.png')
decompose3 (Image1Gongjian, ImageR, ImageG, ImageB)
threshold (ImageR, Regions, 64, 165)
connection (Regions, ConnectedRegions)
* 多特征筛选 面积area 高度width 宽度height
select_shape (ConnectedRegions, SelectedRegions, ['area','width','height'], 'and', [0,34.74,50.14], [5014.33,63.4,120])
*HALCON识别字符要求特征:白纸黑字
count_obj (SelectedRegions, Number)
invert_image (ImageR, ImageInvert) //黑白翻转
*排序区域
sort_region (SelectedRegions, SortedRegions, 'character', 'true', 'row')
*矩形框 平行矩形
smallest_rectangle1 (SortedRegions, Row1, Column1, Row2, Column2)
cr:=(Row1+Row2)/2.0
cc:=(Column1+Column2)/2.0
len1:=abs(Row2-Row1)/2.0
len2:=abs(Column2-Column1)/2.0
phi:=gen_tuple_const(|len2|,0)
gen_rectangle2_contour_xld (box, cr, cc, phi, len2, len1)
*读取字符模型(人工神经网络)
read_ocr_class_mlp ('Document_0-9A-Z_NoRej.omc', OCRHandle)
* 识别字符 参数:字符region 图像 模型句柄
do_ocr_multi_class_mlp (SortedRegions, ImageInvert, OCRHandle, Class, Confidence)
dev_display (Image1Gongjian)
dev_display (box)
dev_get_window (WindowHandle)
set_display_font (WindowHandle, 18, '宋体', 'true', 'false')
disp_message (WindowHandle, '识别结果:'+sum(Class), 'image', 12, 12, 'black', 'true')
clear_ocr_class_mlp (OCRHandle)
运行结果:
铭牌字符识别(倾斜)
基本思路:转HSV颜色模型,矫正旋转(先求弧度再转角度),矫正后就可以开始识别字符(分割字符,特征选择,排序区域、神经网络模型)
代码实现:
dev_clear_window ()
read_image (Image, 'D:/视觉图片/2.jpg')
get_image_size (Image, Width, Height)
dev_open_window (0, 0, Width/4, Height/4, 'black', WindowHandle1)
dev_display (Image)
decompose3 (Image, ImageR, ImageG, ImageB)
*转换HSV颜色模型 色调 饱和度 亮度 rgb->hsv
trans_from_rgb (ImageR, ImageG, ImageB, ImageH, ImageS, ImageV, 'hsv')
* 矫正旋转
threshold (ImageS, Regions, 170, 255)
fill_up (Regions, RegionFillUp)
connection (RegionFillUp, ConnectedRegions)
select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 210000, 220000)
*求最小外接矩形
smallest_rectangle2 (SelectedRegions, Row, Column, Phi, Length1, Length2)
gen_rectangle2_contour_xld (Rectangle, Row, Column, Phi, Length1, Length2)
*弧度转角度
angle := deg(Phi)
*校正倾斜 角度大于0,逆时针转否则顺时针
rotate_image (ImageS, ImageRotate, 180-angle, 'constant')
*识别字符
*分割字符
threshold (ImageRotate, Regions1, 0, 100)
connection (Regions1, ConnectedRegions1)
*多特征筛选 面积高度宽度
select_shape (ConnectedRegions1, SelectedRegions1, ['area','width','height'], 'and', [0,0,31.48], [41666.7,245.37,105.56])
*排序区域
sort_region (SelectedRegions1, SortedRegions, 'character', 'true', 'column')
*读取字符模型(人工神经网络)
read_ocr_class_mlp ('Document_0-9A-Z_NoRej.omc', OCRHandle)
*识别字符 参数:字符region 图像 模型句柄
do_ocr_multi_class_mlp (SortedRegions, ImageRotate, OCRHandle, Class, Confidence)
dev_display (Image)
dev_get_window (WindowHandle)
set_display_font (WindowHandle, 18, 'mono', 'true', 'false')
disp_message (WindowHandle, '识别结果:'+ sum(Class), 'image', 12, 12, 'black', 'true')
clear_ocr_class_mlp (OCRHandle)
运行结果:
铭牌字符集识别(倾斜)
倾斜铭牌字符集:
基本思路:首先要会单个倾斜铭牌字符集的识别,再通过遍历循环和判断展示出来
代码实现:
* Image Acquisition 01: Code generated by Image Acquisition 01
list_files ('D:/铭牌字符图像集', ['files','follow_links','recursive'], ImageFiles)
tuple_regexp_select (ImageFiles, ['\\.(tif|tiff|gif|bmp|jpg|jpeg|jp2|png|pcx|pgm|ppm|pbm|xwd|ima|hobj)$','ignore_case'], ImageFiles)
for Index := 0 to |ImageFiles| - 1 by 1
read_image (Image, ImageFiles[Index])
* Image Acquisition 01: Do something
decompose3 (Image, ImageR, ImageG, ImageB)
*转正
*转换HSV颜色模型 色调 饱和度 亮度 rgb->hsv
trans_from_rgb (ImageR, ImageG, ImageB, ImageH, ImageS, ImageV, 'hsv')
threshold (ImageS, Regions, 170, 255)
fill_up (Regions, RegionFillUp)
connection (RegionFillUp, ConnectedRegions)
select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 200000, 220000)
smallest_rectangle2 (SelectedRegions, Row, Column, Phi, Length1, Length2)
gen_rectangle2_contour_xld (Rectangle, Row, Column, Phi, Length1, Length2)
angle := deg(Phi)
rotate_image (ImageS, ImageRotate, 180-angle, 'constant')
*识别和判断
threshold (ImageRotate, Regions1, 0, 100)
connection (Regions1, ConnectedRegions1)
select_shape (ConnectedRegions1, SelectedRegions1, ['area','width','height'], 'and', [0,0,31.48], [41666.7,245.37,105.56])
count_obj (SelectedRegions1, Number)
sort_region (SelectedRegions1, SortedRegions, 'character', 'true', 'column')
read_ocr_class_mlp ('Document_0-9A-Z_NoRej.omc', OCRHandle)
do_ocr_multi_class_mlp (SortedRegions, ImageRotate, OCRHandle, Class, Confidence)
dev_display (Image)
if (Number==11)
* 有
result:='OK'
color:='green'
dev_set_color (color)
else
* 无
result:='NG'
color:='red'
endif
dev_display (Image)
dev_get_window (WindowHandle)
set_display_font (WindowHandle, 18, 'mono', 'true', 'false')
disp_message (WindowHandle, result, 'image', 12, 12, color, 'true')
disp_message (WindowHandle, '识别结果:'+ sum(Class), 'image', 120, 120, 'black', 'true')
clear_ocr_class_mlp (OCRHandle)
stop()
endfor
运行结果:
有,且输出结果:
无:
粘连目标分割计数(瓶盖)
基本思路:采集图像-分割图像-形态学处理-显示结果
代码实现:
dev_update_on ()
dev_get_window (WindowHandle)
read_image (Image, 'D:/视觉图片/瓶盖.jpg')
rgb1_to_gray (Image, GrayImage)
threshold (GrayImage, Regions, 50, 255)
*去除干扰,毛刺 孤立的小点
opening_circle (Regions, RegionOpening, 3.5)
*腐蚀断开连接
erosion_circle (RegionOpening, RegionErosion, 45.5)
*分割连通域
connection (RegionErosion, ConnectedRegions)
*注意:connection之后使用opening erosion,可能存在空区域,要谨慎(必要时使用select_shape选择)
* erosion_circle (ConnectedRegions, RegionErosion1, 60.5)
*膨胀瓶盖
dilation_circle (ConnectedRegions, RegionDilation, 4.5)
*计数
count_obj (RegionDilation, Number)
*确定中心
area_center (RegionDilation, Area, Row, Column)
*标记中心
dev_set_colored (12)
gen_cross_contour_xld (Cross, Row, Column, 15, 0)
dev_set_draw ('margin')
dev_set_line_width (2)
*设置窗口显示字体 窗口句柄 字号 字体 粗体 斜体
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
dev_clear_window ()
dev_display (Image)
*dev_display (RegionIntersection)
dev_display (Cross)
disp_message (WindowHandle, '数量是:'+Number, 'image', 12, 12, 'black', 'true')
运行结果: