形态学操作

目录

1、腐蚀

1.1 腐蚀目的

1.2 原理与代码实现

2、膨胀

3、应用

3.1 开闭运算、形态学梯度

 3.1.1 开运算

 3.1.2 闭运算

 3.1.3 形态学梯度

 3.1.4 顶帽与黑帽运算

3.2 相关函数


形态学操作常用于对二值化图像的操作

1、腐蚀

1.1 腐蚀目的

去除图像中微小物体,分离较近的两个物体

1.2 原理与代码实现

 

//绘制包含区域函数
void drawState(Mat &img, int number, Mat centroids, Mat stats, String str)
{
	RNG rng(10086);
	vector<Vec3b> colors;
	for (int i = 0; i < number; i++)
	{
		//使用均匀分布的随机数确定颜色
		Vec3b vec3 = Vec3b(rng.uniform(0, 256), rng.uniform(0, 256), rng.uniform(0, 256));
		colors.push_back(vec3);
	}

	for (int i = 1; i < number; i++)
	{
		//中心位置
		int center_x = centroids.at<double>(i, 0);
		int center_y = centroids.at<double>(i, 1);

		//矩形边框
		int x = stats.at<int>(i, CC_STAT_LEFT);
		int y = stats.at<int>(i, CC_STAT_TOP);
		int w = stats.at<int>(i, CC_STAT_WIDTH);
		int h = stats.at<int>(i, CC_STAT_HEIGHT);

		//中心位置绘制
		circle(img, Point(center_x, center_y), 2, Scalar(0, 255, 0), 2, 8, 0);

		//外接矩形
		Rect rect(x, y, w, h);
		rectangle(img, rect, colors[i],1,8, 0);
		putText(img,format("%d",i),Point(center_x,center_y),FONT_HERSHEY_SIMPLEX, 0.5,Scalar(0, 0,255),1);
	}
	imshow(str,img);
}
//形态学操作-腐蚀
int test1()
{
	//生成用于腐蚀的原图像
	Mat src = (Mat_<uchar>(6,6) << 0,0,0,0,255,0,
	    0, 255, 255,255,255, 255,
		0, 255,255, 255,255, 0, 
		0,255,255, 255, 255, 0, 
		0,255, 255,255,255,0, 
		0, 0, 0, 0,0, 0);

	Mat struct1, struct2;

	struct1 = getStructuringElement(0,Size(3,3));//矩形结构元素
	struct2 = getStructuringElement(1,Size(3,3));//十字结构元素

	Mat erodeSrc;//存放腐蚀后的图像

	erode(src, erodeSrc,struct2);
	
	namedWindow("src", WINDOW_GUI_NORMAL);
	namedWindow("erodeSrc",WINDOW_GUI_NORMAL);
	
	imshow("src", src) ;
	imshow("erodeSrc", erodeSrc); 
	cout << "文字腐蚀验证" << endl;
	waitKey(0);

	Mat LearnCV_black = imread("F:/testMap/rice.png", IMREAD_ANYCOLOR);

	Mat erode_black1,erode_black2;
	
	//黑背景图像腐蚀
	erode(LearnCV_black,erode_black1,struct1); 
	erode(LearnCV_black, erode_black2,struct2); 
	
	imshow("LearnCV_black", LearnCV_black);
	imshow("erode_blackl", erode_black1); 
	imshow("erode_black2", erode_black2);
	cout << "验证腐蚀对小连通域的去除"<< endl;
	waitKey(0);
		
	Mat img = imread("F:/testMap/rice.png");
	if (img.empty())
	{
		cout << "请确认图像文件名称是否正确"<< endl;
		return -1;
	}
	Mat img2;
	copyTo(img,img2,img);//克隆一个单独的图像,用于后期图像绘制
	Mat rice,riceBW;

	//将图像转成二值图像,用于统计连通域
	cvtColor(img,rice,COLOR_BGR2GRAY);
	threshold(rice,riceBW,50,255,THRESH_BINARY);

	Mat out,stats, centroids;
	
	//统计图像中连通域的个数
	int number = connectedComponentsWithStats(riceBW,out,stats,centroids, 8,CV_16U);
	drawState(img,number,centroids,stats,"未腐蚀时统计连通域");//绘制图像

	erode(riceBW, riceBW, struct1);//对图像进行腐蚀
	number = connectedComponentsWithStats(riceBW, out,stats, centroids,8,CV_16U); 
	drawState(img2,number,centroids,stats,"腐蚀后统计连通域");//绘制图像


	waitKey(0);
	return 0;
}

2、膨胀

 同上

 

 

