例程:classify_halogen_bulbs.hdev

在Halcon中模式匹配最成熟最常用的方式该署支持向量机了,在本例程中展示了使用支持向量机对卤素灯的质量检测方法。通过这个案例,相信大家可以对支持向量机的使用有一个更加清晰的了解。在相当多的检测和识别的应用中,都可以使用相同的方法来解决分类问题。

图1. 卤素灯图像

大致原理:

一、准备阶段:描述样本

1. 准备好两组卤素灯图像样本,好坏的各若干张图像;

2. 对样本图像进行分割,获取卤素灯关键部位区域;

3. 选择合适的对图像的描述,作为识别的特征;

一、准备阶段:构造分类器

1. 构造支持向量机:初始化支持向量机分类器所需的特征数量、核函数、类型数等参数;

2. 将样本添加到分类器中;

3. 进行训练,使分类器收敛;

二、识别阶段:分类识别

1. 提取待测目标区域;

2. 提取分类所需的特征:与准备阶段3中进行的操作相同;

3. 代入分类器进行分类。

上述在实际的操作过程中,准备阶段样本描述和构造分类器同时进行,即:将样本图像的特征提取和样本添加到分类器中这两步放在一个循环中完成。整个流程如下图所示:

图2. 支持向量机分类识别流程

图中左边部分是准备阶段所做的工作。如图所示,在使用SVM进行分类之前,首先需要构造分类器;构造完分类器之后,样本通过SVM样本描述循环体,被逐个进行特征提取后加入到待训练的SVM分类器中;所有训练样本按照各自的类型添加结束后就进行训练,使SVM收敛。

训练之后的SVM就可以用于分类了,下面就进入识别阶段。如图右侧所示,将待检测的样品图像经过相同的特征提取过程后代入SVM分类器即可得到分类结果。由于SVM本质上是对提取的特征向量的特征空间进行划分来区别特征的类别,因此在识别阶段使用的特征需要和准备阶段的完全相同。这样SVM在对待测样本中提取的特征向量进行划分时才知道它具体落入哪一个类型所在的空间,也就知道该样本的类型了。

对于使用,我们只要知道SVM是一个分类器,可以根据先验知识将特征向量进行分类。如果想深入了解SVM是如何分类的,里面涉及到的原理可以通过下面的链接来查看:

http://files.cnblogs.com/sleepwalker/Ch12_pres%28SVM%29.pdf

几乎所有使用SVM进行分类的流程大框架都遵循上图,在不同的应用中使用SVM的区别就在于图像描述的区别,如:Halcon学习笔记之支持向量机(一)中,样本是每一个像素点,而特征向量是像素点的坐标。在本案例中,样本是两组图像,而特征是分割后区域的若干个形态特征。

主流程代码

首先黏贴出源代码,这是Halcon当中例程中完整的代码:

