图像验证码识别(八)——字符归一化
2016-03-01 14:38
253 查看
前面提到了将验证码上的字符分割成一个单独的字符图片并且保存,但是扣下来的字符串可能会有倾斜的现象,因为现在很多网页验证码为了防止破解都对字符进行了一定的扭曲和旋转,即使是同一个网站的验证码,每个相同的字符很有可能都是不一样的,所以为了提高识别的正确率,在这里最好能让每次进行训练的字符能够保持同一个角度。所以首先需要做的就是旋转倾斜。
一、旋转倾斜
旋转倾斜的目的就是要提高识别的正确率,如果字符‘A’的模板是标准的,让一个横着的‘A’去训练肯定得不到正确的结果。不过怎么旋转呢?想要将每个字符都旋转到印刷体的角度那是很难的,也是不必要的,在这里采用的思想就是每次都旋转成为“最瘦的”。每次分割出来一个字符不管是横着的还是竖着的,都可以回到“最瘦”的角度。具体做法就是利用OpenCV的旋转函数.
[cpp] view
plain copy
cv::Mat M = cv::getRotationMatrix2D(center, angle, scale);
getRotationMatrix2D这个函数所做的就是计算旋转矩阵,熟悉计算机图形学的都知道,图形在做各种变换的时候都是在原有的矩阵上乘以变换矩阵。这里center是CvPoint2D32f类型的结构体,其有两个float类型的变量分别表示要旋转的图像的宽和高,angle就是要旋转的角度,scale是旋转后的缩放系数。得到变换矩阵之后就可以进行旋转操作了
[cpp] view
plain copy
warpAffine(m_Mat,rotate_mat, M,cvSize(getWidth(),getHeight()),INTER_LINEAR,BORDER_CONSTANT,cvScalar(WHITE) );
warpAffine函数就是进行旋转操作。
鉴于大部分验证码的旋转都不是特别夸张,所以处理时我让字符从旋转的范围定在顺时针-15度到15度,每次旋转一度,然后计算最左边第一个黑色像素到最右边第一个黑色像素的距离,取距离最小的角度最终让字符旋转那个角度。
可以看到分割出来的字符和原始的还是有点不太一样,由于测试用的验证码倾斜的并不明显,所以这里调整的也不是很明显。
二、归一化
由于验证码大小不一,图片上又大量背景像素,因此在进行最后一步识别的时候,还应该将验证码的大小缩放到固定的大小。在这里我是先得到字符像素的最小外包矩形,这样可以先把没有用的白色背景像素干扰取消掉。接下来就是将所有的字符都统一缩放到16*16的大小,这样最终得到的经过预处理的标准字符就可以开始训练识别了。
一、旋转倾斜
旋转倾斜的目的就是要提高识别的正确率,如果字符‘A’的模板是标准的,让一个横着的‘A’去训练肯定得不到正确的结果。不过怎么旋转呢?想要将每个字符都旋转到印刷体的角度那是很难的,也是不必要的,在这里采用的思想就是每次都旋转成为“最瘦的”。每次分割出来一个字符不管是横着的还是竖着的,都可以回到“最瘦”的角度。具体做法就是利用OpenCV的旋转函数.
[cpp] view
plain copy
cv::Mat M = cv::getRotationMatrix2D(center, angle, scale);
getRotationMatrix2D这个函数所做的就是计算旋转矩阵,熟悉计算机图形学的都知道,图形在做各种变换的时候都是在原有的矩阵上乘以变换矩阵。这里center是CvPoint2D32f类型的结构体,其有两个float类型的变量分别表示要旋转的图像的宽和高,angle就是要旋转的角度,scale是旋转后的缩放系数。得到变换矩阵之后就可以进行旋转操作了
[cpp] view
plain copy
warpAffine(m_Mat,rotate_mat, M,cvSize(getWidth(),getHeight()),INTER_LINEAR,BORDER_CONSTANT,cvScalar(WHITE) );
warpAffine函数就是进行旋转操作。
鉴于大部分验证码的旋转都不是特别夸张,所以处理时我让字符从旋转的范围定在顺时针-15度到15度,每次旋转一度,然后计算最左边第一个黑色像素到最右边第一个黑色像素的距离,取距离最小的角度最终让字符旋转那个角度。
可以看到分割出来的字符和原始的还是有点不太一样,由于测试用的验证码倾斜的并不明显,所以这里调整的也不是很明显。
二、归一化
由于验证码大小不一,图片上又大量背景像素,因此在进行最后一步识别的时候,还应该将验证码的大小缩放到固定的大小。在这里我是先得到字符像素的最小外包矩形,这样可以先把没有用的白色背景像素干扰取消掉。接下来就是将所有的字符都统一缩放到16*16的大小,这样最终得到的经过预处理的标准字符就可以开始训练识别了。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- Lua中调用C++函数示例
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- C++联合体转换成C#结构的实现方法
- C++高级程序员成长之路
- C++编写简单的打靶游戏
- C++ 自定义控件的移植问题
- C++变位词问题分析
- C/C++数据对齐详细解析
- C++基于栈实现铁轨问题
- C++中引用的使用总结
- 使用Lua来扩展C++程序的方法
- C++中调用Lua函数实例
- Lua和C++的通信流程代码实例
- C与C++之间相互调用实例方法讲解
- 解析C++中派生的概念以及派生类成员的访问属性