仅自学做笔记用,后续有错误会更改
理论
图像在进行形态学操作的时候, 可以通过自定义的结构元素实现结构元素对输入图像的一些对象敏感丶对另外一些对象不敏感, 这样就会让敏感的对象改变而不敏感的对象保留输出。 通过使用两个最基本的形态学操作 - 膨胀 与 腐蚀 , 使用不同的结构元素实现对输入图像的操作,从而得到想要的结果。
这里再简单介绍一下 膨胀 与 腐蚀 操作:
- 膨胀: 输出的像素值, 是结构元素(核)覆盖下的输入图像的最大像素值
- 腐蚀: 输出的像素值, 是结构元素(核)覆盖下的输入图像的最小像素值
膨胀与腐蚀的具体原理与示例, 可以翻到第7课再看看。
上述中, 通过 膨胀 与 腐蚀 来进行提取的操作, 其中的自定义结构元素, 也就是我们说的kernel(核), 常见的核的形状:矩形丶圆丶直线丶磁盘形状丶钻石形状以及各种自定义形状。
提取水平线与垂直线的操作流程:
- 输入图像(一般是彩色图像,imread)
- 转换为灰度图像(cvtColor)
- 转换为二值图像(adaptiveThreshold)
- 定义结构元素
- 开操作(先腐蚀,后膨胀)提取 水平线与垂直线
相关API
转换为二值图像 - 通过adaptiveThreshold这个接口去转换
- adaptiveThreshold(
- Mat src, //输入的灰度图像
- Mat dst, //输出的二值图像
- double maxValue, //超过阈值的部分取值是多少(对于cv.THRESH_BINARY而言)
- int adaptiveMethod, //自适应阈值算法,只能选其中之一: ADAPTIVE_THRESH_MEAN_C,ADAPTIVE_THRESH_GAUSSIAN_C
- int thresholdType, //阈值类型, 必须为THRESH_BINARY或THRESH_BINARY_INV
- int blockSize, //核的大小
- double C, //常量, 可以是正数,0,负数, 它是减去平均或加权平均值后的常数值,通常为正数
);
代码示例
Mat src,dst;
src = imread(...);
// 先显示原图
namedWindow("input image", CV_WINDOW_AUTOSIZE);
imshow("input image", src);
// 再显示灰度图
Mat gray_dst;
cvtColor(src, gray_dst, CV_BGR2GRAY);
namedWindow("gray image", CV_WINDOW_AUTOSIZE);
imshow("gray image", gray_dst);
// 再显示二值图
Mat binImg_dst;
adaptiveThreshold(~gray_dst, binImg_dst, 255, ADAPTIVE_THRESH_MEAN_C, THRSH_BINARY, 15, -2); //注意这个gray_dst有个取反符号,表示先取反再进行二值转换, 如果是白色背景的图, 就会变为黑色
namedWindow("binary image", CV_WINDOW_AUTOSIZE);
imshow("binary image", binImg_dst);
// 再显示开操作之后的图
Mat hline = getStructuringElement(MORPH_RECT, Size(src.cols / 16, 1), Point(-1, -1)); //横线, 核的y轴为1
Mat vline = getStructuringElement(MORPH_RECT, Size(1, src.rows / 16), Point(-1, -1)); //纵线, 核的x轴为1
// 提取水平线
// Mat temp;
// erode(binImg_dst, temp, hline); // 先腐蚀
// dilate(temp, dst, hline); // 再膨胀
// bitwise_not(dst, dst); // 图像取反操作, 将黑色背景再转为白色
// namedWindow("hline image", CV_WINDOW_AUTOSIZE);
// imshow("hline image", dst);
// 提取垂直线
// morphologyEx(binImg, dst, CV_MOP_OPEN, vline); // 直接进行开操作
// bitwise_not(dst, dst);
// namedWindow("vline image", CV_WINDOW_AUTOSIZE);
// imshow("vline image", dst);
// 提取水平线, 并使用均值滤波对结果进行优化显示
Mat temp;
erode(binImg_dst, temp, hline); // 先腐蚀
dilate(temp, dst, hline); // 再膨胀
bitwise_not(dst, dst); // 图像取反操作, 将黑色背景再转为白色
blur(dst, dst, Size(3, 3), Point(-1, -1)); // 均值滤波,进行边缘处理, 使图像更和谐一些
namedWindow("hline image", CV_WINDOW_AUTOSIZE);
imshow("hline image", dst);
效果截图:
原图:
灰度图:
取反过后的二值图:
提取水平线(再取反将背景变为白色):
提取垂直线(同上都是取反了的,背景一样变回为白色, 右下边那个几个短线是文字A的垂直部分,也被提取了)):
使用均值滤波过后的水平线提取