OpenCV 的洪水填充功能的文档指出:
该函数使用并更新掩码,因此您负责 初始化掩码内容。洪水填充不能跨越非零 掩模中的像素。例如,可以使用边缘检测器输出 作为遮罩以停止边缘填充。可以使用相同的 多次调用该函数时屏蔽以确保填充区域 不重叠。
函数如何更新掩码?它是否将洪水填充中的所有像素设置为某个非零值?
与蒙版种子点相同的连通分量中的所有零值像素都将替换为您指定的值。该值必须添加到
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);
此图像的结果:
然后,创建一个蒙版并对其进行洪水填充:
//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));
给出这个结果:
掩模中的白色像素是边缘检测的结果,而灰色像素是洪水填充的结果。
更新: 作为对评论的回应,标志值
4
指定用于比较颜色值差异的像素邻域。来自文档:
较低位包含函数内使用的连接值 4(默认)或 8。连接性决定了考虑像素的哪些邻居。
当未传递
cv::FLOODFILL_MASK_ONLY
标志时,图像和掩模都会更新,但洪水填充将在任何非零掩模值处停止。
还有Python版本
import cv2
import numpy as np
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)
结果:
根据 Aurelius 的回答,面罩需要归零。
检查来源中的评论,它指出
由于这既是输入参数又是输出参数,因此您必须承担责任 初始化它。洪水填充不能跨越输入掩码中的非零像素。
面罩会影响结果,所以使用前需要调零:
cv::Mat mask;
mask = cv::Mat::zeros(img.rows + 2, img.cols + 2, CV_8UC1);