openCV学习笔记(二十三) —— 形态学滤波—— 开运算、闭运算、形态学梯度、顶帽、黑帽

原理

 

 

 

程序

#include<opencv2/opencv.hpp>

using namespace std;
using namespace cv;

/*
	宏定义
*/
#define ORIGINAL_WINDOW_NAME	"【原始图】"
#define OPEN_CLOSE_WINDOW_NAME	"【开运算/闭运算】"
#define ERODE_DILATE_WINDOW_NAME	"【腐蚀/膨胀】"
#define TOP_BLACK_HAT_WINDOW_NAME	"【顶帽/黑帽】"
#define GRADIENT_WINDOW_NAME	"形态学梯度"

/*
	全局变量声明
*/
Mat g_srcImage, g_dstImage;	//原始图和效果图
int g_nElementShape = MORPH_RECT;	//元素结构的形状

									//变量接收的TrackBar位置参数
int g_nMaxIteratorNum = 10;
int g_nOpenCloseNum = 0;
int g_nErodeDilateNum = 0;
int g_nTopBlackHatNum = 0;
int g_nGradientNum = 0;

/*
	全局函数声明
*/
static void onOpenClose(int, void *);
static void onErodeDilate(int, void *);
static void onTopBlackHat(int, void *);
static void onGradient(int, void *);

/*
	main()函数
*/
int main()
{
	//载入原图
	g_srcImage = imread("test.jpg");
	if (!g_srcImage.data)
	{
		printf("读取srcImage错误!\n");
		return -1;
	}

	//显示原始图
	namedWindow(ORIGINAL_WINDOW_NAME);
	imshow(ORIGINAL_WINDOW_NAME, g_srcImage);

	//创建四个窗口
	namedWindow(OPEN_CLOSE_WINDOW_NAME);
	namedWindow(ERODE_DILATE_WINDOW_NAME);
	namedWindow(TOP_BLACK_HAT_WINDOW_NAME);
	namedWindow(GRADIENT_WINDOW_NAME);

	//参数赋值
	g_nOpenCloseNum = 9;
	g_nErodeDilateNum = 9;
	g_nTopBlackHatNum = 2;
	g_nGradientNum = 9;

	//分别为四个窗口创建滚动条
	createTrackbar("迭代值", OPEN_CLOSE_WINDOW_NAME, &g_nOpenCloseNum, g_nMaxIteratorNum * 2 + 1, onOpenClose);
	createTrackbar("迭代值", ERODE_DILATE_WINDOW_NAME, &g_nErodeDilateNum, g_nMaxIteratorNum * 2 + 1, onErodeDilate);
	createTrackbar("迭代值", TOP_BLACK_HAT_WINDOW_NAME, &g_nTopBlackHatNum, g_nMaxIteratorNum * 2 + 1, onTopBlackHat);
	createTrackbar("迭代值", GRADIENT_WINDOW_NAME, &g_nGradientNum, g_nMaxIteratorNum * 2 + 1, onGradient);

	//轮询获取按键信息
	while (true)
	{
		int c;

		//执行回调函数
		onOpenClose(g_nOpenCloseNum, NULL);
		onErodeDilate(g_nErodeDilateNum, NULL);
		onTopBlackHat(g_nTopBlackHatNum, NULL);

		//获取按键
		c = waitKey(0);

		//按下键盘按键Q或者ESC, 程序退出
		if ((char)c == 'q' || (char)c == 27)
		{
			break;
		}

		//按下键盘按键1,使用椭圆(Ellipse)结构元素MORPH_ELLIPSE
		if ((char)c == 49)	//键盘按键1的ASCII码为49
		{
			printf("使用椭圆结构元素");
			g_nElementShape = MORPH_ELLIPSE;
		}
		//按下键盘按键2,使用矩形(Rectangle)结构元素MORPH_RECT
		else if ((char)c == 50)	//键盘按键2的ASCII码为50
		{
			printf("使用矩形结构元素");
			g_nElementShape = MORPH_RECT;
		}
		//按下键盘按键3,使用十字形(Cross-shaped)结构元素MORPH_RECT
		else if ((char)c == 51)	//键盘按键3的ASCII码为50
		{
			printf("使用十字形结构元素");
			g_nElementShape = MORPH_CROSS;
		}
		//按下键盘空格,在矩形、椭圆、十字形结构元素中循环
		else if ((char)c == ' ')
		{
			printf("在矩形、椭圆、十字形结构元素中循环");
			g_nElementShape = (g_nElementShape + 1) % 3;
		}
	}

	destroyAllWindows();

	return 0;
}

