前言:
==========================================================
分类器相对于深度学习来讲是一种古老传统的图片处理技术。halcon中常见的有四类分类器:
MLP(多层神经网络neural Nets)
SVM(支持向量机)
K-NN(K-最邻近)
GMM(高斯混合类型)
分类器的应用领域主要是下面这些:
image segmentation 图像分割
object recognition 对象识别
quality control 质量控制
novelty detection 缺陷检测
optical character recognition(OCR) 光学字符识别
勇哥第一次见到分类器的视觉项目是锂电池的极片缺陷检测,效果还不错。
这两年深度学习火起来后,发现深度学习完成上面所说的领域的应用更容易,效果也更好。
但深度学习对硬件要求太高,你把IPC加装个一百多W的显卡很多时候是不现实的。
如果你用cpu来跑,会发现速度乎快乎慢,cpu全部内核会100%被占用。
分类器相对于深度学习来讲不吃硬件,所以相对来讲算是轻量级的应用。
==========================================================
GMM是高斯混合模形分类, 它是按贝叶斯决策规则进行工作的分类器。
GMM的一些特点如下:
GMM仅仅对于低维的特征向量是可行的(大约差不多15个特征), 因此HALCON仅仅用GMM来对一般特征进行分类和图像分割,而不是OCR。 典型的应用就是图像分割和异常检测。异常检测对于GMM是特殊的。 其意味着不属于训练类之一的特征向量将被拒绝。
我们先来解读一个官方的例子,它使用GMM识别两种不同的水果。
A
柠檬和桔子。
使用的特征是两者的Area和circularity,即region的属性“面积”和“圆度”
有关region的这些常见属性可以参考:http://www.skcircle.com/?id=1617
源码:
从源码上来看,GMM的用法跟PLM基本方式是一致的。算子的名命套路也保持了一致。
PLM的代码稍加修改可以轻松改为GMM的。
read_image (Image, 'color/citrus_fruits_01') get_image_pointer1 (Image, Pointer, Type, Width, Height) dev_close_window () dev_open_window (0, 0, Width, Height, 'white', WindowHandle) set_display_font (WindowHandle, 12, 'mono', 'true', 'false') dev_set_draw ('margin') dev_set_line_width (2) dev_display (Image) dev_update_window ('off') dev_update_pc ('off') dev_update_var ('off') * FeaturesArea := [] FeaturesCircularity := [] ClassName := ['orange','lemon'] * create_class_gmm (2, 2, 1, 'spherical', 'normalization', 10, 42, GMMHandle) * * 增加训练样本,共四张图片,6个桔子,6个柠檬 for I := 1 to 4 by 1 read_image (Image, 'color/citrus_fruits_' + I$'.2d') dev_display (Image) * 'Add Samples' get_regions (Image, SelectedRegions) dev_display (SelectedRegions) count_obj (SelectedRegions, NumberObjects) for J := 1 to NumberObjects by 1 select_obj (SelectedRegions, ObjectSelected, J) get_features (ObjectSelected, WindowHandle, Circularity, Area, RowRegionCenter, ColumnRegionCenter) FeaturesArea := [FeaturesArea,Area] FeaturesCircularity := [FeaturesCircularity,Circularity] FeatureVector := real([Circularity,Area]) if (I <= 2) add_sample_class_gmm (GMMHandle, FeatureVector, 0, 0) disp_message (WindowHandle, 'Add to Class:' + ClassName[0], 'window', RowRegionCenter, ColumnRegionCenter - 100, 'black', 'true') else add_sample_class_gmm (GMMHandle, FeatureVector, 1, 0) disp_message (WindowHandle, 'Add to Class:' + ClassName[1], 'window', RowRegionCenter, ColumnRegionCenter - 100, 'black', 'true') endif endfor disp_continue_message (WindowHandle, 'black', 'true') stop () endfor dev_clear_window () * * 绘制特征图表 visualize_2D_feature_space (Cross, Height, Width, WindowHandle, FeaturesArea[0:5],\ FeaturesCircularity[0:5], 'dim gray', 18) * 'oranges', 40, 440 visualize_2D_feature_space (Cross, Height, Width, WindowHandle, FeaturesArea[6:11],\ FeaturesCircularity[6:11], 'light gray', 18) * 'lemons', 70, 440 disp_continue_message (WindowHandle, 'black', 'true') stop () * 训练 train_class_gmm (GMMHandle, 100, 0.001, 'training', 0.0001, Centers, Iter) for I := 1 to 15 by 1 read_image (Image, 'color/citrus_fruits_' + I$'.2d') dev_display (Image) * 'Classify Image', 10, 10 get_regions (Image, SelectedRegions) dev_display (SelectedRegions) count_obj (SelectedRegions, NumberObjects) for J := 1 to NumberObjects by 1 select_obj (SelectedRegions, ObjectSelected, J) get_features (ObjectSelected, WindowHandle, Circularity, Area, RowRegionCenter, ColumnRegionCenter) FeaturesArea := [FeaturesArea,Area] FeaturesCircularity := [FeaturesCircularity,Circularity] FeatureVector := real([Circularity,Area]) classify_class_gmm (GMMHandle, FeatureVector, 1, ClassID, ClassProb, Density, KSigmaProb) disp_message (WindowHandle, 'Class: ' + ClassName[ClassID], 'window', RowRegionCenter, ColumnRegionCenter - 100, 'black', 'true') disp_message (WindowHandle, 'KSigmaProb: ' + KSigmaProb, 'window', RowRegionCenter + 30, ColumnRegionCenter - 100, 'black', 'true') endfor if (I != 15) disp_continue_message (WindowHandle, 'black', 'true') endif stop () endfor clear_class_gmm (GMMHandle)
函数visualize_2D_feature_space代码如下:
* * Create a coordinate system and draw its axes: dev_set_color ('black') OriginOfGraph := [Height - 0.1 * Height,0.1 * Width] disp_arrow (WindowID, OriginOfGraph[0], OriginOfGraph[1], OriginOfGraph[0], Width - 0.2 * Width, 2) disp_arrow (WindowID, OriginOfGraph[0], OriginOfGraph[1], 0.1 * Height, OriginOfGraph[1], 2) set_tposition (WindowID, OriginOfGraph[0], Width - 0.2 * Width) write_string (WindowID, 'Area') set_tposition (WindowID, 0.07 * Height, OriginOfGraph[1]) write_string (WindowID, 'Circularity') dev_set_color (ColorFeatureVector) * * Define the extent of the graph in image coordinates, the * approximated ranges between the minimum and maximum * feature values, and calculate the resulting * scale factor for each feature axis: ExtentOfGraph := Height - 0.3 * Height RangeC := 0.5 RangeA := 24000 ScaleC := ExtentOfGraph / RangeC ScaleA := ExtentOfGraph / RangeA * * Set the approximated minimum values of the features, which * are the feature values at the origin of the graph: MinC := 0.5 MinA := 20000 * * Get the individual feature vectors in image coordinates * and visualize them: NumberFeatureVectors := |FeaturesA| for I := 0 to NumberFeatureVectors - 1 by 1 * * Get the distance of the feature i from * the origin of the graph in pixels: DiffC := ScaleC * (FeaturesC[I] - MinC) DiffA := ScaleA * (FeaturesA[I] - MinA) * * Get the row and column of the feature * vector in image coordinates: RowFeature := OriginOfGraph[0] - DiffC ColumnFeature := OriginOfGraph[1] + DiffA * * Generate a cross contour for the feature vector i: gen_cross_contour_xld (Cross, RowFeature, ColumnFeature, CrossSize, 0.785398) dev_display (Cross) endfor return ()
代码中visualize_2D_feature_space函数用来绘制特征值的图表,它很形象的表示出分类的效果。
下面这段代码是第0到第5个特征的分布图,它是6个桔子的特征,使用灰度的点表示。
visualize_2D_feature_space (Cross, Height, Width, WindowHandle, FeaturesArea[0:5],\ FeaturesCircularity[0:5], 'dim gray', 18)
下面的代码显示的是第6到11个特征分布图,它是6个柠檬的特征,用淡灰色点表示。
visualize_2D_feature_space (Cross, Height, Width, WindowHandle, FeaturesArea[6:11],\ FeaturesCircularity[6:11], 'light gray', 18)
从这张图我们看到,灰色的6个点应该是桔子的特征点,因为桔子比柠檬更圆。
下面的6个浅灰色的点是柠檬的,它的面积和圆度都比桔子要小。
中间有一个浅灰的点意味着有一个柠檬,它的面积是所有柠檬中最大的,而且最圆。
左上那个灰色的点,表示有一个桔子是所有桔子中面积最小的,而且最不圆的。
我把四张训练图截出来,看看是不是勇哥分析的那样。
第一张图:
第二张:
第三张:
第四张:
从上面的特征分布图上看,灰色与浅色的特征被拉得越开越好,这样分类就会稳定可靠。
中间那个浅灰的点的特征则稍有不佳,如果再靠上一点,则可能分类到桔子类别上去了。
---------------------
作者:hackpig
来源:www.skcircle.com
版权声明:本文为博主原创文章,转载请附上博文链接!

