前言:
==========================================================
分类器相对于深度学习来讲是一种古老传统的图片处理技术。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%被占用。
分类器相对于深度学习来讲不吃硬件,所以相对来讲算是轻量级的应用。
==========================================================
LUT的说明如下:
使用算子create_class_lut_gmm生成查找表(LUT)。由于GMM的第种可能的响应都被存储在LUT中, 因此不再需要对图片的每个像素点进行评估,因此分类速度得以极大的提高。 使用LUT的GMM分类则不使用算子classify_image_class_gmm, 而是使用 classify_image_class_lut。 由于LUT的离散化,LUT分类classify_image_class_lut的精度可能会低于使用 classify_image_class_gmm进行分类的精度
GMM的LUT方式并不是GMM专用的,实际上在MPL,SVM都有LUT。
来看看一个例程:
它使用LUT来分割图片。例程在训练的时候通过一张样图已经把5个分类特征取到,然后直接用算子create_class_lut_gmm创建查找表LUT。接下来在图片分类中使用一次classify_image_class_lut就可以直接取得“细分类”,它是一个处理结果的region数组。
待分类图片是随机在视野内混排的,因此算子classify_image_class_lut一次取得整张图片的处理结果,是非常高效率的。
勇哥把例程标注出3个步骤:
(1)创建GMM,添加样本,进行训练
这一步是传统的用法,和上一篇所讲没啥子区别。
(2)创建GMM LUT分类器
在这一步里,算子create_class_lut_gmm 创建查找表(LUT),它有一组控制参数,详细见贴子:
http://www.skcircle.com/?id=1621
(3)使用LUT进行分类
算子classify_image_class_lut,取得的结果是一个region数组,按索引即可取出分类结果。
* In this example five different color fuses are segmented with * a look-up table classifier (LUT) based on a Gaussian Mixture * Model (GMM). * dev_update_off () dev_close_window () dev_open_window (0, 0, 800, 600, 'white', WindowHandle) dev_set_draw ('margin') ImageRootName := 'color/color_fuses_0' FuseTypes := [5,10,15,20,30] FuseColors := ['Orange','Red','Blue','Yellow','Green'] FuseHighlight := ['orange','red','blue','goldenrod','forest green'] DisplayTextShift := [85,65,75,85,85] dev_set_color ('white') dev_set_line_width (2) read_image (Image, ImageRootName + '0') dev_display (Image) * * Define ROIs for the training data of the classifier set_display_font (WindowHandle, 14, 'mono', 'true', 'false') gen_rectangle1 (FuseOrange, 195, 90, 230, 120) dev_display (FuseOrange) disp_message (WindowHandle, 'Orange Fuse', 'image', 160, 90 - 65, 'black', 'true') gen_rectangle1 (FuseRed, 191, 280, 226, 310) dev_display (FuseRed) disp_message (WindowHandle, 'Red Fuse', 'image', 160, 280 - 55, 'black', 'true') gen_rectangle1 (FuseBlue, 190, 470, 225, 500) dev_display (FuseBlue) disp_message (WindowHandle, 'Blue Fuse', 'image', 160, 470 - 60, 'black', 'true') gen_rectangle1 (FuseYellow, 192, 672, 227, 702) dev_display (FuseYellow) disp_message (WindowHandle, 'Yellow Fuse', 'image', 160, 672 - 70, 'black', 'true') gen_rectangle1 (FuseGreen, 197, 880, 232, 910) dev_display (FuseGreen) disp_message (WindowHandle, 'Green Fuse', 'image', 160, 880 - 65, 'black', 'true') gen_empty_obj (Classes) concat_obj (FuseOrange, FuseRed, Classes) concat_obj (Classes, FuseBlue, Classes) concat_obj (Classes, FuseYellow, Classes) concat_obj (Classes, FuseGreen, Classes) disp_message (WindowHandle, 'ROIs for the training data', 'window', 12, 12, 'black', 'true') disp_continue_message (WindowHandle, 'black', 'true') stop () * * (1)创建GMM,添加样本,进行训练 create_class_gmm (3, 5, 1, 'full', 'none', 3, 42, GMMHandle) add_samples_image_class_gmm (Image, Classes, GMMHandle, 0) disp_message (WindowHandle, 'Training GMM classifier...', 'window', 48, 12, 'black', 'true') train_class_gmm (GMMHandle, 100, 0.001, 'training', 0.001, Centers, Iter) * * (2)创建GMM LUT分类器 disp_message (WindowHandle, 'Creating LUT classifier...', 'window', 84, 12, 'black', 'true') create_class_lut_gmm (GMMHandle, ['bit_depth','rejection_threshold'], [6,0.03], ClassLUTHandle) * * 使用LUT分类器分割图片 for Img := 0 to 3 by 1 read_image (Image, ImageRootName + Img) count_seconds (T1) (3)使用LUT进行分类 classify_image_class_lut (Image, ClassRegions, ClassLUTHandle) count_seconds (T2) TimeToClassify := (T2 - T1) * 1000 dev_display (Image) dev_set_line_width (3) for Fuse := 1 to 5 by 1 * * Perform post-processing on returned classes copy_obj (ClassRegions, ObjectsSelected, Fuse, 1) closing_circle (ObjectsSelected, RegionClosing, 3.5) connection (RegionClosing, ConnectedRegions) select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 2500, 99999) fill_up (SelectedRegions, RegionFillUp) area_center (RegionFillUp, Area, Row, Column) shape_trans (RegionFillUp, RegionTrans, 'convex') dev_set_color (FuseHighlight[Fuse - 1]) dev_display (RegionTrans) * disp_message (WindowHandle, FuseColors[Fuse - 1] + ' ' + FuseTypes[Fuse - 1] + ' A', 'image', Row - 10, Column - DisplayTextShift[Fuse - 1], FuseHighlight[Fuse - 1], 'white') endfor disp_message (WindowHandle, TimeToClassify$'.1f' + ' ms', 'window', 12, 12, 'black', 'true') if (Img < 3) disp_continue_message (WindowHandle, 'black', 'true') stop () endif endfor * disp_message (WindowHandle, 'No more lines to execute', 'window', 50, 12, 'black', 'true')
(1)创建GMM,添加样本,进行训练
(3)使用LUT进行分类
算子classify_image_class_lut取得的结果数组,如下图所示。
下面的循环代码只不过是按索引号(1到5) 把结果取出来,然后做一点美容整形操作再显示出来。
为啥取对象的索引是从1开始? 不知道为啥的童鞋要罚站半小时哦……
忍不住插一句,shape_trans (RegionFillUp, RegionTrans, 'convex') 中这个‘convex’的用法终于通过这个例子搞明白了,对勇哥真是个意外的收获。
for Fuse := 1 to 5 by 1 * * Perform post-processing on returned classes copy_obj (ClassRegions, ObjectsSelected, Fuse, 1) closing_circle (ObjectsSelected, RegionClosing, 3.5) connection (RegionClosing, ConnectedRegions) select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 2500, 99999) fill_up (SelectedRegions, RegionFillUp) area_center (RegionFillUp, Area, Row, Column) shape_trans (RegionFillUp, RegionTrans, 'convex') dev_set_color (FuseHighlight[Fuse - 1]) dev_display (RegionTrans) * disp_message (WindowHandle, FuseColors[Fuse - 1] + ' ' + FuseTypes[Fuse - 1] + ' A', 'image', Row - 10, Column - DisplayTextShift[Fuse - 1], FuseHighlight[Fuse - 1], 'white') endfor
再放几张其它的图片分类结果图:
勇哥突然想到: 以上待分类图片中总是出现训练时的5种分类特征,那么我有一张图只出现2类、或者出现完全不相关的图片会怎么样呢?
那就试试吧!
勇哥ps了一张图片,只有两种分类,并且加入一个不相关的异物-桔子。
桔子的颜色跟黄色物料相近,看看LUT的结果是怎么样的?
结果是分出两类,但是桔子被误分为yellow类。
把桔子换个颜色,会怎么?
结果如下,可以看到这次桔子不属于任何分类。
这个实验说明一个问题,LUT是以图片的什么特征进行分类的?
勇哥把上一篇的GMM分类用法跟本篇用法来对比一下,来找寻这个答案。
**********标准gmm分类用法*********************************** create_class_gmm (2, 2, 1, 'spherical', 'normalization', 10, 42, GMMHandle) get_features (ObjectSelected, WindowHandle, Circularity, Area, RowRegionCenter, ColumnRegionCenter) *添加类别0的特征 add_sample_class_gmm (GMMHandle, FeatureVector, 0, 0) *添加类别1的特征 add_sample_class_gmm (GMMHandle, FeatureVector, 1, 0) train_class_gmm (GMMHandle, 100, 0.001, 'training', 0.0001, Centers, Iter) for I := 1 to 15 by 1 get_features (ObjectSelected, WindowHandle, Circularity, Area, RowRegionCenter, ColumnRegionCenter) classify_class_gmm (GMMHandle, FeatureVector, 1, ClassID, ClassProb, Density, KSigmaProb) endfor **********gmm LUT分类用法*********************************** *FuseOrange,FuseRed,FuseBlue, FuseYellow, FuseGreen 这是5个region区域。 concat_obj (FuseOrange, FuseRed, Classes) concat_obj (Classes, FuseBlue, Classes) concat_obj (Classes, FuseYellow, Classes) concat_obj (Classes, FuseGreen, Classes) create_class_gmm (3, 5, 1, 'full', 'none', 3, 42, GMMHandle) add_samples_image_class_gmm (Image, Classes, GMMHandle, 0) disp_message (WindowHandle, 'Training GMM classifier...', 'window', 48, 12, 'black', 'true') train_class_gmm (GMMHandle, 100, 0.001, 'training', 0.001, Centers, Iter) create_class_lut_gmm (GMMHandle, ['bit_depth','rejection_threshold'], [6,0.03], ClassLUTHandle) for Img := 0 to 3 by 1 classify_image_class_lut (Image, ClassRegions, ClassLUTHandle) for Fuse := 1 to 5 by 1 copy_obj (ClassRegions, ObjectsSelected, Fuse, 1) disp_message (WindowHandle, FuseColors[Fuse - 1] + ' ' + FuseTypes[Fuse - 1] + ' A', 'image', Row - 10, Column - DisplayTextShift[Fuse - 1], FuseHighlight[Fuse - 1], 'white') endfor endfor
由上面代码的对比,可以发现:
LUT的代码中用的是add_samples_image_class_gmm
而上篇代码用的是add_samples_class_gmm
前者直接喂图片(image)给gmm分类器,后者需要喂特征向量给分类器。
因此关于 “LUT是以图片的什么特征进行分类的?”这个问题答案是不知道。因为我们直接把图片传给了分类器,它的内部是怎么操作的我们看不到,不过参考网上的原理,这个操作是使用高斯概率密度函数(正态分布曲线)精确地量化事物。
这个内部操作还提供给我们一组可控制参数的,它就是create_class_lut_gmm 算子的两个参数:GenParamNames,GenParamValues来进行设置的。
在应用层面上,我们通过实验,也能观察到这个内部操作至少跟颜色、灰度值和域值相关的。
---------------------
作者:hackpig
来源:www.skcircle.com
版权声明:本文为博主原创文章,转载请附上博文链接!