缺陷检测——机器学习
写在前面
这篇文章只是讲解了一些非常简单的halcon里机器学习的案例,所以只能初步给大家呈现一下机器学习的基本步骤。不要试图用很短的时间或者很少的精力就能学好机器学习,这是一个漫长的过程,希望我们能一起努力。
halcon提供了3套机器学习的算子,它们都可以用来检测缺陷,接下来就一次介绍它们
1. create_ocr_class_mlp
1.1 ocr识别就只能识别ocr吗?
- halcon在ocr识别中提供了一套算子,支持我们自己去训练模型,然后再拿训练好的模型来识别字符,我在前面的文章中写过,感兴趣的小伙伴可以去查看:
https://editor.csdn.net/md/?articleId=115208338 - 那么问题来了,识别ocr的算子真的就只能识别ocr吗?当然不是了,它也可以用来做一些其他的一些简单的分类检测。其实不难理解,ocr识别时,我们训练模型,也是训练这个字符的一些特征,再手动的将这些特征和一些标签联系起来,下一次找到特征,就输出特征对应的标签。那么工件也有特征,把工件的特征放到训练模型中,再打上工件的标签,我们不就可以拿这个模型做工件的分类了吗?
- 下面我们就看一个例子吧:
1.2 简单的图形分类
halcon案例:classify_metal_parts_ocr.hdev
dev_update_off ()
* 案例: classify_metal_parts_ocr.hdev
* 混料检测 (多层神经感知) ocr的一套算子 分类
* 创建分类器:特征的选择/样本量/特征向量预处理类型
create_ocr_class_mlp (110, 110, 'constant', 'moments_central',\
['circle','hexagon','polygon'], \
10, 'normalization', 10, 42, OCRHandle)
* 获得分类器使用的特征
get_params_ocr_class_mlp (OCRHandle, WidthCharacter, HeightCharacter, Interpolation, \
Features, Characters, NumHidden, Preprocessing, NumComponents)
* 产生trf文件(样本文件)
FileNames := ['./nuts_01','./nuts_02','./nuts_03',\
'./washers_01','./washers_02','./washers_03',\
'./retainers_01','./retainers_02','./retainers_03']
ClassNames := ['hexagon','hexagon','hexagon','circle','circle','circle','polygon','polygon','polygon']
file_exists ('./train_ocr.trf', FileExists)
if(FileExists)
delete_file ('./train_ocr.trf')
endif
for Index := 0 to |FileNames|-1 by 1
read_image (Image, FileNames[Index])
* 这个函数能够获得特征的具体值
* get_features_ocr_class_mlp (Image, OCRHandle, 'true', Features1)
threshold (Image, Region, 6, 114)
fill_up (Region, RegionFillUp)
connection (RegionFillUp, ConnectedRegions)
count_obj (ConnectedRegions, Number)
for I := 0 to Number-1 by 1
select_obj (ConnectedRegions, ObjectSelected, I+1)
append_ocr_trainf (ObjectSelected, Image, \
ClassNames[Index], './train_ocr.trf')
endfor
dev_display (Image)
endfor
* 3. 训练
trainf_ocr_class_mlp (OCRHandle, './train_ocr', 200, 1, 0.01, Error, ErrorLog)
file_exists ('./train_ocr.omc', FileExists)
if(FileExists)
delete_file ('./train_ocr.omc')
endif
write_ocr_class_mlp (OCRHandle, './train_ocr.omc')
read_ocr_class_mlp ('./train_ocr.omc', OCRHandle1)
* 4. 识别
Text:=''
dev_get_window (WindowHandle)
set_display_font (WindowHandle, 20, 'mono', 'true', 'false')
for J := 1 to 4 by 1
read_image (Image, 'rings/mixed_' + J$'02d')
threshold (Image, Regions, 0, 159)
fill_up (Regions, RegionFillUp1)
connection (RegionFillUp1, ConnectedRegions1)
count_obj (ConnectedRegions1, Number1)
dev_display (Image)
for Index1 := 1 to Number1 by 1
select_obj (ConnectedRegions1, ObjectSelected1, Index1)
do_ocr_single_class_mlp (ObjectSelected1, Image, OCRHandle1, 1, Class, Confidence)
area_center (ObjectSelected1, Area, Row, Column)
if(Class == 'hexagon')
dev_set_color ('red')
elseif (Class == 'circle')
dev_set_color ('blue')
elseif (Class == 'polygon')
dev_set_color ('green')
endif
dev_display (ObjectSelected1)
endfor
stop()
endfor
dev_update_on ()
2. create_class_mlp
2.1 将区域作为训练对象
- halcon为我们提供的第二套算子是以区域作为神经感知模型的训练对象的。以区域作为训练对象,最终返回的结果自然也是区域,我们当然可以获得这些区域的特征,比如面积、中心点坐标等等。
- 这个返回结果有时候是非常有用的,比如需要抓取的时候,直接将区域的中心坐标转成世界坐标,发送给机器人就可以了。(这里涉及到了手眼标定)
2.2 基本流程和算子
- 准备区域:
首先要准备好你想要训练的区域,区域个数至少是两个,一个是前景(目标物),一个是背景。如果你的背景明暗变化比较大,可以使用多个区域联合成一个区域,(联合后的区域还是看成一个区域),或者增加区域的个数,比如训练3个、4个区域; - 创建mlp模型
create_class_mlp( : : NumInput, NumHidden, NumOutput, OutputFunction, Preprocessing, NumComponents, RandSeed : MLPHandle)- **NumInput:**图像通道数
- **NumHidden:**中间隐藏神经元的个数
- **NumOutput:**输出特征数量,你准备了几个训练区域,就输出几个区域就行了
- **OutputFunction:**激活函数
- **Preprocessing:**预处理类型,一般选择归一化
- **NumComponents:**变换后的特征数量(对于Preprocessing ='none’和Preprocessing ='normalization’忽略)
- **RandSeed:**随机种子
- **MLPHandle:**模型句柄
- 添加特征到模型中
add_samples_image_class_mlp(Image, ClassRegions : : MLPHandle : )- **ClassRegions:**特征(区域)
- 训练模型
train_class_mlp( : : MLPHandle, MaxIterations, WeightTolerance, ErrorTolerance : Error, ErrorLog)- **MaxIterations:**迭代次数
- **WeightTolerance:**优化算法的两次迭代之间MLP权重差异的阈值
- **ErrorTolerance:**优化算法的两次迭代之间的训练数据上MLP的平均误差之差的阈值
- Error: MLP在训练数据上的平均误差。
- 分类
classify_image_class_mlp(Image : ClassRegions : MLPHandle, RejectionThreshold : )
2.3 看一个案例
如下图:想知道工件的个数,你要如何做呢?
这里我们采用了多层神经感知的方法:下面就是halcon的实现代码:
* 这个案例是使用mlp(多层神经感知)计数
read_image (Image, './6.jpg')
//1 前景
gen_rectangle1 (ROI_0, 890.924, 277.009, 933.712, 325.132)
gen_rectangle1 (TMP_Region, 1141.95, 812.778, 1176.18, 889.775)
union2 (ROI_0, TMP_Region, ROI_0)
gen_rectangle1 (TMP_Region, 762.559, 1172.1, 808.2, 1207.39)
union2 (ROI_0, TMP_Region, Block)
//2 背景
gen_rectangle1 (ROI_0, 101.628, 225.616, 249.813, 785.902)
gen_rectangle1 (TMP_Region, 750.439, 17.5092, 1467.34, 113.558)
union2 (ROI_0, TMP_Region, ROI_0)
gen_rectangle1 (TMP_Region, 2144.18, 969.996, 2252.32, 1402.22)
union2 (ROI_0, TMP_Region, Background)
//3 缝隙(我发现缝隙会影响最终的结果,导致两个物料连结到一起,无法通过腐蚀将它们分开)
// 所以我将缝隙也放入了训练模型当中进行了训练
gen_rectangle1 (ROI_2, 1519.43, 1704.42, 1564.84, 1713.5)
gen_rectangle2 (ROI_3, 958.303, 1261.95, rad(-128.176), 8.97139, 2.00968)
gen_rectangle2 (TMP_Region, 1299.65, 1488.25, rad(45.4293), 15.5433, 2.85932)
union2 (ROI_3, TMP_Region, ROI_3)
concat_obj (Block, Background, ObjectsConcat)
concat_obj (ObjectsConcat, ROI_2, ObjectsConcat)
concat_obj (ObjectsConcat, ROI_3, ObjectsConcat)
* 创建mlp模型
create_class_mlp (3, 10, 4, 'softmax', 'normalization', 10, 42, MLPHandle)//第一个参数是图像通道数
* 添加特征到模型中(这里添加的是4个区域对象)
add_samples_image_class_mlp (Image, ObjectsConcat, MLPHandle)
* 训练模型
train_class_mlp (MLPHandle, 200, 1, 0.01, Error, ErrorLog)
* 分类
classify_image_class_mlp (Image, ClassRegions, MLPHandle, 0.5)
* 进一步处理得到目标数量
select_obj (ClassRegions, ObjectSelected, 1)//选择前景(目标物)
erosion_circle (ObjectSelected, RegionErosion, 8.5)//腐蚀
connection (RegionErosion, ConnectedRegions)//分割
select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 1088.84, 10000)//筛选
count_obj (SelectedRegions, Number)//计数
* 显示
dev_display (Image)
dev_display (SelectedRegions)
dev_get_window (WindowHandle)
set_display_font (WindowHandle, 26, 'mono', 'true', 'false')
disp_message (WindowHandle, Number, 'image', 12, 12, 'black', 'true')
这篇文章就先讲到这里,其他的方法和案例,我们下次再说吧。
对我介绍的内容感兴趣的小伙伴可以关注我,我会持续发布相关的文章。如果觉得我写的还不错的,就帮我点个赞吧!