OpenCV 泛洪填充 floodFill()详解

在学OpenCV的时候遇到个函数floodFill()函数有点不解,特地在这里记录一下。
先说说它的参数
floorFillimage, mask , seedPoint, newVal, loDiff, upDiff, flags

参数 说明
image 处理对象
mask 掩膜(后面会说明)
seedPoint 填充的起点
newVal 填充的颜色
loDiff 填充时下限像素的差
upDiff 填充时上限像素的差
flags 填充的方式 :FLOODFILL_FIXED_RANGE 和FLOODFILL_MASK_ONLY

先看例子,先理解一下flags的作用
先看flags=FLOODFILL_FIXED_RANGE的时候

def image_fill(image):
    src = image.copy()   #先创建一个副本
    mask = np.zeros([src.shape[0]+2, src.shape[1]+2, 1], np.uint8)   #根据副本形状建一个掩膜, 注意,长和宽必须要+2,类型只能是uint8
    cv2.floodFill(src, mask, (60, 60), (0, 0, 255), (50,50,50), (50,50,50), cv2.FLOODFILL_FIXED_RANGE)
    #(60,60)代表起始点;(0,0,255)代表填充颜色;loDiff=(50,50,50)代表只能填充比填充颜色小对应数值的点,upDiff同理
    cv2.imshow('flood_fill', src)
    cv2.imshow('mask', mask)

image1 = cv2.imread('lena.jpg')    #原图
cv2.imshow('image1', image1)
image_fill(image1)
c = cv2.waitKey(0)
cv2.destroyAllWindows()

来看看结果
OpenCV 泛洪填充 floodFill()详解_第1张图片
这里mask的作用是限制填充的范围,即floodFill只会填充处理对象对应的mask为0的区域,上面我将mask设置为全部都是0,所以作用范围是整张图片 (注意,作用范围是整张图片不代表会填充整张图,同时还要满足像素和填充颜色的像素差在[loDiff,upDiff]范围内) 那么,如果mask只设置一部分为0会怎么怎么样呢
(下面代码只需要重点关注mask的修改,其余部分同上)

def image_fill(image):
    src = image.copy()
    mask = np.ones([src.shape[0]+2, src.shape[1]+2, 1], np.uint8)   #掩膜,这里将zeros改成了ones
    mask[30:150, 30:150] = 0   #这里将掩膜部分区域设置为0,所有下面限制了只会填充这一部分区域
    cv2.floodFill(src, mask, (60, 60), (0, 0, 255), (50,50,50), (50,50,50), cv2.FLOODFILL_FIXED_RANGE)
    cv2.imshow('flood_fill', src)
    cv2.imshow('mask', mask)

image1 = cv2.imread('lena.jpg')    #原图
cv2.imshow('image1', image1)
image_fill(image1)
c = cv2.waitKey(0)
cv2.destroyAllWindows()

OpenCV 泛洪填充 floodFill()详解_第2张图片
和前面的对比可以看到,这里的填充被截掉了一块,这是就是mask的作用,在前面的代码中mask的像素全部为0,因此对应到图像中就是整张图片都在范围内,而后一次我修改了mask,使其只在 [30:150, 30:150] 这一区域为0,所以填充范围也会被限制在这里。

下面看看flags=cv2.FLOODFILL_MASK_ONLY的例子,在这个填充模式下,可以理解为强制填充,即不需要loDiff和upDiff,范围内全部强制填充,但是有个前提,就是floodFill不会填充他认为不需要填充的地方,这个后面会解释
这里用一个新的例子,在后面还会用lena图来加以区别

def image_fill():
    src = np.zeros([300,300,3], np.uint8)
    mask = np.ones([src.shape[0]+2, src.shape[1]+2, 1], np.uint8)   #掩膜
    mask[30:150, 30:150] = 0
    cv2.floodFill(src, mask, (60, 60), (0, 0, 255), cv2.FLOODFILL_MASK_ONLY)
    cv2.imshow('flood_fill', src)
    cv2.imshow('mask', mask)

image_fill()
c = cv2.waitKey(0)
cv2.destroyAllWindows()

OpenCV 泛洪填充 floodFill()详解_第3张图片
这里可以看到,处理对象对应mask为0的区域被强制填充了,这个很好理解,那么什么叫 不会填充认为不需要填充的区域,再来看个例子
这里相比于上面的例子只是在处理对像多添加了一块灰色的区域,直接看结果即可

def image_fill():
    src = np.zeros([300,300,3], np.uint8)
    src[:150, :150] = 255
    src[100:150, 100:150] = 180
    mask = np.ones([src.shape[0]+2, src.shape[1]+2, 1], np.uint8)   #掩膜
    mask[30:150, 30:150] = 0
    cv2.floodFill(src, mask, (60, 60), (0, 0, 255), cv2.FLOODFILL_MASK_ONLY)
    cv2.imshow('flood_fill', src)
    cv2.imshow('mask', mask)

image_fill()
c = cv2.waitKey(0)
cv2.destroyAllWindows()

OpenCV 泛洪填充 floodFill()详解_第4张图片
可以看到,这里有一小块灰色区域没被填充到,这块灰色的就是之前设置的灰色区域,floorFill函数会认为这一部分不需要填充
下面再来看看lena图

def image_fill(image):
    src = image.copy()
    mask = np.ones([src.shape[0]+2, src.shape[1]+2, 1], np.uint8)   #掩膜
    mask[30:150, 30:150] = 0
    cv2.floodFill(src, mask, (60, 60), (0, 0, 255), cv2.FLOODFILL_MASK_ONLY)  
    cv2.imshow('flood_fill', src)
    cv2.imshow('mask', mask)

image1 = cv2.imread('lena.jpg')    #原图
cv2.imshow('image1', image1)
image_fill(image1)
c = cv2.waitKey(0)
cv2.destroyAllWindows()

OpenCV 泛洪填充 floodFill()详解_第5张图片
发现没有任何变化,这是因为在mask为0区域内存在各种像素,floodFill就会和上面一样认为不需要填充
下面对lena图设置一块黑色区域来看看

def image_fill(image):
    src = image.copy()
    src[10:150, 10:150] = 0        #设置原图指定区域为0
    mask = np.ones([src.shape[0]+2, src.shape[1]+2, 1], np.uint8)   #掩膜
    mask[30:150, 30:150] = 0
    cv2.floodFill(src, mask, (60, 60), (0, 0, 255), cv2.FLOODFILL_MASK_ONLY)  
    cv2.imshow('flood_fill', src)
    cv2.imshow('mask', mask)

image1 = cv2.imread('lena.jpg')    #原图
cv2.imshow('image1', image1)
image_fill(image1)
c = cv2.waitKey(0)
cv2.destroyAllWindows()

OpenCV 泛洪填充 floodFill()详解_第6张图片
果然有效,因为黑色区域内只有0这一个像素,所以会进行填充

解决完了最麻烦的flags,下面就简要说明一下其他参数
seedPoint代表的是起点,即开始填充的点,可以理解为坐标
loDiff和upDiff相当于 填充的像素范围区间 ,即 [填充颜色-loDiff , 填充颜色+upDiff]

你可能感兴趣的:(OpenCV 泛洪填充 floodFill()详解)