opencv学习笔记8——形态学滤波

一、膨胀和腐蚀


二、开运算、闭运算、形态学梯度、顶帽、黑帽






示例代码:

#include<opencv2\core\core.hpp>
#include<opencv2\highgui\highgui.hpp>
#include<opencv2\imgproc\imgproc.hpp>
#include<iostream>
using namespace cv;
using namespace std;
Mat g_srcImage, g_dstImage;
int g_nElementShape = MORPH_RECT;
int g_nMaxIterationNum = 10;
int g_nOpenCloseNum = 0;
int g_nErodeDilateNum = 0;
int g_nTopBlackHatNum = 0;
static void on_OpenClose(int, void *)
{
	int offset = g_nOpenCloseNum - g_nMaxIterationNum;//偏移量
	int Absolute_offset = offset > 0 ? offset : -offset;//偏移量绝对值
	Mat element = getStructuringElement(g_nElementShape,
		Size(Absolute_offset * 2 + 1, Absolute_offset * 2 + 1),
		Point(Absolute_offset, Absolute_offset));
	if (offset < 0)
		morphologyEx(g_srcImage, g_dstImage, MORPH_OPEN, element);
	else
		morphologyEx(g_srcImage, g_dstImage, MORPH_CLOSE, element);
	imshow("<开/闭运算>", g_dstImage);
}
static void on_ErodeDilate(int, void *)
{
	int offset = g_nOpenCloseNum - g_nMaxIterationNum;//偏移量
	int Absolute_offset = offset > 0 ? offset : -offset;//偏移量绝对值
	Mat element = getStructuringElement(g_nElementShape,
		Size(Absolute_offset * 2 + 1, Absolute_offset * 2 + 1),
		Point(Absolute_offset, Absolute_offset));
	if (offset < 0)
		erode(g_srcImage, g_dstImage,element);
	else
		dilate(g_srcImage, g_dstImage,element);
	imshow("<腐蚀/膨胀>", g_dstImage);
}
static void on_TopBlackHat(int, void*)
{
	int offset = g_nTopBlackHatNum - g_nMaxIterationNum;
	int Absolute_offset = offset > 0 ? offset : -offset;//偏移量绝对值
	Mat element = getStructuringElement(g_nElementShape,
		Size(Absolute_offset * 2 + 1, Absolute_offset * 2 + 1),
		Point(Absolute_offset, Absolute_offset));
	if (offset < 0)
		morphologyEx(g_srcImage, g_dstImage, MORPH_TOPHAT, element);
	else
		morphologyEx(g_srcImage, g_dstImage, MORPH_BLACKHAT, element);
	imshow("<顶帽/黑帽>", g_dstImage);
}
int main()
{
	g_srcImage = imread("lena.jpg");
	if (!g_srcImage.data)
	{
		cout << "读取图片错误\n";
		return false;
	}
	namedWindow("<原图>");
	imshow("<原图>", g_srcImage);
	namedWindow("<开/闭运算>",1);
	namedWindow("<腐蚀/膨胀>", 1);
	namedWindow("<顶帽/黑帽>",1);

	g_nOpenCloseNum = 9;
	g_nErodeDilateNum = 9;
	g_nTopBlackHatNum = 2;
	createTrackbar("迭代值", "<开/闭运算>", &g_nOpenCloseNum,
		g_nMaxIterationNum * 2 + 1, on_OpenClose);
	createTrackbar("迭代值", "<腐蚀/膨胀>", &g_nOpenCloseNum, 2 * g_nMaxIterationNum + 1, on_ErodeDilate);
	createTrackbar("迭代值", "<顶帽/黑帽>", &g_nTopBlackHatNum, g_nMaxIterationNum * 2 + 1, on_TopBlackHat);

	while (1)
	{
		int c;
		on_OpenClose(g_nOpenCloseNum, 0);
		on_ErodeDilate(g_nErodeDilateNum, 0);
		on_TopBlackHat(g_nTopBlackHatNum, 0);

		c = waitKey(0);
		//按q或esc退出
		if ((char)c == 'q' || (char)c == 27)
			break;
		//按1,椭圆
		if ((char)c == 49)
			g_nElementShape = MORPH_ELLIPSE;
		//按2,矩形
		if ((char)c == 50)
			g_nElementShape = MORPH_RECT;
		//按3,十字形
		else if ((char)c == 51)
			g_nElementShape = MORPH_CROSS;
		//space键,在矩形、椭圆、十字之间循环
		else if ((char)c == ' ')
			g_nElementShape = (g_nElementShape + 1) % 3;
	}
	return 0;
}

效果:


理解:

后面的那些都是基于腐蚀和膨胀的。

开运算——先腐蚀再膨胀,消除细小物体,在纤细点处分离物体。

闭运算——先膨胀后腐蚀,排除小型黑洞。

形态学梯度——膨胀-腐蚀,将团块的边缘突出出来,保留物体边缘轮廓。

顶帽——原图-开运算,分离比临近点亮的一些斑块,在一幅图像具有大幅背景并且微小物品有规律,可以用这个进行背景提取。

黑帽——原图-闭运算,分离比临近点暗的一些斑块,效果图有很完美的轮廓。


猜你喜欢

转载自blog.csdn.net/qq_36718317/article/details/80313450