1.漫水填充原理
图像分割中的漫水填充(Flood Fill)算法是一种基于区域增长的像素分类方法。其原理是在图像中从种子点开始,逐渐向周围扩展,并根据一定的条件决定是否将相邻的像素归属于同一区域。
漫水填充的基本原理如下:
- 选择种子点。
- 以种子点为中心,判断4邻域或者8邻域的像素值与种子点像素值的差值,将差值小于阈值的像素点添加进区域内。
- 将新加入的像素点作为新的种子点,反复执行Step2,直到没有新的像素点被添加进该区域。
2.漫水填充分割方法函数floodFill()
int floodFill(InputOutputArray image,
InputOutputArray mask,
Point seedPoint,
Scalar newVal,
CV_OUT Rect* rect = 0,
Scalar loDiff = Scalar(),
Scalar upDiff = Scalar(),
int flags = 4);
参数说明:
-
image:输入输出图像,图像数据类型可以为CV_8U或者CV_32F的单通道或者三通道图像。
-
mask:掩码矩阵,尺寸比如输入图像的宽和高各大2的单通道图像,用于标记漫水填充的区域。
-
seedPoint:种子点。
-
newVal:归入种子点区域内像素点的新像素值。
-
rect:种子点漫水填充区域的最小矩形边界,默认值为0,表示不输出边界。
-
loDiff:添加进种子点区域条件的下界差值,当邻域某像素点的像素值与种子点像素值的差值大于该值时,该像素点被添加进种子点所在的区域。
-
upDiff:添加进种子点区域条件的上界差值,当种子点像素值与邻域某像素点的像素值的差值小于该值时,该像素点被添加进种子点所在的区域。
-
flags:漫水填充方法的操作标志,其由三部分构成,分别表示邻域种类、掩码像素值和填充算法的规则。
返回值:
-
返回一个整数值,表示实际填充的像素数量。
示例代码:
void floodFill_f(Mat mat){
// 如果是四通道图像,则要把四通道图像转换成三通道
Mat image;
cv::cvtColor(mat, image, cv::COLOR_BGRA2BGR);
RNG rng(10086);//随机数,用于随机生成像素
//设置操作标志flags
int connectivity=4;//连接领域方式
int maskVal=255;//掩码图像的数值
int flags=connectivity|(maskVal<<8)|FLOODFILL_FIXED_RANGE;//漫水填充操作方式标志
Rect rect; // 输出的填充区域
//设置与选中像素点的差值
Scalar loDiff=Scalar (20,20,20);
Scalar upDiff=Scalar (20,20,20);
//声明掩摸矩阵变量
Mat mask=Mat::zeros(image.rows+2,image.cols+2,CV_8UC1);
ostringstream ss;
for(int i=0;i<20;i++){
//随机产生图像中某一像素值
int py=rng.uniform(0,image.rows-1);
int px=rng.uniform(0,image.cols-1);
Point point=Point (px,py);
//彩色图像中填充的像素值
Scalar newVal=Scalar (rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255));
//浸水填充函数
int area= floodFill(image,mask,point,newVal,&rect,loDiff,upDiff,flags);
//输出像素点和填充的像素数目
ss<<"像素点x:"<<point.x<<" y:"<<point.y<<" 填充像素数目"<<area<<endl;
}
LOGD("%s",ss.str().c_str());
//输出填充的图像结果
imwrite("/sdcard/DCIM/img.png",image);
imwrite("/sdcard/DCIM/mask.png",mask);
}
输出图像:
掩码图像: