十一、提取水平与垂直线
1、原理方法
图像形态学操作时候,可以通过自定义的结构元素getStructuringElement(模板形状类型,Size(), Point(-1, -1));
对输入图像一些对象敏感、而对另一些对象不敏感,这样就会让敏感的对象改变而不敏感的对象保留输出。通过使用两个最基本的形态学操作—膨胀
与腐蚀
,使用不同的结构元素实现对输入图像的操作、得到想要的结果。
- 膨胀:输出的像素值是结构元素覆盖下输入图像的最大像素值
- 腐蚀:输出的像素值是结构元素覆盖下输入图像的最小像素值
举例说明:例如想检测水平线,可以构造一个类型为MORPH_RECT
尺寸为Size(src.cols / 16, 1)
(一个水平细长条矩形模板)的结构元素,这样经过腐蚀操作,垂直线(二值图像中)会对其敏感从而消除,水平线受其影响较小,经过膨胀操作,最终还原图像中的水平线。
2、提取步骤
- 输入彩色图像
imread
- 转换为灰度图像
cvtCOLOR
- 转换为二值图像
adaptiveThreshold
- 定义结构元素
getStructuringElement
- 开操作(腐蚀+膨胀)提取水平与垂直线()
morphologyEx
3、提取水平线(竖直线)
Mat src, dst;
src = imread("添加图片路径");//1、输入彩色图像
Mat gray_src;
cvtCOLOR(src, gray_src, COLOR_BGR2GRAY);//2、转灰度
Mat binimg;//3、二值化
adaptiveThreshold(~gray_src, binimg, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 15, -2);//分析见文末,灰度图取反,会让灰度图中的黑色线条像素值较高大于阈值,二值化后变成明显的白条。
Mat hline = getStructuringElement(MORPH_RECT, Size(src.cols / 16, 1), Point(-1, -1));//4、获得一个水平的结构元素,Size(列,行);
//Mat vline = getStructuringElement(MORPH_RECT, Size(1, src.rows / 16), Point(-1, -1));//获得一个垂直的结构元素
morphologyEx(bintag, dst, MORPH_OPEN, hline);//5、获取横(竖)线条,用hline(vline)结构元素进行开操作
//也可以分别进行模糊膨胀的操作,如下:
/*Mat temp;//定义一个中间值
erode(bintag, temp, hline);//对二值图像进行腐蚀操作,消除掉竖线条的影响
dilate(temp, dst, hline);//膨胀操作,恢复横线条原有尺寸*/
//blur(dst, dst, Size(3, 3), Point(-1, -1));//模糊操作,输出更圆滑
bitwise_not(dst, dst);//将背景变成白色
imshow("final result", dst);
提取水平线:(从左到右依次为原图;灰度图;二值图;最终结果)
提取垂直线:
解释自适应阈值:参考这里
它的思想不是计算全局图像的阈值,而是根据图像不同区域亮度分布,计算其局部阈值,所以对于图像不同区域,能够自适应计算不同的阈值,因此被称为自适应阈值法。(其实就是局部阈值法)对光照不均匀的图像尤其适用。
adaptiveThreshold(~gray_src, binimg, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 15, -2);`
第一个参数:输入的灰度图像
第二个参数:传出的二值图像
第三个参数:二值图像最大值
第四个参数:指定自适应阈值算法。可选择ADAPTIVE_THRESH_MEAN_C 或 ADAPTIVE_THRESH_GAUSSIAN_C其中一种。
第五个参数:指定阈值类型。可选择THRESH_BINARY或者THRESH_BINARY_INV其中一种。(即二进制阈值或反二进制阈值)。
第六个参数:表示邻域块大小,用来计算区域阈值,一般选择为3、5、7…等。
第七个参数:参数C表示与算法有关的参数,它是一个从均值或加权均值提取的常数,可以是负数。