1. C/C++

OpenCV-第十话-形态学操作

一.形态学操作(morphology operators)

#图像形态学操作 – 基于形状的一系列图像处理操作的合集,主要是基于集合论基础上的形态学数学

#形态学有四个基本操作:腐蚀、膨胀、开、闭

#膨胀与腐蚀是图像处理中最常用的形态学操作手段

1.膨胀

#跟卷积操作类似,假设有图像A和结构元素B,结构元素B在A上面移动,其中B定义其中心为锚点,计算B覆盖下A的最大像素值用来替换锚点的像素,其中B作为结构体可以是任意形状。

2.腐蚀

#腐蚀跟膨胀操作的过程类似,唯一不同的是以最小值替换锚点重叠下图像的像素值。

3.相关API

#getStructuringElement(int shape, Size ksize, Point anchor)

– 形状 (MORPH_RECT \MORPH_CROSS \MORPH_ELLIPSE)

– 大小

– 锚点 默认是Point(-1, -1)意思就是中心像素

 

#dilate(src, dst, kernel)

#erode(src, dst, kernel)

4.动态调整结构元素大小(方便测试使用)

#TrackBar – createTrackbar(const String & trackbarname, const String winName,  int* value, int count, Trackbarcallback func, void* userdata=0)

其中最中要的是 callback 函数功能。如果设置为NULL就是说只有值update,但是不会调用callback的函数。

5.腐蚀和膨胀代码

/*
OpenCV 形态学操作学习
Michael Jiang<sencom1997@outlook.com>
2019年7月25日09:14:49
*/

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

using namespace cv;
int main()
{
	//读取图像
	Mat src = imread("D:/test10.png", IMREAD_COLOR);

	//判断读取是否成功
	if (src.empty()) {
		printf("pic load failed!\n");
		return -1;
	}

	//先腐蚀后膨胀
	Mat dst;
	Mat temp;
	Mat kernel = getStructuringElement(MORPH_RECT, Size(9, 9));
	erode(src, temp, kernel);
	dilate(temp, dst, kernel);
	//显示窗口
	imshow("src", src);
	imshow("dst", dst);
	waitKey(0);
	return 0;
}

 

二.具体形态学操作

#开操作- open

#闭操作- close

#形态学梯度- Morphological Gradient

#顶帽 – top hat

#黑帽 – black hat

1.开操作

就是先腐蚀后膨胀(如上面的演示)

可以去掉小的对象,假设对象是前景色,背景是黑色

2.闭操作

先膨胀后腐蚀

可以填充小的洞(fill hole),假设对象是前景色,背景是黑色

3.形态学梯度

膨胀减去腐蚀

又称为基本梯度(其它还包括-内部梯度、方向梯度)

4.顶帽

顶帽 是原图像与开操作之间的差值图像

5.黑帽

黑帽是闭操作图像与源图像的差值图像

#############################

相关API

morphologyEx(src, dest, CV_MOP_BLACKHAT, kernel);

– Mat src – 输入图像

– Mat dest – 输出结果

– int OPT – CV_MOP_OPEN/ CV_MOP_CLOSE/ CV_MOP_GRADIENT / CV_MOP_TOPHAT/ CV_MOP_BLACKHAT 形态学操作类型

-Mat kernel 结构元素

-int Iteration 迭代次数,默认是1

############################

代码演示

1.开操作,上面的先腐蚀后膨胀就可以改写为

//先腐蚀后膨胀
Mat dst;
Mat temp;
Mat kernel = getStructuringElement(MORPH_RECT, Size(9, 9));
//erode(src, temp, kernel);
//dilate(temp, dst, kernel);
morphologyEx(src, dst, MORPH_OPEN, kernel);

2.闭操作

//先腐蚀后膨胀
Mat dst;
Mat temp;
Mat kernel = getStructuringElement(MORPH_RECT, Size(9, 9));
//erode(src, temp, kernel);
//dilate(temp, dst, kernel);
morphologyEx(src, dst, MORPH_CLOSE, kernel);

… …以此类推

三.提取水平和垂直直线

1.提取步骤

1.输入图像彩色图像 imread

2.转换为灰度图像 – cvtColor

3.转换为二值图像 – adaptiveThreshold

4.定义结构元素

5.开操作 (腐蚀+膨胀)提取 水平与垂直线

 

转换为二值图像

adaptiveThreshold(

Mat src, // 输入的灰度图像

Mat dest, // 二值图像

double maxValue, // 二值图像最大值

int adaptiveMethod // 自适应方法,只能其中之一

// ADAPTIVE_THRESH_MEAN_C , ADAPTIVE_THRESH_GAUSSIAN_C

int thresholdType,// 阈值类型

int blockSize, // 块大小

double C // 常量C 可以是正数,0,负数

)

2.代码实现

/*
OpenCV 形态学操作-提取水平和垂直直线学习
Michael Jiang<sencom1997@outlook.com>
2019年7月25日09:55:00
*/

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

using namespace cv;
int main()
{
	//读取图像
	Mat src = imread("D:/test10.png", IMREAD_COLOR);

	//判断读取是否成功
	if (src.empty()) {
		printf("pic load failed!\n");
		return -1;
	}
	Mat dst;
	Mat temp;
	//BGR转灰度
	cvtColor(src, temp, COLOR_BGR2GRAY);

	//转换为二值图像
	adaptiveThreshold(~temp, dst, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 23, -2);

	//定义结构元素
	int xsize = dst.cols / 30;
	int ysize = dst.rows / 30;
	Mat xKernel = getStructuringElement(MORPH_RECT, Size(xsize, 1));
	Mat yKernel = getStructuringElement(MORPH_RECT, Size(1, ysize));
	
	//开操作
	Mat xfin;
	Mat yfin;
	morphologyEx(dst, xfin, MORPH_OPEN, xKernel);
	morphologyEx(dst, yfin, MORPH_OPEN, yKernel);

	//显示窗口
	imshow("src", src);
	imshow("dst", dst);
	imshow("xfin", xfin);
	imshow("yfin", yfin);
	waitKey(0);
	return 0;
}

 

 

四.去除图片中的干扰项

代码实现

/*
OpenCV 形态学操作-去除干扰项学习
Michael Jiang<sencom1997@outlook.com>
2019年7月25日10:37:23
*/

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

using namespace cv;
int main()
{
	//读取图像
	Mat src = imread("D:/test10.png", IMREAD_COLOR);

	//判断读取是否成功
	if (src.empty()) {
		printf("pic load failed!\n");
		return -1;
	}
	Mat dst;
	Mat temp;
	//BGR转灰度
	cvtColor(src, temp, COLOR_BGR2GRAY);

	//转换为二值图像
	adaptiveThreshold(~temp, dst, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2);

	//定义矩形结构元素
	Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));

	//进行开操作
	Mat fin;
	morphologyEx(dst, fin, MORPH_OPEN, kernel);

	//显示窗口
	imshow("src", src);
	imshow("dst", dst);
	imshow("fin", fin);
	waitKey(0);
	return 0;
}