勇哥的视觉实验:SVM分类器(九) 用SVM和PLM进行OCR,对比两者的区别

前言:

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

分类器相对于深度学习来讲是一种古老传统的图片处理技术。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%被占用。
分类器相对于深度学习来讲不吃硬件,所以相对来讲算是轻量级的应用。

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


这个例子程序比较了SVM和MLP OCR分类器的训练和识别时间。

首先,通过向字符添加合成变形(如移位、旋转和笔划宽度的变化),创建一个包含5000多个样本的中等规模的训练集。

包括偏移以模拟分割错误。当然,如果没有分割错误,OCR特征本身是平移不变的。

然后训练一个SVM分类器,对第一个SVM分类器进行reduce_ocr_class_svm,得到第二个SVM分类器。

(算子reduce_ocr_class_svm通过精简SVM得到近似的效果良好的基于SVM的OCR分类器)

最后训练MLP分类器。

你将看到,SVM和MLP分类器的训练在当前的多核计算机上大致相同。

最后,该程序通过对原始训练字符进行变形,并在训练字符中加入结构化噪声,生成测试字符。

您将看到SVM分类器比MLP分类器能够更好地处理这些特定类型的失真。

请注意,所选择的失真不一定反映实际应用中发生的失真。

您还将看到MLP分类器的分类时间更好。


训练一个svm, 一个经过reduce_ocr_class_svm后的svm,一个MLP。

image.png


以下为运行中抓取的某帧结果。最后给出了全部样本的的结果统计。

得到的SVM与MLP的对比结论如下:

  • SVM分类器比MLP分类器能够更好地处理这些特定类型的失真。

  • MLP分类器的分类时间更好


image.png

image.png

image.png



dev_update_off ()
dev_close_window ()
dev_open_window (0, 0, 500, 500, 'black', WindowHandle)
dev_set_color ('green')
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
get_tmp_dir (TmpDir)
TrainFile := TmpDir + '/letters.trf'
TrainFileBig := TmpDir + '/letters_big.trf'
* 创建原始训练样本并将其存储在训练文件中.
dev_clear_window ()
dev_set_part (0, 0, 499, 499)
disp_message (WindowHandle, 'Creating initial samples... ', 'window', 12, 12, 'green', 'false')
gen_initial_trainfile (TrainFile)
* 现在修改原始训练样本以创建更大的训练集.
disp_message (WindowHandle, 'Creating modified samples... ', 'window', 42, 12, 'green', 'false')
read_ocr_trainf_names (TrainFile, CharClasses, CharCount)
read_ocr_trainf (Characters, TrainFile, CharClassesSingle)
dev_set_check ('~give_error')
delete_file (TrainFileBig)
dev_set_check ('give_error')
count_obj (Characters, NumChars)
for J := 0 to NumChars - 1 by 1
    select_obj (Characters, Char, J + 1)
    Class := CharClassesSingle[J]
    full_domain (Char, CharFull)
    get_image_size (CharFull, Width, Height)
    dev_set_part (0, 0, Height - 1, Width - 1)
    append_ocr_trainf (CharFull, CharFull, Class, TrainFileBig)
    append_ocr_translated (CharFull, 1, 1, TrainFileBig, Class)
    append_ocr_translated (CharFull, 1, 0, TrainFileBig, Class)
    append_ocr_translated (CharFull, 1, -1, TrainFileBig, Class)
    append_ocr_translated (CharFull, 0, -1, TrainFileBig, Class)
    append_ocr_translated (CharFull, -1, -1, TrainFileBig, Class)
    append_ocr_translated (CharFull, -1, 0, TrainFileBig, Class)
    append_ocr_translated (CharFull, -1, 1, TrainFileBig, Class)
    append_ocr_translated (CharFull, 0, 1, TrainFileBig, Class)
    append_ocr_rotated (CharFull, 3, TrainFileBig, Class)
    append_ocr_rotated (CharFull, -3, TrainFileBig, Class)
    append_ocr_rotated (CharFull, 5, TrainFileBig, Class)
    append_ocr_rotated (CharFull, -5, TrainFileBig, Class)
    append_ocr_rotated (CharFull, 8, TrainFileBig, Class)
    append_ocr_rotated (CharFull, -8, TrainFileBig, Class)
    append_ocr_erosion (CharFull, 1.2, TrainFileBig, Class)
    append_ocr_erosion (CharFull, 1.5, TrainFileBig, Class)
    append_ocr_dilated (CharFull, 1.2, TrainFileBig, Class)
    append_ocr_dilated (CharFull, 1.5, TrainFileBig, Class)
endfor

* 训练SVM和MLP分类器。
*注:为简单起见,分类是在原始灰度值上进行的,而不分割字符。
*在实际的应用程序中,字符当然必须被分割。
*在这种情况下,区域特征也将用于分类。

dev_clear_window ()
dev_set_part (0, 0, 499, 499)
disp_message (WindowHandle, 'Training SVM... ', 'window', 20, 20, 'green', 'false')
create_ocr_class_svm (8, 10, 'constant', 'pixel_invar', CharClasses, 'rbf', 0.01, 0.01, 'one-versus-all', 'normalization', 10, OCRHandleSVM)
count_seconds (S1)
trainf_ocr_class_svm (OCRHandleSVM, TrainFileBig, 0.001, 'default')
count_seconds (S2)
disp_message (WindowHandle, 'Training SVM... ' + (S2 - S1)$'5.2f' + 's', 'window', 20, 20, 'green', 'false')
get_support_vector_num_ocr_class_svm (OCRHandleSVM, NumSupportVectors, NumSVPerSVM)
disp_message (WindowHandle, 'Reducing SVM... ', 'window', 50, 20, 'green', 'false')
count_seconds (S1)

* 请注意,在本例中,MaxError参数被设置为人为的大值。
*在实际应用中,必须根据独立测试数据集上的错误率来确定此参数
reduce_ocr_class_svm (OCRHandleSVM, 'bottom_up', 2, 0.1, OCRHandleSVMR)

count_seconds (S2)
disp_message (WindowHandle, 'Reducing SVM... ' + (S2 - S1)$'5.2f' + 's', 'window', 50, 20, 'green', 'false')
get_support_vector_num_ocr_class_svm (OCRHandleSVMR, NumSupportVectorsR, NumSVPerSVMR)
disp_message (WindowHandle, 'Training MLP... ', 'window', 80, 20, 'green', 'false')
create_ocr_class_mlp (8, 10, 'constant', 'pixel_invar', CharClasses, 50, 'none', 10, 42, OCRHandleMLP)
count_seconds (S1)
trainf_ocr_class_mlp (OCRHandleMLP, TrainFileBig, 200, 1, 0.01, Error, ErrorLog)
count_seconds (S2)
disp_message (WindowHandle, 'Training MLP... ' + (S2 - S1)$'5.2f' + 's', 'window', 80, 20, 'green', 'false')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()

* 在在字符中引入严重失真,并确定错误率和分类时间.
NumDistort := 10
ErrorsSVM := 0
ErrorsSVMR := 0
ErrorsMLP := 0
TimeSVM := 0
TimeSVMR := 0
TimeMLP := 0
set_window_param (WindowHandle, 'flush', 'false')
for J := 0 to NumChars - 1 by 1
    select_obj (Characters, Char, J + 1)
    Class := CharClassesSingle[J]
    full_domain (Char, CharFull)
    get_image_size (CharFull, Width, Height)
    Num := max([J * NumDistort,1])
    gen_empty_obj (Chars)
    for K := 1 to NumDistort by 1
        gen_distorted_character (CharFull, CharDistort)
        concat_obj (Chars, CharDistort, Chars)
        dev_set_part (0, 0, Height - 1, Width - 1)
        dev_display (CharDistort)
        dev_set_part (0, 0, 499, 499)
        disp_message (WindowHandle, 'SVM:      Time: ' + (TimeSVM / Num * 1000)$'4.2f' + 'ms, Errors: ' + (real(ErrorsSVM) / Num * 100)$'5.3f' + '%', 'window', 20, 20, 'black', 'true')
        disp_message (WindowHandle, 'Red. SVM: Time: ' + (TimeSVMR / Num * 1000)$'4.2f' + 'ms, Errors: ' + (real(ErrorsSVMR) / Num * 100)$'5.3f' + '%', 'window', 50, 20, 'black', 'true')
        disp_message (WindowHandle, 'MLP:      Time: ' + (TimeMLP / Num * 1000)$'4.2f' + 'ms, Errors: ' + (real(ErrorsMLP) / Num * 100)$'5.3f' + '%', 'window', 80, 20, 'black', 'true')
        flush_buffer (WindowHandle)
    endfor
    count_seconds (S1)
    for K := 1 to NumDistort by 1
        select_obj (Chars, CharDistort, K)
        do_ocr_single_class_svm (CharDistort, CharDistort, OCRHandleSVM, 1, ClassRes)
        if (ClassRes != Class)
            ErrorsSVM := ErrorsSVM + 1
        endif
    endfor
    count_seconds (S2)
    TimeSVM := TimeSVM + S2 - S1
    count_seconds (S1)
    for K := 1 to NumDistort by 1
        select_obj (Chars, CharDistort, K)
        do_ocr_single_class_svm (CharDistort, CharDistort, OCRHandleSVMR, 1, ClassRes)
        if (ClassRes != Class)
            ErrorsSVMR := ErrorsSVMR + 1
        endif
    endfor
    count_seconds (S2)
    TimeSVMR := TimeSVMR + S2 - S1
    count_seconds (S1)
    for K := 1 to NumDistort by 1
        select_obj (Chars, CharDistort, K)
        do_ocr_single_class_mlp (CharDistort, CharDistort, OCRHandleMLP, 1, ClassRes, Confidence)
        if (ClassRes != Class)
            ErrorsMLP := ErrorsMLP + 1
        endif
    endfor
    count_seconds (S2)
    TimeMLP := TimeMLP + S2 - S1
endfor
set_window_param (WindowHandle, 'flush', 'true')
dev_clear_window ()
dev_set_part (0, 0, 499, 499)
Num := NumChars * NumDistort
disp_message (WindowHandle, 'SVM:      Time: ' + (TimeSVM / Num * 1000)$'4.2f' + 'ms, Errors: ' + (real(ErrorsSVM) / Num * 100)$'5.3f' + '%', 'window', 20, 20, 'green', 'false')
*即reduce_ocr_class_svm后的svm
disp_message (WindowHandle, 'Red. SVM: Time: ' + (TimeSVMR / Num * 1000)$'4.2f' + 'ms, Errors: ' + (real(ErrorsSVMR) / Num * 100)$'5.3f' + '%', 'window', 50, 20, 'green', 'false')
disp_message (WindowHandle, 'MLP:      Time: ' + (TimeMLP / Num * 1000)$'4.2f' + 'ms, Errors: ' + (real(ErrorsMLP) / Num * 100)$'5.3f' + '%', 'window', 80, 20, 'green', 'false')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
dev_set_check ('~give_error')
delete_file (TrainFile)
delete_file (TrainFileBig)
dev_set_check ('give_error')


本例程是:compare_ocr_svm_mlp.hdev

比较svm和mlp的区别的例程比较少见,值得一读!

而在官方手册上提到svm与mlp的比较如下:

SVM和多层感知器(MLP)的比较:
通常情况下,SVM通常在训练时速度更快,尤其是对于大型训练集,其识别率比MLP略高。
MLP分类速度更快,因此在时间紧迫的应用中应首选。请注意,本指南假定参数的最佳调整。

当然,两者在原理上是完全不同的,以上仅是在使用效果上的对比。


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

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