* This program uses an SVM classifier
* to detect bad halogen bulbs.
*
* The training images have to be stored in sub directories
* which are named after their class names.
*
* The procedure calculate_features may be edited to select different
* features for the classification (if the number of features is changed,
* you have to change the first parameter of create_class_svm as well)
*
get_system ('image_dir', HalconImages)
get_system ('operating_system', OS)
if (OS = 'Windows NT')
tuple_split (HalconImages, ';', HalconImages)
else
tuple_split (HalconImages, ':', HalconImages)
endif
ReadOK := false
dev_get_preferences ('suppress_handled_exceptions_dlg', SaveMode)
dev_set_preferences ('suppress_handled_exceptions_dlg', 'true')
for k := 0 to |HalconImages|-1 by 1
try
read_image (Image, HalconImages[k] + '/halogen_bulb/halogen_bulb_01.png')
ReadPath := HalconImages[k] + '/halogen_bulb/'
ReadOK := true
break
catch (Exception)
endtry
endfor
if (not ReadOK)
disp_message (WindowHandle, 'Could not find the images in $HALCONIMAGES', 'window', -1, -1, 'black', 'true')
stop ()
endif
dev_set_preferences ('suppress_handled_exceptions_dlg', SaveMode)
read_image (Image, 'halogen_bulb/halogen_bulb_01.png')
get_image_pointer1 (Image, Pointer, Type, Width, Height)
dev_close_window ()
dev_open_window (0, 0, Width/2, Height/2, 'black', WindowHandle)
set_display_font (WindowHandle, 14, 'courier', 'true', 'false')
*
ClassNames := ['good','bad','none']
Colors := ['forest green','red','red']
Nu := [0.05]
KernelParam := [0.02]
*
* Create an SVM classifier
create_class_svm (7, 'rbf', KernelParam, Nu, |ClassNames|, 'one-versus-one', 'principal_components', 5, SVMHandle)
*
* Add samples
add_samples_to_svm (ClassNames, SVMHandle, WindowHandle, ReadPath)
dev_clear_window ()
*
* Train the classifier
disp_message (WindowHandle, 'Training...', 'window', -1, -1, 'black', 'true')
train_class_svm (SVMHandle, 0.001, 'default')
disp_message (WindowHandle, 'Training completed', 'window', -1, -1, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
*
* Classify halogen bulbs
classify_regions_with_svm (SVMHandle, Colors, ClassNames, ReadPath)
*
* Clear the classifier from memory
clear_class_svm (SVMHandle)

以上这是Halcon中案例的源代码,代码稍微有点长,但是其中很大篇幅代码与算法关系不大,下面进行详细介绍。

程序详解

初始化系统

首先我们可以看到截图所示部分的代码,所占篇幅较大。这部分代码的目的仅仅是初始化环境,并对样本图像的目录进行检查,这里不再对内容进行过多介绍。值得注意的是,其中对try-catch的使用在其它例程中不多见,但是实际应用中还是很有必要的,大家在写代码的时候不妨可以参考一下。

准备阶段

初始化

下面截图所示代码为准备阶段所做的事情:构造分类器、循环添加样本、训练分类器。

第一行定义了分类器所要分辨的类型:good, bad, none;

第二行定义了在输出时候不同结果显示的颜色;

第三和第四行是构造的分类器参数;

第五行,如注释所示,是构造SVM分类器;

对于前两行定义的元组,实质是一个枚举类型。因为在Halcon中,类型输出实际是一个整数,即诸如:0,1,2……的整数。因此如果输出是0,则对应的类型是good;输出1对应是bad;输出2对应的类型是none。而在显示的时候,同样的,可以使用Colors元组中相应位置的数据作为显示参数,用于显示不同颜色的字符或者区域。

通过create_class_svm构造SVM分类器之后需要添加样本进行训练,下面就进入外部过程add_sample_to_svm。如下图所示,通过鼠标右键,可以查看外部过程详细定义,该外部过程定义如下:

add_sample_to_svm:

这是一个循环,每次循环完成的任务为:

1. 读取下一帧样本图像(Image);

2. 使用固定阈值分割后提取待测区域(Region);

3. 计算特征向量(Features);

4. 将特征向量按照类型加入SVM中;

图3. 分割后的区域

calculate_features同样也是一个外部过程,该外部过程定义如下:

calculate_features:

从定义中,我们可以知道特征向量的选取,包括:面积(Area)、密实度(Compactness)、四个不变矩特征(PSI1,PSI2,PSI3,PSI4)和凸度(Convexity)。这些特征都属于区域的形态特征,最后将这些特征合并成一个实数型的特征向量Features,作为本过程的最终运算结果:

图4. 特征示例

训练SVM

添加样本后就开始训练SVM分类器,这一步Halcon仅通过一个tran_class_svm就能够完成,训练过程实质就是使用构造SVM时定义的核函数(此处为rbf)在高维特征空间寻找最优的分界面,将特征空间划分成不同类型(此处为good、bad、none三类)。训练过程是SVM的核心,也是需要进行大量运算的过程,因此在这一个算子上,可能会耗费比较长的时间。

具体如何划分,原理感兴趣的朋友可以下载上面的链接中的pdf文件进行研究。

识别阶段

到了识别阶段,就是对待测样本进行分类了,分类结果本案例中共有三类:good、bad、none。整个识别过程被封装在外部过程classify_regions_with_svm中:

classify_regions_with_svm:

从程序中可以看到,识别过程经历了与样本添加过程中相同的分割和特征提取。将提取到的特征向量代入SVM分类器就就能得出分类结果(Class)了。代入分类器的算子为classify_class_svm。从这里我们也可以看到,对SVM分类器实质是在对提取到的特征向量进行分类。

图5. 识别结果图

总结

整体来说,SVM分类到这里基本上已经结束,其它部分显示的代码就不在进行介绍了,相信大家也看得懂。这里我没有对参数的配置进行介绍,只介绍了整个流程。对于参数的解释,使用Halcon的朋友通过查询手册要来得更加方便,也更加准确。

Halcon学习笔记之支持向量机(二)的更多相关文章

  1. Halcon学习笔记之支持向量机(一)

    例程:class_overlap_svm.hdev 说明:这个例程展示了如何用一个支持向量机来给一幅二维的图像进行分类.使用二维数据的原因是因为它可以很容易地联想成为区域和图像.本例程中使用了三个互相 ...

  2. 【Unity Shaders】学习笔记——SurfaceShader(二)两个结构体和CG类型

    [Unity Shaders]学习笔记——SurfaceShader(二)两个结构体和CG类型 转载请注明出处:http://www.cnblogs.com/-867259206/p/5596698. ...

  3. Linux进程间通信IPC学习笔记之同步二(SVR4 信号量)

    Linux进程间通信IPC学习笔记之同步二(SVR4 信号量)

  4. Linux进程间通信IPC学习笔记之同步二(Posix 信号量)

    Linux进程间通信IPC学习笔记之同步二(Posix 信号量)

  5. VSTO 学习笔记(十二)自定义公式与Ribbon

    原文:VSTO 学习笔记(十二)自定义公式与Ribbon 这几天工作中在开发一个Excel插件,包含自定义公式,根据条件从数据库中查询结果.这次我们来做一个简单的测试,达到类似的目的. 即在Excel ...

  6. Unity3d之Hash&Slash学习笔记之(二)--角色基础类的构建

    Hash&Slash学习笔记之(二)--角色基础类的构建 BaseStat类的构建 基本成员变量: _baseValue //基础属性值 _buffValue //增加的buff值 _expT ...

  7. 汇编入门学习笔记 (十二)—— int指令、port

    疯狂的暑假学习之  汇编入门学习笔记 (十二)--  int指令.port 參考: <汇编语言> 王爽 第13.14章 一.int指令 1. int指令引发的中断 int n指令,相当于引 ...

  8. 【转】 Pro Android学习笔记(九二):AsyncTask(1):AsyncTask类

    文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.net/flowingflying/ 在Handler的学习系列中,学习了如何h ...

  9. React Native 学习笔记--进阶(二)--动画

    React Native 进阶(二)–动画 动画 流畅.有意义的动画对于移动应用用户体验来说是非常必要的.我们可以联合使用两个互补的系统:用于全局的布局动画LayoutAnimation,和用于创建更 ...

随机推荐

  1. windows程序设为开机自启动

    在Windows文件管理器中输入 %APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup 把程序快捷方式放到此处即可.

  2. 移动端rem布局 js

    // rem布局适配 (function(doc, win) { var docEl = doc.documentElement, resizeEvt = 'orientationchange' in ...

  3. Excel 导入 分批导入

    tm.begin(); sm.begin(); try { result = excel.readE(headKeyV,path); for (int index = 1; index < re ...

  4. 原始js表单文本框初始化获取焦点和选中

    发现: 1 使用dom对象.focus() 放在 window.onload 时可以 让这个DOM对象获取焦点. 2 使用DOM对象.select() 可以选中文本框中的文字. 3 不要加上on  , ...

  5. Problem 63

    Problem 63 https://projecteuler.net/problem=63 Powerful digit counts The 5-digit number, 16807=75, i ...

  6. STM32的USART发送数据时如何使用TXE和TC标志

    在USART的发送端有2个寄存器,一个是程序可以看到的USART_DR寄存器,另一个是程序看不到的移位寄存器,对应USART数据发送有两个标志,一个是TXE=发送数据寄存器空,另一个是TC=发送结束. ...

  7. hdu 5176 The Experience of Love

    The Experience of Love  Accepts: 11  Submissions: 108  Time Limit: 4000/2000 MS (Java/Others)  Memor ...

  8. [Bzoj3940] [AC自动机,USACO 2015 February Gold] Censor [AC自动机模板题]

    AC自动机模板题(膜jcvb代码) #include <iostream> #include <algorithm> #include <cstdio> #incl ...

  9. HBase行键的设计

    rowkey是行的主键,而且hbase只能用rowkey范围即scan来查找数据.rowkey是以字典排序的.可以巧妙设计行键,比如想通过电影的评价进行排序,可以把评分rate和电影id组合起来,ra ...

  10. CentOS6.5下修改MySQL编码方法

    1.查看默认编译,默认登陆到mysql后,通过show variable like命令来查看系统变量 可以看到,默认的数据库编码方式基本设置成了latin1的编译方式,此时我们需要将其修改成utf8的 ...