勇哥的视觉实验:SVM分类器(七) 支持向量机的应用例子,优化svm的参数对比不同方式参数设置下的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%被占用。
分类器相对于深度学习来讲不吃硬件,所以相对来讲算是轻量级的应用。

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

下面的实例程序比较了不同参数的OCR支持向量机对人工数据的识别率。

字母图像随机失真,并作为训练数据反馈给三种不同的SVM训练变体:

1. 带默认设置的SVM

2. 人工优化设置的SVM(功能,nu,gamma(Kernelparameter))

3. 基于nu和gamma自动估计特征的SVM


“term tuning”在这里仅指识别率。本例中不考虑执行时间。

最佳参数集的估计可能需要相当长的时间,因为它是在非常高维空间上的定向搜索(取决于可能的特征的数量以及是否必须估计nu和gamma)。

对于“最佳参数估计”这个功能可以参考勇哥之前的文章:http://www.skcircle.com/?id=1640



这个例子演示了分类器的自动参数估计和自动特征选择——在本例中是一个用于OCR的SVM(支持向量机)分类器

image.png

这个警告是:

警告:F5将启动自动功能选择
这可能需要一段时间(最多几个小时)!
在Intel i5(4核,3.3GHz)上大约15分钟的计算时间。
如果您现在没有时间请取消程序执行,稍后再来测试

勇哥这个破i5笔记本不行,等到花儿都谢了,还是用台式机跑吧!

image.png

耗时算子是:select_feature_set_trainf_svm ,它是用来自动选择适合的特征。

image.png


来看看勇哥的xeon服务器,20核居然跑了24分钟,果然还是很垃圾哦。

应该是单核速度太慢的原因。

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')
set_system ('seed_rand', 42)
get_tmp_dir (TmpDir)
TrainFile := TmpDir + '/letters_autosvm.trf'
TrainFileBig := TmpDir + '/letters_big_autosvm.trf'
* 
* 创建原始训练样本并将其存储在训练文件中.
dev_clear_window ()
dev_set_part (0, 0, 499, 499)
*这个例子演示了分类器的自动参数估计和自动特征选择——在本例中是一个用于OCR的SVM(支持向量机)分类器
Message := 'This example demonstrates the'
Message[1] := 'automatic parameter estimation and'
Message[2] := 'automatic feature selection for'
Message[3] := 'classifiers - in this case a SVM'
Message[4] := '(support vector machine) classifier'
Message[5] := 'for OCR.'
disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
disp_message (WindowHandle, 'Please wait while ...', 'window', 200, 12, 'white', 'false')
disp_message (WindowHandle, ' ... creating initial samples ... ready', 'window', 230, 12, 'white', 'false')
gen_initial_trainfile (TrainFile)
read_ocr_trainf_names (TrainFile, CharClasses, CharacterCount)
read_ocr_trainf (Characters, TrainFile, CharacterNames)
dev_set_check ('~give_error')
delete_file (TrainFileBig)
dev_set_check ('give_error')
*创建初始样本
disp_message (WindowHandle, ' ... creating initial samples ... ready', 'window', 230, 12, 'white', 'false')
*添加变形的样本
disp_message (WindowHandle, ' ... adding distorted samples ...', 'window', 260, 12, 'white', 'false')
count_obj (Characters, NumChars)
for Index := 1 to 2 by 1
    for J := 0 to NumChars - 1 by 1
        select_obj (Characters, Char, J + 1)
        full_domain (Char, CharFull)
        gen_distorted_character (CharFull, CharDistort, 7)
        Class := CharacterNames[J]
        threshold (CharDistort, Region, 0, 128)
        area_center (Region, Area, Row, Column)
        if (Area < 10)
            continue
        endif
        append_ocr_trainf (Region, CharDistort, Class, TrainFileBig)
        full_domain (CharDistort, ImageFull)
        get_image_size (CharFull, Width, Height)
    endfor
endfor
* Train the SVMs
disp_message (WindowHandle, ' ... adding distorted samples ... ready', 'window', 260, 12, 'white', 'false')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
dev_clear_window ()
dev_set_part (0, 0, 499, 499)
Message := 'Train SVM with default settings ...   '
disp_message (WindowHandle, Message, 'window', 12, 12, 'white', 'false')
create_ocr_class_svm (8, 10, 'bilinear', 'default', CharClasses, 'rbf', 0.02, 0.05, 'one-versus-one', 'normalization', 10, OCRHandleSVMDefault)
count_seconds (S1)
trainf_ocr_class_svm (OCRHandleSVMDefault, TrainFileBig, 0.001, 'default')
count_seconds (S2)
Message := Message + (S2 - S1)$'3.2' + 's'
disp_message (WindowHandle, Message, 'window', 12, 12, 'white', 'false')
Message[1] := ' \nTrain SVM manually optimized ...      '
disp_message (WindowHandle, Message, 'window', 12, 12, 'white', 'false')
create_ocr_class_svm (8, 10, 'bilinear', ['gradient_8dir','pixel','projection_horizontal','foreground_grid_16','phi','moments_region_2nd_invar','chord_histo','ratio'], CharClasses, 'rbf', 0.001, 0.03, 'one-versus-one', 'normalization', 10, OCRHandleSVMOpt)
count_seconds (S1)
trainf_ocr_class_svm (OCRHandleSVMOpt, TrainFileBig, 0.001, 'default')
count_seconds (S2)
Message[1] := ' \nTrain SVM manually optimized ...      ' + (S2 - S1)$'3.2' + 's'
disp_message (WindowHandle, Message, 'window', 12, 12, 'white', 'false')
count_seconds (S2)
Message[2] := ' \nAutomatic parameter estimation ... '
disp_message (WindowHandle, Message, 'window', 12, 12, 'white', 'false')

