勇哥的视觉实验:GMM分类器(一) 基本用法

前言:

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

分类器相对于深度学习来讲是一种古老传统的图片处理技术。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识别两种不同的水果。

image.pngimage.pngA

柠檬和桔子。

使用的特征是两者的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代码如下:

image.png

* 
* 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)


image.png


下面的代码显示的是第6到11个特征分布图,它是6个柠檬的特征,用淡灰色点表示。

visualize_2D_feature_space (Cross, Height, Width, WindowHandle, FeaturesArea[6:11],\
 FeaturesCircularity[6:11], 'light gray', 18)


从这张图我们看到,灰色的6个点应该是桔子的特征点,因为桔子比柠檬更圆。

下面的6个浅灰色的点是柠檬的,它的面积和圆度都比桔子要小。

中间有一个浅灰的点意味着有一个柠檬,它的面积是所有柠檬中最大的,而且最圆。

左上那个灰色的点,表示有一个桔子是所有桔子中面积最小的,而且最不圆的。

image.png


我把四张训练图截出来,看看是不是勇哥分析的那样。

第一张图:

image.png

第二张:

image.png

第三张:

image.png

第四张:

image.png

从上面的特征分布图上看,灰色与浅色的特征被拉得越开越好,这样分类就会稳定可靠。

中间那个浅灰的点的特征则稍有不佳,如果再靠上一点,则可能分类到桔子类别上去了。




--------------------- 

作者: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