
* This example program shows how to classify different
* metal parts using a general MLP classification
*
dev_update_off ()
dev_close_window ()
dev_open_window (0, 0, 640, 480, 'black', WindowHandle)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
dev_set_colored (6)
dev_set_draw ('margin')
dev_set_line_width (3)
*
* Create an MLP classifier
create_class_mlp (6, 5, 3, 'softmax', 'normalization', 3, 42, MLPHandle)
*
* Add training samples to the classifier
FileNames := ['nuts_01','nuts_02','nuts_03','washers_01','washers_02','washers_03','retainers_01','retainers_02','retainers_03']
Classes := [0,0,0,1,1,1,2,2,2]
for J := 0 to |FileNames| - 1 by 1
read_image (Image, 'rings/' + FileNames[J])
dev_display (Image)
dev_set_colored (6)
segment (Image, Objects)
dev_display (Objects)
dev_set_color ('black')
disp_message (WindowHandle, 'Add Sample ' + J + ', Class Index ' + Classes[J], 'window', 10, 10, 'black', 'true')
add_samples (Objects, MLPHandle, Classes[J])
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
endfor
*
* Train the classifier with the training samples
dev_clear_window ()
dev_set_color ('black')
disp_message (WindowHandle, 'Training...', 'window', 10, 10, 'black', 'true')
train_class_mlp (MLPHandle, 200, 1, 0.01, Error, ErrorLog)
clear_samples_class_mlp (MLPHandle)
disp_message (WindowHandle, 'Training... completed', 'window', 10, 10, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
*
* Classify objects
dev_set_draw ('fill')
for J := 1 to 4 by 1
read_image (Image, 'rings/mixed_' + J$'02d')
dev_display (Image)
dev_set_color ('black')
dev_set_draw ('margin')
disp_message (WindowHandle, 'Classifiy Image' + J, 'window', 10, 10, 'black', 'true')
segment (Image, Objects)
classify (Objects, MLPHandle, Classes)
disp_obj_class (Objects, Classes)
if (J < 4)
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
endif
endfor
stop ()
*
* Clear the classifier from memory
clear_class_mlp (MLPHandle)每一张图像中包含数个属于同一类别的金属件。对于特定图像的类的索引被存储在元组Classes中。在这个案例中,9张图像是可行的(见下图)。在前3张图像的物体属于类别0,接下来3张图像中物体属于类别1,最后3张图像的物体属于类别2。
FileNames := ['nuts_01','nuts_02','nuts_03','washers_01','washers_02','washers_03','retainers_01','retainers_02','retainers_03'] Classes := [0,0,0,1,1,1,2,2,2]
现在,每一张训练图像被用两个程序segment和add_samples去处理。
for J := 0 to |FileNames| - 1 by 1
read_image (Image, 'rings/' + FileNames[J])
dev_display (Image)
dev_set_colored (6)
segment (Image, Objects)
dev_display (Objects)
dev_set_color ('black')
disp_message (WindowHandle, 'Add Sample ' + J + ', Class Index ' + Classes[J], 'window', 10, 10, 'black', 'true')
add_samples (Objects, MLPHandle, Classes[J])
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
endfor
训练图像
程序segment用简单的blob分析分割并分离包含在图像中的物体。
binary_threshold (Image, Region, 'max_separability', 'dark', UsedThreshold) connection (Region, ConnectedRegions) fill_up (ConnectedRegions, Regions) return ()
对于每一个区域,程序add_samples用程序get_features决定一个特征向量。特征向量和已知类别索引建立了训练样本,其用算子add_sample_class_mlp添加到分类器中。
count_obj (Regions, Number) for J := 1 to Number by 1 select_obj (Regions, Region, J) get_features (Region, Features) add_sample_class_mlp (MLPHandle, Features, Class) endfor return ()
在程序get_features中被提取的特征是区域特征,特别是区域的两个圆度和4个矩(用算子moments-region_central_invar)。
select_obj (Region, SingleRegion, 1) circularity (SingleRegion, Circularity) roundness (SingleRegion, Distance, Sigma, Roundness, Sides) moments_region_central_invar (SingleRegion, PSI1, PSI2, PSI3, PSI4) Features := [Circularity,Roundness,PSI1,PSI2,PSI3,PSI4] return ()
在添加了所有可行的样本后,训练器用train_class_mlp所训练,用clear_samples_class_mlp将样本从内存中移除。
train_class_mlp (MLPHandle, 200, 1, 0.01, Error, ErrorLog) clear_samples_class_mlp (MLPHandle)
现在,具有不知物体的图像被探索。物体的分割和它们特征的提取利用和训练图像相同的程序(segment和get_features)来实现。但是,这时一个特征向量的类别还不知道,必须用分类来决定。这样,相对于程序add_samples,在程序classify中,被提取的特征向量被用来作为算子classify_class_mlp的输入,而不是用add_sample_class_mlp。结果就是类的索引,其最适合特定区域提取的特征向量。
for J := 1 to 4 by 1
read_image (Image, 'rings/mixed_' + J$'02d')
dev_display (Image)
dev_set_color ('black')
dev_set_draw ('margin')
disp_message (WindowHandle, 'Classifiy Image' + J, 'window', 10, 10, 'black', 'true')
segment (Image, Objects)
classify (Objects, MLPHandle, Classes)
disp_obj_class (Objects, Classes)
if (J < 4)
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
endif
endfor对于结果的一个视觉查看,程序disp_obj_class用特定颜色(依靠区域所属的类别)展示了每一个区域。

根据它们的形状来分类金属件:(左)金属件的图像,(右)被分为3类的金属件(被用不同的灰度值所描述)
详细代码请参考halcon例子:classify_metal_parts.hdev


少有人走的路


