*警告:F5将启动自动功能选择
*这可能需要一段时间(最多几个小时)!
*在Intel i5(4核,3.3GHz)上大约15分钟的计算时间。
*如果您现在没有时间请取消程序执行,稍后再来测试

Warning := 'Warning: F5 will start the'
Warning[1] := 'automatic feature selection.'
Warning[2] := 'This may take a while (up to hours)!'
Warning[3] := 'On an Intel i5 (4 cores, 3.3GHz) expect'
Warning[4] := 'about 15 minutes of calculation time.'
Warning[5] := ' '
Warning[6] := 'If you don\'t have the time now'
Warning[7] := 'please cancel the program and'
Warning[8] := 'come back later.'
Warning[9] := ' '
Warning[10] := 'If you want to continue, press F5.'
disp_message (WindowHandle, Warning, 'window', 150, 20, 'white', 'red')
stop ()

dev_clear_window ()
disp_message (WindowHandle, Message, 'window', 12, 12, 'white', 'false')
Status := 'Performing automatic feature selection ...'
Status[1] := ' \nPlease check the HDevelop status bar'
Status[2] := 'for progress information.'
disp_message (WindowHandle, Status, 'window', 200, 12, 'yellow', 'false')
count_seconds (S1)
select_feature_set_trainf_svm (TrainFileBig, ['zoom_factor','ratio','width','height','foreground','foreground_grid_9','foreground_grid_16','anisometry','compactness','convexity','moments_region_2nd_invar','moments_region_2nd_rel_invar','moments_region_3rd_invar','moments_central','phi','num_connect','num_holes','projection_horizontal','projection_vertical','projection_horizontal_invar','projection_vertical_invar','chord_histo','num_runs','pixel','pixel_invar','pixel_binary','gradient_8dir','cooc','moments_gray_plane'], 'greedy', 8, 10, ['nu','gamma'], ['auto','auto'], OCRHandle, FeatureSet, Score)
count_seconds (S2)
* Check the automatically estimated parameters
get_params_ocr_class_svm (OCRHandle, WidthCharacter, HeightCharacter, Interpolation, Features, CharactersT, KernelType, KernelParam, Nu, Mode, Preprocessing, NumComponents)
dev_clear_window ()

*自动参数估计…
*现在将在严重扭曲的字符上测试所有三个分类器,并计算错误率。
*您将看到,自动训练的分类器的性能接近手动优化的分类器。

