版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
OpenCV中自带有基于meanshift的分割方法pyrMeanShiftFiltering()。由函数名pyrMeanShiftFiltering可知,这里是将meanshift算法和图像金字塔相结合用来分割的。
void PyrMeanShiftFiltering( const CvArr* srcarr, //输入图像
CvArr* dstarr, //输出图像
double sp, //颜色域半径
double sr, //空间域半径
int max_level, //金字塔最大层数
CvTermCriteria termcrit ) //迭代终止条件</span>
/********************************
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
)
效果图:
原图
meanshift分割
漫水填充后
步骤:
(1) 读入图像并显示
扫描二维码关注公众号,回复:
7203366 查看本文章
(2) 设置参数并进行分割
(3) 设置掩模进行漫水填充
程序:
//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<uchar>(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;
}