前言:
==========================================================
分类器相对于深度学习来讲是一种古老传统的图片处理技术。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。
以下为运行中抓取的某帧结果。最后给出了全部样本的的结果统计。
得到的SVM与MLP的对比结论如下:
SVM分类器比MLP分类器能够更好地处理这些特定类型的失真。
MLP分类器的分类时间更好
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
版权声明:本文为博主原创文章,转载请附上博文链接!

