前言:
==========================================================
分类器相对于深度学习来讲是一种古老传统的图片处理技术。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的时候,也有这个对2D数据进行分类的例子,参见:http://www.skcircle.com/?id=1627
下面这个示例程序演示了如何使用支持向量机(SVM)对二维数据进行分类。
使用二维数据是因为它可以很容易地可视化为区域和图像。
该示例使用了三个基本重叠的类。
它从每个类中生成样本,并用样本训练支持向量机。然后,利用支持向量机对完整的二维特征空间进行分类。
从结果可以看出,支持向量机将特征空间中的每个点分类为三类中的一类。因此,即使在训练样本的凸包之外很远的点也将被分配给三个类中的一个。
这是支持向量机分类器的一个普遍性质,有时需要训练一个显式拒绝类。
此外,这个例子程序表明,参数Nu需要仔细选择,如果类重叠,它设置的效果应该大于不可避免的错误点。
首先随机生成的3个类,它们有一部分是重叠的。
当设置Nu=0.01的时候,我们看到分类的结果明显是错误的。
当Nu=0.18的时候,是过滤拟合的,结果仍然不理想。
当Nu=0.25的时候,取得了很好的分类效果。
dev_close_window () dev_open_window (0, 0, 600, 600, 'black', WindowHandle) dev_set_part (0, 0, 199, 199) set_display_font (WindowHandle, 16, 'mono', 'true', 'false') dev_update_off () * 生成三个重叠的椭圆作为提取训练样本的区域 gen_ellipse (RegionClass1, 60, 60, rad(-45), 60, 40) gen_ellipse (RegionClass2, 70, 130, rad(-145), 70, 30) gen_ellipse (RegionClass3, 140, 100, rad(100), 55, 40) * Sample feature points from each region by segmenting a different noisy image * for each region and intersecting the segmented region with the class region. gen_image_const (Image, 'byte', 200, 200) add_noise_white (Image, ImageNoise1, 60) add_noise_white (Image, ImageNoise2, 60) add_noise_white (Image, ImageNoise3, 60) threshold (ImageNoise1, RegionNoise1, 40, 255) threshold (ImageNoise2, RegionNoise2, 40, 255) threshold (ImageNoise3, RegionNoise3, 40, 255) intersection (RegionClass1, RegionNoise1, SamplesClass1) intersection (RegionClass2, RegionNoise2, SamplesClass2) intersection (RegionClass3, RegionNoise3, SamplesClass3) * 显示每个类的示例. dev_clear_window () dev_set_color ('red') dev_display (SamplesClass1) dev_set_color ('green') dev_display (SamplesClass2) dev_set_color ('blue') dev_display (SamplesClass3) Message := 'Training samples of the 3 classes' disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true') disp_continue_message (WindowHandle, 'black', 'true') stop () classify_2d_feature_space (SamplesClass1, SamplesClass2, SamplesClass3, RegionClass1, RegionClass2, RegionClass3, WindowHandle, 'rbf', 0.05, 0.01) Message := 'Nu = 0.01: Wrong classification' disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true') disp_continue_message (WindowHandle, 'black', 'true') stop () classify_2d_feature_space (SamplesClass1, SamplesClass2, SamplesClass3, RegionClass1, RegionClass2, RegionClass3, WindowHandle, 'rbf', 0.05, 0.18) Message := 'Nu = 0.18: Overfitting' disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true') disp_continue_message (WindowHandle, 'black', 'true') stop () classify_2d_feature_space (SamplesClass1, SamplesClass2, SamplesClass3, RegionClass1, RegionClass2, RegionClass3, WindowHandle, 'rbf', 0.05, 0.25) Message := 'Nu = 0.25: Good generalization' disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
函数classify_2d_feature_space的代码:
* 读取样本点并将其作为训练样本添加到支持向量机中. concat_obj (SamplesClass1, SamplesClass2, Samples) concat_obj (Samples, SamplesClass3, Samples) * 对Nu尝试不同的值是有意义的。 *对于太小的值(约0.2,取决于随机样本的分布),类区域的边界将变得非常不平滑, *表明对于所选Nu,类重叠过多,因此SVM需要对训练数据进行过度拟合。 *根据KernelType和KernelParam的选择,类边界的形状会有很大的不同。 *因此,可以看出,要获得最佳平滑的类边界,最好对类重叠的百分比进行估计。 create_class_svm (2, KernelType, KernelParam, Nu, 3, 'one-versus-one', 'normalization', 0, SVMHandle) for Class := 0 to 2 by 1 select_obj (Samples, SamplesClass, Class + 1) get_region_points (SamplesClass, Rows, Cols) for J := 0 to |Rows| - 1 by 1 add_sample_class_svm (SVMHandle, real([Rows[J],Cols[J]]), Class) endfor endfor get_sample_num_class_svm (SVMHandle, NumSamples) *训练SVM. train_class_svm (SVMHandle, 0.001, 'default') * 现在对二维特征空间中的所有点进行分类,并将分类存储在类别标签图像中。 gen_image_const (LabelClass, 'byte', 200, 200) for R := 0 to 199 by 1 for C := 0 to 199 by 1 Features := real([R,C]) classify_class_svm (SVMHandle, Features, 1, Class) set_grayval (LabelClass, R, C, Class) endfor endfor label_to_region (LabelClass, Classes) * 显示特征空间中类的每个点. dev_set_colored (3) dev_display (Classes) dev_set_color ('white') dev_set_draw ('margin') dev_display (RegionClass1) dev_display (RegionClass2) dev_display (RegionClass3) dev_set_draw ('fill') set_tposition (WindowHandle, 5, 5) write_string (WindowHandle, 'Class regions') return ()
其实有关Nu的设置,在上一篇介绍新奇检测的例子中已经讲的比较详细了,http://www.skcircle.com/?id=1645
本篇的侧重点则在于介绍类的过渡拟合问题。
---------------------
作者:hackpig
来源:www.skcircle.com
版权声明:本文为博主原创文章,转载请附上博文链接!

