* 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