Message[2] := ' \nAutomatic parameter estimation ... ' + (S2 - S1)$'6.1f' + 's'
disp_message (WindowHandle, Message, 'window', 12, 12, 'white', 'false')
String := 'Now all three classifiers will be tested'
String[1] := 'on heavily distorted characters and the'
String[2] := 'error rates are calculated.'
String[3] := ' \nYou will see, that the performance of the'
String[4] := 'automatically trained classifier is close'
String[5] := 'to the manually optimized one.'
disp_message (WindowHandle, String, 'window', 200, 12, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
dev_clear_window ()
* Now introduce heavy distortions into the characters
* and determine the error rates
NumDistort := 10
ErrorsSVMDef := 0
ErrorsSVMTuned := 0
ErrorsSVMAuto := 0
TimeSVMDef := 0
TimeSVMTun := 0
TimeSVMAut := 0
Num := 0
for J := 0 to NumChars - 1 by 1
    select_obj (Characters, Char, J + 1)
    Class := CharacterNames[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, 7)
        full_domain (CharDistort, CharDistortFull)
        threshold (CharDistortFull, Region, 0, 128)
        reduce_domain (CharDistortFull, Region, CharSeg)
        area_center (Region, Area, Row, Column)
        if (Area < 2)
            concat_obj (Chars, CharDistortFull, Chars)
        else
            concat_obj (Chars, CharSeg, Chars)
        endif
        dev_set_part (-Height, -Width, Height - 1 + Height, Width - 1 + Width)
        dev_display (CharDistortFull)
        dev_set_part (0, 0, 499, 499)
        Message := 'Testing character ' + (J + 1) + ' of ' + NumChars
        *错误率
        Message[1] := 'Error rates for:'
        *缺省设置的svm
        Message[2] := 'Default:                 ' + (real(ErrorsSVMDef) / Num * 100)$'5.3f' + '%'
        *人工优化设置的svm
        Message[3] := 'Manually tuned SVM:      ' + (real(ErrorsSVMTuned) / Num * 100)$'5.3f' + '%'
        *自动特征选择的svm
        Message[4] := 'Automatically tuned SVM: ' + (real(ErrorsSVMAuto) / Num * 100)$'5.3f' + '%'
        disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
    endfor
    count_seconds (S1)
    for K := 1 to NumDistort by 1
        select_obj (Chars, CharDistort, K)
        do_ocr_single_class_svm (CharDistort, CharDistort, OCRHandleSVMDefault, 1, ClassRes)
        if (ClassRes != Class)
            ErrorsSVMDef := ErrorsSVMDef + 1
        endif
    endfor
    count_seconds (S2)
    TimeSVMDef := TimeSVMDef + S2 - S1
    count_seconds (S1)
    for K := 1 to NumDistort by 1
        select_obj (Chars, CharDistort, K)
        do_ocr_single_class_svm (CharDistort, CharDistort, OCRHandleSVMOpt, 1, ClassRes)
        if (ClassRes != Class)
            ErrorsSVMTuned := ErrorsSVMTuned + 1
        endif
    endfor
    count_seconds (S2)
    TimeSVMTun := TimeSVMTun + S2 - S1
    count_seconds (S1)
    for K := 1 to NumDistort by 1
        select_obj (Chars, CharDistort, K)
        do_ocr_single_class_svm (CharDistort, CharDistort, OCRHandle, 1, ClassRes)
        if (ClassRes != Class)
            ErrorsSVMAuto := ErrorsSVMAuto + 1
        endif
    endfor
    count_seconds (S2)
    TimeSVMAut := TimeSVMAut + S2 - S1
endfor
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
dev_set_check ('~give_error')
delete_file (TrainFile)
delete_file (TrainFileBig)
dev_set_check ('give_error')
dev_clear_window ()
disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
disp_message (WindowHandle, 'End of program', 'window', 150, 12, 'black', 'true')
*

gen_initial_trainfile的源码:

image.png

read_image (Image, 'letters')
* Segment the image.
binary_threshold (Image, Region, 'max_separability', 'dark', UsedThreshold)
* Connect the i's and j's with their dots.
dilation_circle (Region, RegionDilation, 3.5)
* Compute the correct connected components.
connection (RegionDilation, ConnectedRegions)
* Reduce each connected component (character) to its original shape.
intersection (ConnectedRegions, Region, RegionIntersection)
* Sort the characters line-by-line.
sort_region (RegionIntersection, Characters, 'character', 'true', 'row')
* Compute the true class of each character.
count_obj (Characters, Number)
Classes := []
Sequence := [0:26 * 20 - 1]
Sequence := Sequence / 20
LetterColumn := chr(ord('a') + Sequence)
Classes := [LetterColumn,gen_tuple_const(20,'.')]
* Construct the necessary training file from the segmented characters.
write_ocr_trainf (Characters, Image, Classes, TrainFileName)
return ()


gen_distorted_character函数源码:

它用于产生扭曲变形的字符。这个功能还是蛮有参考价值的!

image.png

get_image_size (Char, Width, Height)
EroDil := rand(1) * NoiseLevel - (NoiseLevel / 2.0)
if (EroDil < 0)
    gray_erosion_shape (Char, CharEroDil, 1 - EroDil, 1 - EroDil, 'rhombus')
else
    gray_dilation_shape (Char, CharEroDil, 1 + EroDil, 1 + EroDil, 'rhombus')
endif
hom_mat2d_identity (HomMat2DIdentity)
hom_mat2d_rotate (HomMat2DIdentity, rad(rand(1) * (NoiseLevel * 3.0) - ((NoiseLevel * 3.0) / 2.0)), Height / 2, Width / 2, HomMat2DRotate)
hom_mat2d_translate (HomMat2DRotate, rand(1) * (NoiseLevel / 2.0) - (NoiseLevel / 4.0), rand(1) * (NoiseLevel / 2.0) - (NoiseLevel / 4.0), HomMat2DTranslate)
affine_trans_image (CharEroDil, CharTrans, HomMat2DTranslate, 'constant', 'false')
expand_domain_gray (CharTrans, CharExpanded, 2)
gen_image_proto (CharExpanded, ImageBlank, 128)
add_noise_white (ImageBlank, ImageNoise, 60)
smooth_image (ImageNoise, ImageSmooth, 'gauss', 1)
scale_image (ImageSmooth, ImageScaled, 3, -256)
add_image (CharExpanded, ImageScaled, CharDistort, 1, -128)
threshold (CharDistort, Region, 0, 128)
reduce_domain (CharDistort, Region, CharDistort)
return ()


相当精彩的演示程序,赞美一下!!


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

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