//形态学操作-膨胀
int test2()
{

	//生成用于膨胀的原图像
		Mat src = (Mat_<uchar>(6, 6) << 0,0,0,0,255,0,
		0,255,255,255,255,255,
		0,255,255,255,255,0, 
		0,255,255,255,255, 0, 
		0,255,255,255,255,0, 
		0, 0,0,0,0, 0);

	Mat struct1, struct2;

	struct1 = getStructuringElement(0,Size(3,3));//矩形结构元素
	struct2 = getStructuringElement(1,Size(3,3));//十字结构元素
	
	Mat erodeSrc;//存放膨胀后的图像
	dilate(src, erodeSrc, struct2);//膨胀

	namedWindow("src",WINDOW_GUI_NORMAL);
	namedWindow("dilateSrc",WINDOW_GUI_NORMAL); 
	imshow("src",src) ;
	imshow("dilateSrc", erodeSrc);

	cout << "文字膨胀" << endl; 
	waitKey(0);

	Mat LearnCV_black = imread("F:/testMap/learnCV_black.png", IMREAD_ANYCOLOR);
	Mat dilate_black1, dilate_black2;

	//黑背景图像膨胀
	dilate(LearnCV_black, dilate_black1, struct1); 
	dilate(LearnCV_black,dilate_black2, struct2); 
	imshow("LearnCV_black", LearnCV_black);
	imshow("dilate_black1", dilate_black1); 
	imshow("dilate_black2", dilate_black2); 


	waitKey(0);
	return 0;
}

3、应用

3.1 开闭运算、形态学梯度

3.1.1 开运算

先腐蚀再膨胀

 3.1.2 闭运算

先膨胀再腐蚀

 3.1.3 形态学梯度

膨胀结果减去腐蚀结果

 3.1.4 顶帽与黑帽运算

原图像减去开运算

 闭运算减去原图像

 

3.2 相关函数

 

//形态学应用
int test3()
{
	//用于验证形态学应用的二值化矩阵
	Mat src = (Mat_<uchar>(9, 12) << 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255, 0,
		0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0,
		0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0,
		0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0,
		0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0,
		0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255, 0,
		0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);

	namedWindow("src", WINDOW_NORMAL);//可以自由调节显示图像的尺寸
	imshow("src", src);

	//3×3矩形结构元素
	Mat kernel = getStructuringElement(0, Size(3, 3));

	//对二值化矩阵进行形态学操作
	Mat open, close, gradient, tophat, blackhat, hitmiss;

	//对二值化矩阵进行开运算
	morphologyEx(src, open, MORPH_OPEN, kernel);
	namedWindow("open", WINDOW_NORMAL);//可以自由调节显示图像的尺寸
	imshow("open", open);

	//对二值化矩阵进行闭运算
	morphologyEx(src, close, MORPH_CLOSE, kernel);
	namedWindow("close", WINDOW_NORMAL);//可以自由调节显示图像的尺寸
	imshow("close", close);

	//对二值化矩阵进行梯度运算
	morphologyEx(src, gradient, MORPH_GRADIENT, kernel);
	namedWindow(" gradient", WINDOW_NORMAL);//可以自由调节显示图像的尺寸
	imshow("gradient", gradient);

	//对二值化矩阵进行顶帽运算
	morphologyEx(src, tophat, MORPH_TOPHAT, kernel);
	namedWindow("tophat", WINDOW_NORMAL);//可以自由调节显示图像的尺寸
	imshow("tophat ", tophat);

	//对二值化矩阵进行黑帽运算
	morphologyEx(src, blackhat, MORPH_BLACKHAT, kernel);
	namedWindow("blackhat", WINDOW_NORMAL);//可以自由调节显示图像的尺寸
	imshow("blackhat", blackhat);

	//对二值化矩阵进行击中击不中变换
	morphologyEx(src, hitmiss, MORPH_HITMISS, kernel);
	namedWindow("hitmiss", WINDOW_NORMAL);//可以自由调节显示图像的尺寸
	imshow("hitmiss", hitmiss);


	cout << "用图像验证形态学操作效果" << endl;
	waitKey(0);

	Mat keys = imread("F:/testMap/key.png", IMREAD_GRAYSCALE);
	imshow("原图像", keys);

	threshold(keys, keys, 80, 255, THRESH_BINARY); //二值化
	imshow("二值化后的keys", keys);

	//5×5矩形结构元素
	Mat kernel_keys = getStructuringElement(0, Size(5, 5));
	Mat open_keys, close_keys, gradient_keys, tophat_keys, blackhat_keys, hitmiss_keys;

	//对图像进行开运算
	morphologyEx(keys, open_keys, MORPH_OPEN, kernel_keys);
	imshow("open_keys", open_keys);

	//对图像进行闭运算
	morphologyEx(keys, close_keys, MORPH_CLOSE, kernel_keys);
	imshow("close_keys", close_keys);

	//对图像进行梯度运算
	morphologyEx(keys, gradient_keys, MORPH_GRADIENT, kernel_keys);
	imshow(" gradient_keys", gradient_keys);

	//对图像进行顶帽运算
	morphologyEx(keys, tophat_keys, MORPH_TOPHAT, kernel_keys);
	imshow("tophat_keys", tophat_keys);

	//对图像进行黑帽运算
	morphologyEx(keys, blackhat_keys, MORPH_BLACKHAT, kernel_keys);
	imshow("blackhat_keys", blackhat_keys);

	//对图像进行击中击不中变换
	morphologyEx(keys, hitmiss_keys, MORPH_HITMISS, kernel_keys);
	imshow("hitmiss_keys", hitmiss_keys);

	waitKey(0);
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zhang丶&|!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值