勇哥的视觉实验:GMM分类器(二) 基于LUT的用法,即高斯混合模型创建查找表进行图片分类

前言:

==========================================================

分类器相对于深度学习来讲是一种古老传统的图片处理技术。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,添加样本,进行训练

image.png

(3)使用LUT进行分类

算子classify_image_class_lut取得的结果数组,如下图所示。

image.png

下面的循环代码只不过是按索引号(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


再放几张其它的图片分类结果图:

image.png


image.png


勇哥突然想到: 以上待分类图片中总是出现训练时的5种分类特征,那么我有一张图只出现2类、或者出现完全不相关的图片会怎么样呢?

那就试试吧!


勇哥ps了一张图片,只有两种分类,并且加入一个不相关的异物-桔子。

桔子的颜色跟黄色物料相近,看看LUT的结果是怎么样的?

image.png

结果是分出两类,但是桔子被误分为yellow类。

image.png


把桔子换个颜色,会怎么?

image.png

结果如下,可以看到这次桔子不属于任何分类。

image.png


这个实验说明一个问题,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
版权声明:本文为博主原创文章,转载请附上博文链接!


本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2024年4月    »
1234567
891011121314
15161718192021
22232425262728
2930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864