本文为原创文章,未经本人允许,禁止转载。转载请注明出处。
1.提取水平线和垂直线
在之前的博客【OpenCV基础】第十课:形态学操作中,我们介绍了很多形态学操作。其中,膨胀与腐蚀操作可以使用任意的结构元素,例如矩形、圆、直线等各种自定义形状。
提取水平线和垂直线的具体步骤见下:
1.1.步骤一:读入原始图像
使用imread
函数读入原始图像:
1.2.步骤二:转换为灰度图像
使用cvtColor
函数将原始图像转换为灰度图像:
当然,也可以直接通过修改imread
的参数直接将原始图像转换成灰度图像读进来。具体请见:【OpenCV基础】第二课:加载、修改、保存图像。
1.3.步骤三:转换为二值图像
这一步我们需要使用一个新的API:adaptiveThreshold
。
该API的参数说明:
1
2
3
4
5
6
7
8
9
void adaptiveThreshold(
InputArray src,
OutputArray dst,
double maxValue,
int adaptiveMethod,
int thresholdType,
int blockSize,
double C
);
InputArray src
是输入图像。OutputArray dst
是输出图像。double maxValue
用于计算第5个参数。int adaptiveMethod
是阈值的计算方法,同样也用于计算第5个参数。有两种方式:ADAPTIVE_THRESH_MEAN_C
:阈值等于blockSize内像素的平均值减去第7个参数C。ADAPTIVE_THRESH_GAUSSIAN_C
:阈值等于blockSize内像素的高斯均值(即高斯加权的均值)减去第7个参数C。
int thresholdType
是图像的转换方式。有八种方式:THRESH_BINARY
、THRESH_BINARY_INV
、THRESH_TRUNC
、THRESH_TOZERO
、THRESH_TOZERO_INV
、THRESH_MASK
、THRESH_OTSU
以及THRESH_TRIANGLE
。这里只介绍涉及二值图像转换的两种方法,其中dst(x,y)
为输出图像$(x,y)$点的像素值,src(x,y)
为输入图像$(x,y)$点的像素值,T(x,y)
为$(x,y)$点的阈值(由参数4获得),maxValue由参数3获得:int blockSize
为正奇数,用法见参数4。double C
用法见参数4,可以为正数、0、负数。
我们尝试将得到的灰度图像通过adaptiveThreshold
转换为二值图像:
1
adaptiveThreshold(gray1, binary1, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2);
发现我们要提取的水平线和垂直线旁边有很宽的白条,会影响到我们的提取效果,因此我们需要先对灰度图像做个取反操作,即~gray1
:
1
adaptiveThreshold(~gray1, binary1, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2);
再来看下效果:
~
通过位运算对图像进行取反操作。例如对于灰度图像来说,像素值的类型是unsigned char
,即八位无符号二进制数。假设像素值是2,其反码为0000 0010
,按位取反得到~2
为1111 1101
,因为是无符号数,所以该二进制数对应的十进制数为253,即255-2。
bitwise_not
也是通过位运算进行取反操作,效果等同于~
。
1.4.步骤四:定义结构元素
使用getStructuringElement
定义我们所需的结构元素。
用于提取水平线的结构元素:
1
Mat hline = getStructuringElement(MORPH_RECT, Size(src.cols / 16, 1), Point(-1, -1));
用于提取垂直线的结构元素:
1
Mat vline = getStructuringElement(MORPH_RECT, Size(1, src.rows / 16), Point(-1, -1));
1.5.步骤五:执行开操作
然后我们通过执行开操作来提取水平线和垂直线。
提取水平线:
提取垂直线:
2.提取验证码
基于第1部分的内容,我们来处理验证码图片中的干扰项。例如要处理的验证码图片见下:
我们依然按照1.1~1.5这5个步骤来处理这张图片。但是我们需要稍作修改。
针对第四步,我们这次使用矩形的结构元素:
1
Mat kernel=getStructuringElement(MORPH_RECT,Size(3,3),Point(-1,-1));
使用矩形结构元素的好处在于可以帮助我们去除各种线段(不局限于水平线或者垂直线),并且也可以去除图片中的散点。
此外,对最终提取得到的图像做了取反操作,使其看起来更顺眼一点: