提取图像中的水平线和垂直线属于基础的形态学操作的应用,原理:根据要提取图形来定义一个特定的结构元素,然后以这个结构相素去遍历图像,进行一系列形态学操作,以此过滤掉其他特征的图形,达到提取的效果。
示例:提取下图中的水平线。
解决思路如下:
1.将原图转化为灰度图像(cvtColor()函数)。
2.运用自适应阈值花操作:adaptiveThreshold函数,根据像素的邻域块的像素值分布来确定该像素位置上的二值化阈值,将原本的灰度图像转化成二值化图像。
函数原型: void adaptiveThreshold(InputArray src, OutputArray dst,ouble maxValue, int adaptiveMethod,int thresholdType, int bolckSize, double C)
参数说明
参数1:InputArray类型的src,输入图像,填单通道,单8位浮点类型Mat即可。
参数2:函数运算后的结果存放在这。即为输出图像(与输入图像同样的尺寸和类型)。
参数3:预设满足条件的最大值。
参数4:指定自适应阈值算法。可选择ADAPTIVE_THRESH_MEAN_C 或 ADAPTIVE_THRESH_GAUSSIAN_C两种。
参数5:指定阈值类型。可选择THRESH_BINARY或者THRESH_BINARY_INV两种。(即二进制阈值或反二进制阈值)。
参数6:表示邻域块大小,用来计算区域阈值,一般选择为3、5、7…等。
参数7:参数C表示与算法有关的参数,它是一个从均值或加权均值提取的常数,可以是负数。
3.根据需要提取的图形特征定义结构元素,这里我们要提取水平线,相应地,我们就定义一个水平的矩形结构元素。
eg:Mat kernel =getStructuringElement(MORPH_RECT, Size(dest.cols / 16, 1), Point(-1, -1));
4.用着结构元素进行形态学操作,过滤其他形状。这里我们使用的是开操作,这样当结构元素遍历图像时,就过滤掉了与其不吻合的其他元素,只保留水平线。
5.最后在通过bitwise_not取反。
实现代码如下:
#include <opencv2\opencv.hpp>
#include<opencv2\imgproc\imgproc.hpp>
#include <iostream>
using namespace cv;
int main()
{
Mat src,gray_src,dest, dst;
src = imread("C:/Users/86159/Desktop/pp.png"); //载入图片
cvtColor(src, gray_src, COLOR_BGR2GRAY); //转化成灰度图
adaptiveThreshold(~gray_src, dest, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2); //转化为二值化图像
Mat kernel = getStructuringElement(MORPH_RECT, Size(dest.cols / 16, 1), Point(-1, -1)); //定义结构元素
morphologyEx(dest, dst, MORPH_OPEN, kernel); //开操作提取水平线
bitwise_not(dst, dst); //取反
imshow("效果图", dst);
waitKey(0);
return 0;
}
希望对读者有所帮助,喜欢的话可以关注一下我的公众号,我会把学习笔记发在上面,大家可以一起共同学习!