1. 程式人生 > >opencv學習筆記8——形態學濾波

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;
}

效果:


理解:

後面的那些都是基於腐蝕和膨脹的。

開運算——先腐蝕再膨脹,消除細小物體,在纖細點處分離物體。

閉運算——先膨脹後腐蝕,排除小型黑洞。

形態學梯度——膨脹-腐蝕,將團塊的邊緣突出出來,保留物體邊緣輪廓。

頂帽——原圖-開運算,分離比臨近點亮的一些斑塊,在一幅影象具有大幅背景並且微小物品有規律,可以用這個進行背景提取。

黑帽——原圖-閉運算,分離比臨近點暗的一些斑塊,效果圖有很完美的輪廓。