识别验证码图片,使用halcon 21.05
下面代码识别准确率100%
目录
- 训练,图片打标签
- 使用代码创建分类器;
- 识别验证码,检验识别效果
- 使用“助手”加载训练文件,加载训练分类器,察看收集的字符,训练识别准确率
训练,图片打标签
*
* Training of the OCR
* The font is used in "bottle.hdev"
*
*
* Step 0: Preparations
*
* Step 1: Segmentation
FontName:='yan_zheng_ma119'
* 训练文件保存
TrainingFileName:='E:/Work/'+FontName+'.trf'
* 分类器保存
FontFileOMC:='E:/Work/'+FontName+'.omc'
dev_update_window ('off')
*训练
* 1 ,18
* 30
* 已经训练
* 已经训练了39,40,52
* 图29、54 重点识别
* read_image (Image, 'E:/Work/验证码图片/9.jpg')
read_image (Image, 'E:/Work/验证码图片1/744.jpg')
*获取图片尺寸
get_image_size (Image, Width, Height)
dev_close_window ()
dev_open_window (0, 0, 4 * Width, 7 * Height, 'black', WindowID)
* 设置打印字符的大小
set_display_font (WindowID, 80, 'mono', 'true', 'false')
*放大图片
zoom_image_size(Image,ImageZoom,4 * Width,4 * Height ,'constant')
*创建指定区域
gen_rectangle1 (Rectangle, 36, 57, 189, 588)
* 获取图片指定区域的图片
reduce_domain(ImageZoom,Rectangle,imgMask)
* 根据阈值选取图像,筛选体积大的,数字越大体积越大,红色为选中
*threshold (Image, RawSegmentation, 200, 300)
threshold (imgMask, RawSegmentation, 0.1, 160)
*connection (circleRegion, ConnectedRegions)
*内部充满
fill_up (RawSegmentation, RegionFillUp)
*char_threshold (Image, Image, Characters, 3, 50, Threshold)
*根据形状特征填充孔洞
*fill_up_shape(RawSegmentation, fillRegin, 'area', 5, 5)
*去掉小的模块
*opening_rectangle1 (RegionFillUp, Cut,2,2)
*利用矩形结构元素执行开运算。矩形宽设为1,高为7,相当于低于7的连接被截断
*opening_rectangle1 (RegionFillUp, Cut,3, 3)
*分割粘连字符 10,30,,60,80 不行:90,100;宽度79,74,84,71
* 20 等号污染了问号;
* per 55识别成功29、54
*partition_dynamic(circleRegion,parRegion,70,55)
* 成功拆分,图片9
*partition_dynamic(circleRegion,parRegion,55,50)
* 成功拆分,图片11
* partition_dynamic(circleRegion,parRegion,55,55)
* 成功拆分,图片29
*partition_dynamic(circleRegion,parRegion,55,70)
*成功划分7.jpg `
*partition_dynamic(circleRegion,parRegion,60,70)
*成功划分998.jpg
* partition_dynamic(circleRegion,parRegion,60,50)
*將單個字符暈染連成一塊,水平、垂直方向延伸粘连
closing_rectangle1 (RegionFillUp, RegionClosing1,1, 25)
* 开口可以消除小区域(比圆形结构元件小)并平滑区域的边界。
opening_circle (RegionClosing1, circleRegion,5)
*着色
connection (circleRegion, ConnPatterns)
*分割 ,默认以 partition_dynamic分割,能正确分割大多数图片情况;
*partition_dynamic(RegionFillUp,parRegion,60,50)
partition_rectangle (ConnPatterns, par2, 76, 150)
partition_dynamic(ConnPatterns,par1,60,80)
*着色对象个数
count_obj (par1, par1_count)
count_obj (par2, par2_count)
AgainCheck:=0
* 检查两个对象分割的块个数是否一致
if ( par1_count != par2_count )
partition_rectangle (ConnPatterns, par1, 76, 150)
AgainCheck:=1
endif
* 第二次检查,每个分割块的宽度,是否在允许范围?
if (AgainCheck==0)
count_obj (par1, par1_count)
*select_obj调用之前,必须调用sort_region
sort_region (par1, SortedRegions2, 'first_point', 'true', 'column')
* select_obj (SortedRegions2, CharRegion, 1)
* select_obj (SortedRegions2, CharRegion, 2)
* select_obj (SortedRegions2, CharRegion, 3)
* select_obj (SortedRegions2, CharRegion, 4)
* select_obj (SortedRegions2, CharRegion, 5)
for P := 1 to par1_count by 1
select_obj (SortedRegions2, CharRegion, P )
* 获取region的宽度
region_features (CharRegion, 'width', CharWidth)
if (CharWidth < 46 or CharWidth>107 )
partition_rectangle (ConnPatterns, par1, 76, 150)
break
endif
endfor
endif
* 与threshold后的图,求交集
intersection (par1, RawSegmentation, NumberCandidates)
* 选择指定尺寸的块
select_shape (NumberCandidates, Numbers, ['width','height'], 'and',[40, 10],[100,150])
*着色对象个数
* count_obj (Numbers, Check_count)
* 如果着色对象数不足5个,说明分割有问题
* if ( Check_count!=5)
* partition_rectangle (ConnPatterns, par2, 76, 150)
* intersection (par2, RawSegmentation, NumberCandidates)
* select_shape (NumberCandidates, Numbers, ['width','height'], 'and',[40, 10],[100,150])
* endif
sort_region (Numbers, SortedRegions, 'first_point', 'true', 'column')
dev_display (imgMask)
dev_set_color ('green')
dev_set_line_width (2)
dev_set_shape ('rectangle1')
dev_set_draw ('margin')
dev_display (SortedRegions)
*
stop()
*----------------训练模型,开始-----------------------
TrainingNames := ['1','/','1','=' ,'?']
*TrainingFileName := FontName + '.trf'
shape_trans (SortedRegions, RegionTrans, 'rectangle1')
area_center (RegionTrans, Area, Row, Column)
MeanRow := mean(Row)
dev_set_check ('~give_error')
*delete_file (TrainingFileName)
dev_set_check ('give_error')
*图片数字下标
K:=0
for I := 0 to |Column| - 1 by 1
select_obj (SortedRegions, CharaterRegions, I+1)
* 获取region的宽度
* region_features (CharaterRegions, 'width', CharWidth)
gen_empty_region (EmptyObject)
if(CharaterRegions!=EmptyObject)
append_ocr_trainf (CharaterRegions, imgMask, TrainingNames[K], TrainingFileName)
disp_message (WindowID, TrainingNames[K], 'window', MeanRow+180, Column[I]-26, 'magenta', 'false')
K:=K+1
endif
endfor
*----------------训练模型,结束-----------------------
使用代码创建分类器;
在所有的样本图片都打上标签后,就可以训练多层感知分类器了
TrainFile:='E:/Work/yan_zheng_ma119.trf'
FontFileOMC:='E:/Work/yan_zheng_ma119.omc'
*读取训练文件的字符
read_ocr_trainf_names (TrainFile, CharacterNames, CharacterCount)
*使用多层感知器创建OCR分类器。
create_ocr_class_mlp (8, 10, 'constant', 'default', CharacterNames, 20,'none', 81, 42, OCRHandle)
*训练OCR分类器。
trainf_ocr_class_mlp (OCRHandle, TrainFile, 100, 0.01, 0.01, Error, ErrorLog)
*写入分类器文件保存
write_ocr_class_mlp (OCRHandle, FontFileOMC)
识别验证码,检验识别效果
*
* Step 1: Segmentation
FontName:='yan_zheng_ma119'
* 分类器保存
FontFileOMC:='E:/Work/'+FontName+'.omc'
dev_update_window ('off')
*训练
* 重点识别:图29、54、9,11,
*
* 循环图片文件列表,一个个识别
*读取目录里面的文件
list_files ('E:/Work/验证码3', ['files' ], ImageFiles)
for ImgIndex := 1 to |ImageFiles| by 1
*for ImgIndex := 1 to 1000 by 1
fileName:=ImageFiles[ImgIndex - 1]
read_image (Image, fileName)
* read_image (Image, 'E:/Work/验证码图片/29.jpg')
* 拆分字符串
tuple_split(fileName,'\\',fileNameShort)
*取最后一个字符串
fileShortName:=fileNameShort[5]
*文件数量数
fileCount := |ImageFiles|
* 待处理文件数
fileCount_surplus := |ImageFiles|-ImgIndex
get_image_size (Image, Width, Height)
dev_close_window ()
dev_open_window (0, 0, 4 * Width, 7 * Height, 'black', WindowID)
* 设置显示字体大小
set_display_font (WindowID, 27, 'mono', 'true', 'false')
zoom_image_size(Image,ImageZoom,4 * Width,4 * Height ,'constant')
*显示图片序号
disp_message (WindowID, fileShortName+',剩余待处理数'+fileCount_surplus+'/'+fileCount, 'window', 0, 0, 'magenta', 'false')
*regiongrowing (ImageInvert, Regions, 2, 2, 1, 255)
*gen_rectangle1 (Rectangle, 4.875, 24.125, 46.625, 141.875)
gen_rectangle1 (Rectangle, 36, 57, 189, 588)
reduce_domain(ImageZoom,Rectangle,imgMask)
* 筛选体积大的,数字越大体积越大,红色为选中
threshold (imgMask, RawSegmentation, 0.1, 160)
*内部充满
fill_up (RawSegmentation, RegionFillUp)
*char_threshold (Image, Image, Characters, 3, 50, Threshold)
*根据形状特征填充孔洞
*fill_up_shape(RawSegmentation, fillRegin, 'area', 5, 5)
*去掉小的模块
*opening_rectangle1 (RegionFillUp, Cut,2,2)
*利用矩形结构元素执行开运算。矩形宽设为1,高为7,相当于低于7的连接被截断
*opening_rectangle1 (RegionFillUp, Cut,3, 3)
*將單個字符暈染連成一塊,水平、垂直方向延伸粘连
closing_rectangle1 (RegionFillUp, RegionClosing1,1, 25)
* 开口可以消除小区域(比圆形结构元件小)并平滑区域的边界。
opening_circle (RegionClosing1, circleRegion,5)
*着色
connection (circleRegion, ConnPatterns)
*分割粘连字符 ,默认以 partition_dynamic分割,能正确分割大多数图片情况;
*partition_dynamic(RegionFillUp,parRegion,60,50)
partition_rectangle (ConnPatterns, par2, 76, 150)
partition_dynamic(ConnPatterns,par1,60,80)
*着色对象个数
count_obj (par1, par1_count)
count_obj (par2, par2_count)
AgainCheck:=0
* 检查两个对象分割的块个数是否一致
if ( par1_count != par2_count )
partition_rectangle (ConnPatterns, par1, 76, 150)
AgainCheck:=1
endif
* 第二次检查,每个分割块的宽度,是否在允许范围?
if (AgainCheck==0)
count_obj (par1, par1_count)
*select_obj调用之前,必须调用sort_region
sort_region (par1, SortedRegions2, 'first_point', 'true', 'column')
* select_obj (SortedRegions2, CharRegion, 1)
* select_obj (SortedRegions2, CharRegion, 2)
* select_obj (SortedRegions2, CharRegion, 3)
* select_obj (SortedRegions2, CharRegion, 4)
* select_obj (SortedRegions2, CharRegion, 5)
for P := 1 to par1_count by 1
select_obj (SortedRegions2, CharRegion, P )
* 获取region的宽度
region_features (CharRegion, 'width', CharWidth)
if (CharWidth < 46 or CharWidth>107 )
partition_rectangle (ConnPatterns, par1, 76, 150)
break
endif
endfor
endif
* 与threshold后的图,求交集
intersection (par1, RawSegmentation, NumberCandidates)
* 选择指定尺寸的块
select_shape (NumberCandidates, Numbers, ['width','height'], 'and',[40, 10],[100,150])
*着色对象个数
* count_obj (Numbers, Check_count)
* 如果着色对象数不足5个,说明分割有问题
* if ( Check_count!=5)
* partition_rectangle (ConnPatterns, par2, 76, 150)
* intersection (par2, RawSegmentation, NumberCandidates)
* select_shape (NumberCandidates, Numbers, ['width','height'], 'and',[40, 10],[100,150])
* endif
sort_region (Numbers, SortedRegions, 'first_point', 'true', 'column')
dev_display (imgMask)
dev_set_color ('green')
dev_set_line_width (2)
dev_set_shape ('rectangle1')
dev_set_draw ('margin')
dev_display (SortedRegions)
*
* stop()
shape_trans (SortedRegions, RegionTrans, 'rectangle1')
area_center (RegionTrans, Area, Row, Column)
MeanRow := mean(Row)
dev_set_check ('~give_error')
dev_set_check ('give_error')
* 设置显示字体大小
set_display_font (WindowID, 80, 'mono', 'true', 'false')
*----------------识别 ,开始 -----------------------
read_ocr_class_mlp (FontFileOMC, OCRHandle2)
*图片数字下标
K:=0
for I := 0 to |Column| - 1 by 1
select_obj (SortedRegions, CharaterRegions, I+1)
gen_empty_region (EmptyObject)
if(CharaterRegions!=EmptyObject)
do_ocr_multi_class_mlp (CharaterRegions, imgMask, OCRHandle2, Class, Confidence)
disp_message (WindowID, Class, 'window', MeanRow+180, Column[I]-26, 'magenta', 'false')
K:=K+1
endif
* 不打印第二个数字右侧的 =,?
if( I==2 )
break
endif
endfor
* 等待0.5秒钟
wait_seconds (0.5)
* 循环图片结束
endfor
*----------------识别 ,结束-----------------------
使用“助手”加载训练文件,加载训练分类器,察看收集的字符,训练识别准确率
加载训练文件,加载分类器;