opencv学习笔记11(形态学操作应用)

形态学操作应用

  • 原理方法
    • 二值图像与灰度图像上的膨胀操作
    • 二值图像与灰度图像上的腐蚀操作
  • 结构元素
  • 自适应阈值化操作
    • 函数原型
  • 提取水平与垂直线步骤
  • 结果展示
    • 提取水平或垂直线
    • 去除某图片干扰元素
  • 代码实现

原理方法

图像形态学操作时候,可以通过自定义的结构元素实现结构元素对输入图像一些对象敏感、另外一些对象不敏感,这样就会让敏感的对象改变而不敏感的对象保留输出。通过使用两个最基本的形态学操作 – 膨胀与腐蚀,使用不同的结构元素实现对输入图像的操作、得到想要的结果。

  • 膨胀,输出的像素值是结构元素覆盖下输入图像的最大像素值
  • 腐蚀,输出的像素值是结构元素覆盖下输入图像的最小像素值

二值图像与灰度图像上的膨胀操作

opencv学习笔记11(形态学操作应用)_第1张图片

二值图像与灰度图像上的腐蚀操作

opencv学习笔记11(形态学操作应用)_第2张图片

结构元素

  • 上述膨胀与腐蚀过程可以使用任意的结构元素
  • 常见的形状:矩形、园、直线、磁盘形状、砖石形状等各种自定义形状。
    opencv学习笔记11(形态学操作应用)_第3张图片
getStructuringElement(int shape, Size ksize, Point anchor=Point(-1,-1));
参数:
shape:表核的形状,矩形MORPH_RECT;交叉形MORPH_CROSS;椭圆形MORPH_ELLIPSE;
ksize:核尺寸大小,如Size(3,3);
anchor:锚点的位置,锚点只影响形态学运算结果的偏移;
功能:返回指定形状和尺寸的结构元素(返回类型为Mat类型);

自适应阈值化操作

转载于:https://www.cnblogs.com/GaloisY/p/11037350.html
_Challenger

自适应阈值化操作:adaptiveThreshold()函数

在图像阈值化操作中,更关注的是从二值化图像中,分离目标区域和背景区域,但是仅仅通过设定固定阈值很难达到理想的分割效果。而自适应阈值,则是根据像素的邻域块的像素值分布来确定该像素位置上的二值化阈值。这样做的好处:

  1. 每个像素位置处的二值化阈值不是固定不变的,而是由其周围邻域像素的分布来决定的。
  2. 亮度较高的图像区域的二值化阈值通常会较高,而亮度低的图像区域的二值化阈值则会相适应的变小。
  3. 不同亮度、对比度、纹理的局部图像区域将会拥有相对应的局部二值化阈值。

函数原型

 void adaptiveThreshold(
   InputArray src, 
   OutputArray dst,  
   double 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表示与算法有关的参数,它是一个从均值或加权均值提取的常数,可以是负数。(具体见下面的解释)。

对参数4与参数7内容的解释:
自适应阈值化计算大概过程是为每一个象素点单独计算的阈值,即每个像素点的阈值都是不同的,就是将该像素点周围B*B区域内的像素加权平均,然后减去一个常数C,从而得到该点的阈值。B由参数6指定,常数C由参数7指定。

ADAPTIVE_THRESH_MEAN_C,为局部邻域块的平均值,该算法是先求出块中的均值,再减去常数C。

ADAPTIVE_THRESH_GAUSSIAN_C,为局部邻域块的高斯加权和。该算法是在区域中(x, y)周围的像素根据高斯函数按照他们离中心点的距离进行加权计算,再减去常数C。

提取水平与垂直线步骤

  • 输入图像彩色图像 imread
  • 转换为灰度图像 – cvtColor
  • 转换为二值图像 – adaptiveThreshold
  • 定义结构元素
  • 开操作 (腐蚀+膨胀)提取 水平与垂直线或其他操作

结果展示

提取水平或垂直线

  1. 原始图像
    opencv学习笔记11(形态学操作应用)_第4张图片

  2. 灰度化后的图像
    opencv学习笔记11(形态学操作应用)_第5张图片

  3. 对灰度图像取反后的图像(为了后面二值化操作时将我们要提取的水平或垂直线变为前景像素)
    opencv学习笔记11(形态学操作应用)_第6张图片

  4. 二值化后的图像(此时,前景像素水平或垂直线为白色高亮部分,在后面的操作中就可以对白色区域进行开操作,使用特定的结构元素保留水平或垂直线)
    opencv学习笔记11(形态学操作应用)_第7张图片

  5. 此处使用水平结构元素进行的开操作后的图像,结果为水平元素,其余垂直像素都被开操作去除
    opencv学习笔记11(形态学操作应用)_第8张图片

  6. 此处使用垂直结构元素进行的开操作后的图像,结果为水平元素,其余水平像素都被开操作去除
    opencv学习笔记11(形态学操作应用)_第9张图片

  7. 此处使用bitwise_not函数对开操作后的图像进行取反,可将前景像素由白色变为黑色
    opencv学习笔记11(形态学操作应用)_第10张图片

去除某图片干扰元素

使用矩形结构元素对图像进行开操作,去除一些背景元素
(1)左图为原图像,右图为灰度化后的结果opencv学习笔记11(形态学操作应用)_第11张图片
(2)左图为灰度图像取反,右图为自适应二值化结果
opencv学习笔记11(形态学操作应用)_第12张图片
(3)左图为开操作结果,右图为其图像取反结果
opencv学习笔记11(形态学操作应用)_第13张图片

代码实现

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;

//保留水平线(参数为原始图像)
void saveVLine(Mat &src);
//保留垂直线(参数为原始图像)
void saveHLine(Mat &src);
//去除部分背景(参数为原始图像)
void saveRect(Mat &src);

int main(int argc, char** argv) {
	Mat src;
	src = imread("G:/OpenCV/opencv笔记所用图片/X3.png");
	if (!src.data) {
		printf("could not load image...\n");
		getchar();
		return -1;
	}

	imshow("input image", src);	//显示原始图片
	//保留水平线
	saveVLine(src);	//此函数内的结构元素大小可根据需要进行更改,用来提取特定图片特定的水平线
	//保留垂直线
	//saveHLine(src);	//此函数内的结构元素大小可根据需要进行更改,用来提取特定图片特定的水平线
	
	//src = imread("G:/OpenCV/opencv笔记所用图片/X4.png");
	//imshow("input image", src);	//显示原始图片
	//删除X4.png背景元素
	//saveRect(src);	//此函数内的结构元素大小可根据需要进行更改,用去除特定背景元素

	waitKey(0);
	return 0;
}

//水平结构元素整体能从属于的高亮区域被保留,而此结构元素不能从属于的高亮区域则被消除
void saveVLine(Mat &src){
	//对原始图片进行灰度化
	Mat gray_src;
	cvtColor(src, gray_src, CV_BGR2GRAY);		//将图片灰度化
	imshow("gray image", gray_src);				//展示灰度化后的图片
	imshow("~gray_src image", ~gray_src);		//展示~gray_src取反后的图片
	
	//~gray_src表示对图片gray_src取反,为了二值化后的图片前景为白色,背景为黑色,好对图片进行开操作
	//对灰度图像进行自适应阈值化操作(自适应二值化)
	Mat binImg;
	adaptiveThreshold(~gray_src, binImg, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2);	//对图片进行二值化
	imshow("binary image", binImg);

	// 获取水平结构元素(进行开操作使用的结构元素)
	Mat vline = getStructuringElement(MORPH_RECT, Size(src.cols / 16, 1), Point(-1, -1));//此处结构元素的长为图片的1/16,也可以根据实际情况进行设置
	Mat temp,dst;

	//下方先腐蚀后膨胀相当于开运算(可以直接使用开运算代替即可)
	/*erode(binImg, temp, vline);
	dilate(temp, dst, vline);
	imshow("erode and dilate image", dst);
	*/

	//下方为开运算(使用上方的水平结构元素进行开操作,水平结构元素能完全从属于的高亮区域保留,不能完全从属于的高亮区域则变为黑色)
	morphologyEx(binImg, dst, CV_MOP_OPEN, vline);//使用水平结构元素,开运算可以保留水平的去除白亮的竖直线,此水平结构元素保留了水平的线
	imshow("open image", dst);
	bitwise_not(dst, dst);							//对dst图像进行取反操作,使得前景像素由白变黑,背景变白(根据需求进行此操作)
	//blur(dst, dst, Size(3, 3), Point(-1, -1));	//进行模糊操作,是结果看起来平滑一些(也可以舍去此操作)
	imshow("bitwise_not image", dst);

}

//垂直结构元素整体能从属于的高亮区域被保留,而此结构元素不能从属于的高亮区域则被消除
void saveHLine(Mat &src){
	//对原始图片进行灰度化
	Mat gray_src;
	cvtColor(src, gray_src, CV_BGR2GRAY);		//将图片灰度化
	imshow("gray image", gray_src);				//展示灰度化后的图片
	imshow("~gray_src image", ~gray_src);		//展示~gray_src取反后的图片

	//~gray_src表示对图片gray_src取反,为了二值化后的图片前景为白色,背景为黑色,好对图片进行开操作
	//对灰度图像进行自适应阈值化操作(自适应二值化)
	Mat binImg;
	adaptiveThreshold(~gray_src, binImg, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2);	//对图片进行二值化
	imshow("binary image", binImg);

	// 垂直结构元素
	Mat hline = getStructuringElement(MORPH_RECT, Size(1, src.rows / 16), Point(-1, -1));
	Mat temp, dst;

	//下方为开运算(使用上方的垂直结构元素进行开操作,垂直结构元素能完全从属于的高亮区域保留,不能完全从属于的高亮区域则变为黑色)
	morphologyEx(binImg, dst, CV_MOP_OPEN, hline);//使用水平结构元素,开运算可以保留水平的去除白亮的竖直线,此水平结构元素保留了水平的线
	imshow("open image", dst);
	bitwise_not(dst, dst);							//对dst图像进行取反操作,使得前景像素由白变黑,背景变白(根据需求进行此操作)
	imshow("bitwise_not image", dst);
}

//矩形结构元素整体能从属于的高亮区域被保留,而此结构元素不能从属于的高亮区域则被消除(开操作针对的都是高亮区域,故前景像素必须是高亮的)
//此处根据此矩形结构元素大小可以将小于此矩形结构元素的区域进行擦除
void saveRect(Mat &src){
	//对原始图片进行灰度化
	Mat gray_src;
	cvtColor(src, gray_src, CV_BGR2GRAY);		//将图片灰度化
	imshow("gray image", gray_src);				//展示灰度化后的图片
	imshow("~gray_src image", ~gray_src);		//展示~gray_src取反后的图片

	//~gray_src表示对图片gray_src取反,为了二值化后的图片前景为白色,背景为黑色,好对图片进行开操作
	//对灰度图像进行自适应阈值化操作(自适应二值化)
	Mat binImg;
	adaptiveThreshold(~gray_src, binImg, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2);	//对图片进行二值化
	imshow("binary image", binImg);

	// 垂直结构元素
	Mat kRect = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));
	Mat temp, dst;

	//下方为开运算(使用上方的矩形结构元素进行开操作,垂直结构元素能完全从属于的高亮区域保留,不能完全从属于的高亮区域则变为黑色)
	morphologyEx(binImg, dst, CV_MOP_OPEN, kRect);//使用水平结构元素,开运算可以保留水平的去除白亮的竖直线,此水平结构元素保留了水平的线
	imshow("open image", dst);
	bitwise_not(dst, dst);							//对dst图像进行取反操作,使得前景像素由白变黑,背景变白
	imshow("bitwise_not image", dst);
}

你可能感兴趣的:(opencv,c++)