前一篇文章《Android划矩形截屏并加入OCR识别》在安卓中我们做了划矩形截图进行OCR实识,其中只是简单的进行了二值化的处理然后就传入图片识别,本来计划把图片二值化后做一些透视变换的Demo可以增加识别的效果,然后就出来了今天的文章。
样版原图
我自己照了一张素材图片,本来要进行处理的,如上图九型人格的字,照完后其实可以看到,上图中由于拍照的角度问题,有至少三分之一的面积是书封皮的反光。
threshold效果
我自己常用的二值化函数,因为里面有THRESH_OTSU自动阈值 ,觉得挺方便,使用效果也不错,就直接在程序中用了,结果就出来了一面的效果。
从上面可以看出来,我们如果要进行OCR识别,这样的效果估计只能认出“格”这个字,而九型人三个字都已经无法识别了。
遇到这个情况时,就只能回去补初级知识,看到了自适应二值化adaptiveThreshold函数,最初开始学的时候只是了解了一下,因为里面的有些值需要自己设,觉得麻烦,所以就一直没有在意。所以今天我们就来重新认识下这个函数。
adaptiveThreshold
代码语言:javascript复制void adaptiveThreshold( InputArray src, OutputArray dst,
double maxValue, int adaptiveMethod,
int thresholdType, int blockSize, double C );
参数说明
参数1:InputArray类型的src,输入图像,填单通道,单8位浮点类型Mat即可。
参数2:函数运算后的结果存放在这。即为输出图像(与输入图像同样的尺寸和类型)。
参数3:预设满足条件的最大值。
参数4:指定自适应阈值算法。可选择ADAPTIVE_THRESH_MEAN_C 或 ADAPTIVE_THRESH_GAUSSIAN_C两种。
ADAPTIVE_THRESH_MEAN_C,为局部邻域块的平均值。该算法是先求出块中的均值,再减去常数C。
ADAPTIVE_THRESH_GAUSSIAN_C ,为局部邻域块的高斯加权和。该算法是在区域中(x,y)周围的像素根据高斯函数按照他们离中心点的距离进行加权计算, 再减去常数C。
参数5:指定阈值类型。可选择THRESH_BINARY或者THRESH_BINARY_INV两种。(即二进制阈值或反二进制阈值)。
参数6:表示邻域块大小,用来计算区域阈值,一般选择为3、5、7......等。
参数7:参数C表示与算法有关的参数,它是一个从均值或加权均值提取的常数,可以是负数。
代码演示
我们直接对源图进行普通二值化和自适应二值化的使用,做一个对比,前面加入了灰度,高斯模糊,二值化后的形态学操作,最后再输出显示图片。
代码语言:javascript复制#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
try
{
Mat src = imread("D:/Business/DemoTEST/CPP/opencv-perspective/imgOCR/01.png");
if (src.empty())
{
printf("不能读取图片...n");
getchar();
return -1;
}
resize(src, src, Size(), 0.5, 0.5, INTER_LINEAR);
Mat gray, dst, dst2;
imshow("src", src);
//灰度
cvtColor(src, gray, COLOR_BGR2GRAY);
//高斯模糊
GaussianBlur(gray, gray, Size(3, 3), 0.8,0.8);
imshow("GaussianBlur", gray);
//二值化
adaptiveThreshold(gray, dst, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 11, 2);
threshold(gray, dst2, 0, 255, THRESH_BINARY | THRESH_OTSU);
//形态学操作
Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));
morphologyEx(dst, dst, MORPH_CLOSE, kernel,Point(-1,-1),1);
morphologyEx(dst2, dst2, MORPH_CLOSE, kernel,Point(-1,-1),1);
imshow("dst", dst);
imshow("dst2", dst2);
}
catch (const std::exception& ex)
{
printf("error:%s", ex.what());
}
waitKey(0);
return 0;
}
接下来我们直接看看效果
threshold
V
S
adaptive
Threshold
上面为两种二值化的对比结果
从上面的图可以看出来,用自适应二值化后,九型人格四个字非常明显的可以看出来,不过相对的,燥点也是比较多的,后面我们在这个基础上再看看怎么样处理不必要的东西。
-END-