带掩模的OpenCV floodfill

时间:2013-05-23 04:33:51

标签: opencv flood-fill

OpenCV的Floodfill函数的documentation表明:

  

该功能使用并更新掩码,因此您需要负责   初始化掩码内容。洪水填充不能跨越非零   掩码中的像素。例如,可以使用边缘检测器输出   作为面具停止填充边缘。可以使用相同的   掩码中多次调用函数以确保填充区域   不重叠。

该功能如何更新掩码?它是否将填充中的所有像素设置为某个非零值?

3 个答案:

答案 0 :(得分:25)

与掩码的种子点相同的连接组件中的所有零值像素都将替换为您指定的值。必须将此值添加到flags参数,左移8位:

uchar fillValue = 128;
cv::floodFill(img, mask, seed, cv::Scalar(255) ,0, cv::Scalar(), cv::Scalar(), 4 | cv::FLOODFILL_MASK_ONLY | (fillValue << 8));

下面是一个简单但可能具有启发性的例子。像这样创建一个图像:

//Create simple input image
cv::Point seed(4,4);
cv::Mat img = cv::Mat::zeros(100,100,CV_8UC1);
cv::circle(img, seed, 20, cv::Scalar(128),3);

此图片中的结果:

Original image

然后,创建一个面具并充满它:

//Create a mask from edges in the original image
cv::Mat mask;
cv::Canny(img, mask, 100, 200);
cv::copyMakeBorder(mask, mask, 1, 1, 1, 1, cv::BORDER_REPLICATE);

//Fill mask with value 128
uchar fillValue = 128;
cv::floodFill(img, mask, seed, cv::Scalar(255) ,0, cv::Scalar(), cv::Scalar(), 4 | cv::FLOODFILL_MASK_ONLY | (fillValue << 8));

给出了这个结果:

Flood-filled mask

掩模中的白色像素是边缘检测的结果,而灰色像素是泛光填充的结果。

<强>更新 响应于该评论,标志值4指定用于比较颜色值差异的像素邻域。来自文档:

  

较低位包含函数内使用的连接值4(默认值)或8。连通性决定了像素的哪些邻居被考虑。

cv::FLOODFILL_MASK_ONLY标志未通过时,两者图像和蒙版都会更新,但是填充将在任何非零掩码值处停止。

答案 1 :(得分:5)

和python版本

im = cv2.imread("seagull.jpg")
h,w,chn = im.shape
seed = (w/2,h/2)

mask = np.zeros((h+2,w+2),np.uint8)

floodflags = 4
floodflags |= cv2.FLOODFILL_MASK_ONLY
floodflags |= (255 << 8)

num,im,mask,rect = cv2.floodFill(im, mask, seed, (255,0,0), (10,)*3, (10,)*3, floodflags)

cv2.imwrite("seagull_flood.png", mask)

(来自维基媒体的海鸥图片:https://commons.wikimedia.org/wiki/Commons:Quality_images#/media/File:Gull_portrait_ca_usa.jpg

结果:result

答案 2 :(得分:0)

根据Aurelius的回答,掩码需要清零。

在源中检查评论,它指出

  

由于这既是输入参数又是输出参数,因此您必须承担责任   初始化它。填充填充不能跨越输入蒙版中的非零像素。

遮罩会影响结果,因此在使用前需要将其清零:

cv::Mat mask;
mask = cv::Mat::zeros(img.rows + 2, img.cols + 2, CV_8UC1);