OpenCV笔记18 图像分割--分水岭算法

35 篇文章 13 订阅

一、基本概念

图像分割是按照一定的原则将一幅图像分割为若干个互不相干的小的局部的过程。分水岭算法会把临近像素间的相似性作为一个重要的参考依据,从而将在空间位置上相近并且灰度值相近的像素点相互连接起来,构成一个封闭的轮廓。封闭性是分水岭的算法的一个重要的特征。

       分水岭算法是一个种基于拓补理论的数学形态学的分割。其思想是把图像看做测地学上的拓补地貌,图像中的买一个像素可以看做是地理上的海报高度,每一个局部的极小值及其影响区域称为集水盆地,而集水盆地的边界便是分水岭。在每一个局部极小值的表面,刺穿一个小孔然后吧整个模型慢慢浸入到水中,随着浸入的加深,每一个局部极小值的影响慢慢的向外面拓展,在两个集水盆地汇合处构建大坝,即形成了分水岭。

分水岭算法的原理: 把图像看做一个平面,图像中灰度值高的区域看做是山峰,灰度值低的地方看做是山谷,不同区域的山谷可以用不同的颜色来标记。

二、waterhord函数

void watershed(
 InputArray image, // 是一个8位的三通道的彩色图像矩阵序列,
InputOutputArray markers  // 必须包含种子的信息,大意说的是在执行分水岭函数watershed之前,必须对第二个参数markers进行处理,它应该包含不同区域的轮廓,每个轮廓有一个自己唯一的编号,轮廓的定位可以通过Opencv中findContours方法实现,这个是执行分水岭之前的要求。算法会根据markers传入的轮廓作为种子(也就是所谓的注水点),对图像上其他的像素点根据分水岭算法规则进行判断,并对每个像素点的区域归属进行划定,直到处理完图像上所有像素点。而区域与区域之间的分界处的值被置为“-1”,以做区分。
);

第一个参数可以不说,但是第二个参数很重要:markers 必须包含种子的信息,在执行分水岭函数watershed之前,必须对第二个参数markers进行处理,它应该包含不同区域的轮廓,每个轮廓有一个自己唯一的编号,轮廓的定位是通过findContours方法来寻找的,这个是执行分水岭之前的要求。算法会根据markers传入的轮廓作为种子(也就是所谓的注水点),对图像上其他的像素点根据分水岭算法规则进行判断,并对每个像素点的区域归属进行划定,直到处理完图像上所有像素点。而区域与区域之间的分界处的值被置为“-1”,以做区分。

三、流程步骤

watershed图像自动分割的实现步骤:

1. 将图像灰度化、滤波、边缘检测(canny算子)

2. 查找轮廓,并且把轮廓信息按照不同的编号绘制到watershed的第二个入参merkers上,相当于标记注水点。

3. waterhord函数进行分水岭运算

4. 填充不同的颜色来查看不同的区域

四、代码

 

 

 ----------------------------------------------------------------------------------------------------------------

 

 

 

 

 

 

// 生产随机数字的
Vec3b RandomColor(int value)
{
	value = value % 255;
	RNG  rng;
	int  b = rng.uniform(0, value);
	int  g = rng.uniform(0, value);
	int  r = rng.uniform(0, value);
	return Vec3b(b,g,r);
}



int main()
{

	// 第一   图像预处理
	Mat src = imread("C:\\Users\\19473\\Desktop\\opencv_images\\540.png");
	if (!src.data)
	{
		printf("could not  load  image....\n");
	}
	imshow("原图",src);
	Mat  gray;
	cvtColor(src,gray,CV_BGR2GRAY);
	GaussianBlur(gray,gray,Size(5,5),2); //高斯滤波
	imshow("高斯图像", gray);

	Canny(gray, gray, 60, 150);
	imshow("Canny Image", gray);

	// 第二  开始找轮廓
	vector<vector<Point>>  contours;
	vector<Vec4i>  hierarchy;
	findContours(gray, contours, hierarchy,RETR_TREE,CHAIN_APPROX_SIMPLE,Point());
	Mat imageContour = Mat::zeros(src.size(),CV_8SC1); // 轮廓的图像
	====================================== watershord的第二个参数,这个参数就是分水岭算法的灵魂=================================

	Mat  marks(src.size(),CV_32S);
	marks = Scalar::all(0);

	==================================================================================================
	int  index = 0;
	int  compCount = 0;
	for ( ; index >= 0; index = hierarchy[index][0], compCount++ )
	{
		// 对 marks 进行标记,对不同的区域进行编号,有多少个轮廓就有多少个注水点
	drawContours(marks, contours, index, Scalar::all(compCount + 1), 1, 8, hierarchy);
	drawContours(imageContour, contours, index, Scalar(255), 1, 8, hierarchy);

	}

	Mat   markshows;
	convertScaleAbs(marks, markshows);
	imshow("markshow ", markshows);
	imshow("轮廓 ", imageContour);

	Mat  watered;
	watershed(src,marks);
	convertScaleAbs(marks, watered);
	imshow("convertScaleAbs", watered);



	// 对每个区域进行颜色填充
	Mat   wateredImage= Mat::zeros(src.size(), CV_8UC3);
	for (int i=0;i<marks.rows;i++) 
	{
		for (int j = 0; j < marks.cols; j++) 
		{
			int gray = marks.at<int>(i,j);
			if (marks.at<int>(i,j)==-1) 
			{
				// 分界线的颜色是白色的
				wateredImage.at<Vec3b>(i,j) = Vec3b(255,255,255);
			}
			else 
			{
				wateredImage.at<Vec3b>(i, j) = RandomColor(gray);
			}
		}
	}


	Mat   wshed;
	//分割并填充颜色的结果跟原始图像融合

	addWeighted(src, 0.4, wateredImage, 0.6, 0, wshed);
	imshow("与原图合并之后的图像", wshed);


	waitKey(0);
	return 0;
}

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉库,它提供了许多图像处理和计算机视觉算法图像分割计算机视觉中的一个重要任务,它可以将图像分多个区域或对象。OpenCV提供了许多图像分割算法,包括阈值分割、区域生长、聚类、水平集方法等。 以下是几个常见的OpenCV图像分割算法的介绍: 1. 阈值分割(Thresholding):阈值分割是一种简单的图像分割方法,它通过将图像中的像素值与一个阈值进行比较,将像素分为不同的类别。OpenCV提供了多种阈值分割算法,如全局阈值和自适应阈值等。 2. 区域生长(Region Growing):区域生长是一种基于像素的图像分割方法,它通过将具有相似属性的像素组合一个区域,并将其他像素标记为背景。OpenCV提供了区域生长算法的实现,可以根据不同的应用场景选择不同的生长算法。 3. 聚类(Clustering):聚类是一种无监督的图像分割方法,它通过将相似的像素组合群集,并将其他像素标记为背景。OpenCV提供了多种聚类算法,如K-means、DBSCAN等。 4. 水平集方法(Level Set Method):水平集方法是近年来发展起来的一种先进的图像分割方法,它通过将图像中的边界或轮廓进行跟踪和演化,将图像分割不同的区域。OpenCV提供了水平集方法的实现,可以根据不同的应用场景选择不同的水平集算法。 在使用OpenCV进行图像分割时,通常需要先对图像进行预处理,如滤波、去噪、缩放等,然后再选择合适的算法进行分割OpenCV还提供了许多工具和函数,用于处理图像数据和执行各种计算机视觉任务。使用OpenCV进行图像分割可以大大提高效率和准确性,适用于各种计算机视觉应用场景。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值