前言:
==========================================================
分类器相对于深度学习来讲是一种古老传统的图片处理技术。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%被占用。
分类器相对于深度学习来讲不吃硬件,所以相对来讲算是轻量级的应用。
==========================================================
本篇是k-nn分类器的首篇,因此讨论图片分割之前,先看看k-nn的基础介绍:
k-NN分类器是一个简单但是功能非常强大的分类器,能够储存所有训练集中的数据和分类, 并且对新的样品也能基于其邻近的训练数据进行分类。 K-近邻( k-nearest neighbors / knn )是一类基于实例 ( instance-based ) 的非参数学习算法。 在这里,输入是由数据集里的 k 个最近的训练实例组成,输出是一个类成员。 一个新对象的分类原则是,它被分到离它最近的 k 个邻居中的多数所在的那个类中。 特别地,k = 1 时,该对象被分到离它最近的邻居所在的类中。 通常,可以赋邻居权值表示邻居对分类的贡献。 例如,可以取对象到每个邻居的距离的倒数作为它的权值。 knn 算法的缺点是,它对数据的局部结构敏感,容易过度拟合数据。
截止本篇为止,已经介绍过了全部的四类常见分类器,把挑选分类器的原则介绍一下:
(1)MLP分类器:分类速度快,但训练速度慢,对内存的要求低,支持多维特征空间, 特别适合需要快速分类并且支持离线训练的场景,但不支持缺陷检测。 (2)SVM分类器:分类检测的速度快,当向量维度低时速度最快,但比MLP分类器慢, 尽管其训练速度比MLP分类器快得多。其对内存的占用取决于样本的数量,如果有大量的样本, 如字符库这样的样本需要训练,分类器会变得十分庞大。 (3)GMM分类器:训练速度和检测速度都很快,特别是类别较少时速度非常快, 支持异常检测,但不适用于高维度特征检测。 (4)kNN分类器:训练速度非常快,分类速度比MLP分类器慢, 适合缺陷检测和多维度特征分类,但对内存的需求较高。
之前我们在讨论GMM和SVM时都见过图片分割的例子,下面是K-NN分类器的例子。
GMM图片分割的例子:http://www.skcircle.com/?id=1622
SVM图片分割的例子: http://www.skcircle.com/?id=1635
下面这个示例程序演示了如何使用k-NN分类器分割RGB图像。
分类器用四种不同的颜色进行训练。请注意,得到的分类直观上是正确的。
然而,也可以看到,四种颜色之外的颜色会被分到其中一个颜色分类中,而且还具有很高的置信度。
在这幅图中,船舷上的黄色油漆、船顶灯光上的绿色以及船门以很高置信度信分配到了四个级别中的一个。
首先划四个区域做为分类样本。
训练并分割的不行,因为 船舷上的黄色油漆、顶灯上的绿色和门无意中被分配到四个训练类中的一个。
由于船舷上的黄色油漆、顶灯上的绿色和门无意中被分配到四个训练类中的一个,
我们将构造一个显式拒绝类,其中包含每个不需要的颜色的样本,并使用拒绝类重新训练分类器。
这个拒绝类就是下图中的黄色框区域。
更新了拒绝类并重新训练后的结果就正确了。
dev_update_off () dev_close_window () dev_open_window (0, 0, 735, 485, 'black', WindowHandle) set_display_font (WindowHandle, 14, 'mono', 'true', 'false') dev_set_draw ('margin') dev_set_colored (6) dev_set_line_width (3) read_image (Image, 'patras') dev_display (Image) Color := ['indian red','cornflower blue','white','black','yellow'] * 创建包含四个类的训练样本的区域 gen_rectangle1 (Sea, 10, 10, 120, 270) gen_rectangle2 (Deck, [170,400], [350,375], [-0.56,-0.75], [64,104], [26,11]) union1 (Deck, Deck) gen_rectangle1 (Walls, 355, 623, 420, 702) gen_rectangle2 (Chimney, 286, 623, -0.56, 64, 33) concat_obj (Sea, Deck, Classes) concat_obj (Classes, Walls, Classes) concat_obj (Classes, Chimney, Classes) dev_set_color (Color[0]) dev_display (Deck) dev_set_color (Color[1]) dev_display (Sea) dev_set_color (Color[2]) dev_display (Walls) dev_set_color (Color[3]) dev_display (Chimney) Message := 'Training regions for the color classifier' disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true') disp_continue_message (WindowHandle, 'black', 'true') stop () * 创建分类器并添加样本 create_class_knn (3, KNNHandle) add_samples_image_class_knn (Image, Classes, KNNHandle) dev_display (Image) Message := 'Training ...' disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true') * 训练 train_class_knn (KNNHandle, [], []) Message := Message + ' ready.' Message[1] := 'Segment image using the classifier ...' disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true') * 分割图片(也是分类图片) classify_image_class_knn (Image, ClassRegions, DistanceImage, KNNHandle, 255.0 * 255.0) region_to_mean (ClassRegions, Image, ImageClass) dev_display (ImageClass) Message[1] := Message[1] + ' ready.' disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true') disp_continue_message (WindowHandle, 'black', 'true') stop () *由于船舷上的黄色油漆、顶灯上的绿色和门无意中被分配到四个训练类中的一个, *我们将构造一个显式拒绝类,其中包含每个不需要的颜色的样本,并使用拒绝类重新训练分类器 gen_rectangle2 (Rejection, [193,66,261], [235,332,328], [-0.32,-1.45,-1.51], [33,34,60], [4,3,3]) union1 (Rejection, Rejection) concat_obj (Classes, Rejection, Classes) dev_display (Image) dev_set_color (Color[0]) dev_display (Deck) dev_set_color (Color[1]) dev_display (Sea) dev_set_color (Color[2]) dev_display (Walls) dev_set_color (Color[3]) dev_display (Chimney) dev_set_color (Color[4]) dev_display (Rejection) disp_message (WindowHandle, 'Add a rejection class to improve the robustness of the classifier', 'window', 12, 12, 'black', 'true') disp_continue_message (WindowHandle, 'black', 'true') stop () dev_display (Image) * 创建分类器并添加样本 create_class_knn (3, KNNHandle) add_samples_image_class_knn (Image, Classes, KNNHandle) * 分割图片(也是分类图片) Message := 'Training the classifier with rejection class...' disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true') train_class_knn (KNNHandle, [], []) Message := Message + ' ready.' Message[1] := 'Segment image using the classifier ...' disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true') * 分割图片(也是分类图片) classify_image_class_knn (Image, ClassRegionsNotRejected, DistanceImage1, KNNHandle, 255.0 * 255.0) * 选择除拒绝类以外的所有类 copy_obj (ClassRegionsNotRejected, ClassRegionsNotRejected, 1, 4) * 注意,平均图像中的黑色区域对应于被拒绝的像素 region_to_mean (ClassRegionsNotRejected, Image, ImageClassNotRejected) dev_display (ImageClassNotRejected) Message[1] := Message[1] + ' ready.' disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
---------------------
作者:hackpig
来源:www.skcircle.com
版权声明:本文为博主原创文章,转载请附上博文链接!

