meanshift segmentation(原理+源码)

一、meanshift 分割算法原理;

 

参考论文:Mean shift: A robust approach toward feature space analysis , PAMI, 2002

mean shift认为中心是概率密度( probalility density function  )的 极大值点 ,沿着梯度方向,自适应调整步长(越靠近极值点步长越小),迭代搜索 。

其算法主要分为二步:

 1. 模点搜索,即找每个数据点的类中心,以中心的颜色代替自己的颜色,从而平滑图像。但模点搜索得到的模点太多,并且很多模点挨得很近,若果将每个模点都作为一类的话,类别太多,容易产生过分割,即分割太细,所以要合并掉一些模点。

2.模点聚类。模点聚类后所得到的分割区域中,有些区域所包含的像素点太少,这些小区域也不是我们想要的,需要再次合并。OpenCV采用 flood fill 函数实现。


二、meanshift 分割算法在opencv上的实现;

CV_EXPORTS_W void pyrMeanShiftFiltering(InputArray src,//输入图像

OutputArray dst,//输出图像
                                         
double sp,
//空间域半径

double sr, //颜色域半径

                                                                                      int maxLevel=1,分割金字塔的最大层数
                               
TermCriteria termcrit=TermCriteria
(TermCriteria::MAX_ITER+TermCriteria::EPS,5,1) ) ;//迭代的终止条件

           其中,double sp,//空间域半径,double sr,//颜色域半径,int maxLevel=1,分割金字塔的最大层数,这三个值越大,程序运行的速度越慢


源码范例

#include 
#include 
#include 
#include 
#include

using namespace cv;
using namespace std;

Mat src, dst;


void meanshift_seg(int spatialRad, int colorRad, int maxPryLevel)
{

	调用meanshift图像金字塔进行分割

	pyrMeanShiftFiltering(src, dst, spatialRad, colorRad, maxPryLevel);
	RNG rng = theRNG();
	Mat mask(dst.rows + 2, dst.cols + 2, CV_8UC1, Scalar::all(0));
	for (int i = 0; i < dst.rows; i++)    //opencv图像等矩阵也是基于0索引
	{
		for (int j = 0; j < dst.cols; j++)
		{
			if (mask.at(i + 1, j + 1) == 0)
			{
				Scalar newcolor(rng(256), rng(256), rng(256));
				floodFill(dst, mask, Point(j, i), newcolor, 0, Scalar::all(1), Scalar::all(1));
			}
		}
	}
	
}



int main(int argc, uchar* argv[])

{
	clock_t start, end;
	start = clock();

	src = imread("1.jpg");
	meanshift_seg(10,10,1);

	imshow("src", src);
	imshow("dst", dst);

	end = clock();
	cout << "Run time: " << (double)(end - start) / CLOCKS_PER_SEC << "S" << endl;

	waitKey();//无限等待用户交互响应
}

原图

meanshift segmentation(原理+源码)_第1张图片

分割后的图像

meanshift segmentation(原理+源码)_第2张图片





你可能感兴趣的:(图像处理)