/*
	开运算/闭运算窗口的回调函数
*/
static void onOpenClose(int, void *)
{
	//偏移量的定义
	int offset = g_nOpenCloseNum - g_nMaxIteratorNum;	//偏移量
	int AbsoluteOffset = offset > 0 ? offset : -offset;	//偏移量绝对值

														//自定义核
	Mat element = getStructuringElement(g_nElementShape, Size(AbsoluteOffset * 2 + 1, AbsoluteOffset * 2 + 1), Point(AbsoluteOffset, AbsoluteOffset));

	//进行操作
	if (offset < 0)
	{
		printf("开运算...\n");
		morphologyEx(g_srcImage, g_dstImage, MORPH_OPEN, element);
	}
	else
	{
		printf("闭运算...\n");
		morphologyEx(g_srcImage, g_dstImage, MORPH_CLOSE, element);
	}

	imshow(OPEN_CLOSE_WINDOW_NAME, g_dstImage);
}

/*
腐蚀/膨胀窗口的回调函数
*/
static void onErodeDilate(int, void *)
{
	//偏移量的定义
	int offset = g_nErodeDilateNum - g_nMaxIteratorNum;	//偏移量
	int AbsoluteOffset = offset > 0 ? offset : -offset;	//偏移量绝对值

														//自定义核
	Mat element = getStructuringElement(g_nElementShape, Size(AbsoluteOffset * 2 + 1, AbsoluteOffset * 2 + 1), Point(AbsoluteOffset, AbsoluteOffset));

	//进行操作
	if (offset < 0)
	{
		printf("腐蚀运算...\n");
		erode(g_srcImage, g_dstImage, element);
	}
	else
	{
		printf("膨胀运算...\n");
		dilate(g_srcImage, g_dstImage, element);
	}

	imshow(ERODE_DILATE_WINDOW_NAME, g_dstImage);
}

/*
顶帽/黑帽窗口的回调函数
*/
static void onTopBlackHat(int, void *)
{
	//偏移量的定义
	int offset = g_nTopBlackHatNum - g_nMaxIteratorNum;	//偏移量
	int AbsoluteOffset = offset > 0 ? offset : -offset;	//偏移量绝对值

														//自定义核
	Mat element = getStructuringElement(g_nElementShape, Size(AbsoluteOffset * 2 + 1, AbsoluteOffset * 2 + 1), Point(AbsoluteOffset, AbsoluteOffset));

	//进行操作
	if (offset < 0)
	{
		printf("顶帽运算...\n");
		morphologyEx(g_srcImage, g_dstImage, MORPH_TOPHAT, element);
	}
	else
	{
		printf("黑帽运算...\n");
		morphologyEx(g_srcImage, g_dstImage, MORPH_BLACKHAT, element);
	}

	imshow(TOP_BLACK_HAT_WINDOW_NAME, g_dstImage);
}


/*
形态学梯度窗口的回调函数
*/
static void onGradient(int, void *)
{
	//偏移量的定义
	int offset = g_nGradientNum - g_nMaxIteratorNum;	//偏移量
	int AbsoluteOffset = offset > 0 ? offset : -offset;	//偏移量绝对值

														//自定义核
	Mat element = getStructuringElement(g_nElementShape, Size(AbsoluteOffset * 2 + 1, AbsoluteOffset * 2 + 1), Point(AbsoluteOffset, AbsoluteOffset));

	//进行操作
	printf("形态学梯度运算...\n");
	morphologyEx(g_srcImage, g_dstImage, MORPH_GRADIENT, element);

	imshow(GRADIENT_WINDOW_NAME, g_dstImage);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值