【OpenCV】Meanshift图像分割

 OpenCV中自带有基于meanshift的分割方法pyrMeanShiftFiltering()。由函数名pyrMeanShiftFiltering可知,这里是将meanshift算法和图像金字塔相结合用来分割的。

void PyrMeanShiftFiltering( const CvArr* srcarr,          //输入图像
				    CvArr* dstarr,        //输出图像
				   double  sp,            //颜色域半径
				    double sr,            //空间域半径
				       int max_level,     //金字塔最大层数                    
			    CvTermCriteria termcrit )     //迭代终止条件
/********************************
image       输入三通道8bit彩色图像,同时作为输出。
mask        是掩模图像,它的大小是输入图像的长宽左右各加1个像素,
            mask一方面作为输入的掩模图像,另一方面也会在填充的过程中不断被更新。
            floodFill漫水填充的过程并不会填充mask上灰度值不为0的像素点,
            所以可以使用一个图像边缘检测的输出作为mask,
            这样填充就不会填充或越过边缘轮廓。
            mask在填充的过程中被更新的过程是这样的:
            每当一个原始图上一个点位(x,y)被填充之后,
            该点位置对应的mask上的点(x+1,y+1)的灰度值随机被设置为1(原本该点的灰度值为0),
            代表该点已经被填充处理过。
seedPoint   是漫水填充的起始种子点。
newVal      被充填的色彩值。
rect        可选的参数,用于设置floodFill函数将要重绘区域的最小矩形区域;
loDiff
upDiff      用于定义跟种子点相比色彩的下限值和上限值,
            介于种子点减去loDiff和种子点加上upDiff的
            值会被填充为跟种子点同样的颜色。
第八个参数,定义漫水填充的模式,用于连通性、扩展方向等的定义。
*/
int cv::floodFill(  InputOutputArray    image,
                    InputOutputArray    mask,
                    Point   seedPoint,
                    Scalar  newVal,
                    Rect *  rect = 0,
                    Scalar  loDiff = Scalar(),
                    Scalar  upDiff = Scalar(),
                    int     flags = 4 
)

效果图:

原图

【OpenCV】Meanshift图像分割_第1张图片

meanshift分割

【OpenCV】Meanshift图像分割_第2张图片

漫水填充后

【OpenCV】Meanshift图像分割_第3张图片

 

步骤:

(1) 读入图像并显示

(2) 设置参数并进行分割

(3) 设置掩模进行漫水填充

【OpenCV】Meanshift图像分割_第4张图片

程序:

 //meanshift程序
#include "opencv2/highgui/highgui.hpp"  
#include "opencv2/core/core.hpp"  
#include "opencv2/imgproc/imgproc.hpp"  

using namespace cv;
using namespace std;

int main(int argc, char** argv)
{
	Mat src_img = imread("2.jpg"); //读入图像,RGB三通道    
	imshow("src 1210", src_img);
	Mat dst_img;                    //分割后图像  
	int spatialRad = 50;        //空间窗口大小  
	int colorRad = 50;          //色彩窗口大小  
	int maxPyrLevel = 2;        //金字塔层数  
	pyrMeanShiftFiltering(src_img, dst_img, spatialRad, colorRad, maxPyrLevel); //色彩聚类平滑滤波  
	imshow("dst 1210", dst_img);
	RNG rng = theRNG();
	Mat mask(dst_img.rows + 2, dst_img.cols + 2, CV_8UC1, Scalar::all(0));  //掩模  
	for (int y = 0; y < dst_img.rows; y++)
	{
		for (int x = 0; x < dst_img.cols; x++)
		{
			if (mask.at(y + 1, x + 1) == 0)  //非0处即为1,表示已经经过填充,不再处理  
			{
				Scalar newVal(rng(256), rng(256), rng(256));
				floodFill(dst_img, mask, Point(x, y), newVal, 0, Scalar::all(5), Scalar::all(5)); //执行漫水填充  
			}
		}
	}
	imshow("漫水填充", dst_img);
	waitKey();
	return 0;
}

你可能感兴趣的:(OpenCV)