算法的原理很简单,就是从一个点开始,将附近满足像素要求的点全部填充成指定的颜色,直到封闭区域内的所有像素点都被填充新颜色为止。
我们以这张图片为例
代码如下
import cv2 as cv
import numpy as np
def fill_color_demo(image):
copyimg = image.copy()
h, w = image.shape[:2]
mask = np.zeros([h+2, w+2], np.uint8)
cv.floodFill(copyimg, mask, (40, 30), (0, 255, 255), (100,100, 100), (50, 50, 50), cv.FLOODFILL_FIXED_RANGE)
cv.imshow("floodfill", copyimg)
cv.imwrite("D:/opencv/copyimg.jpg", copyimg)
print("--------- Hello Python ---------")
src = cv.imread("D:/opencv/color.jpg")
print(src.shape)
cv.namedWindow("color", cv.WINDOW_AUTOSIZE)
cv.imshow("color", src)
fill_color_demo(src)
print(src.shape)
cv.waitKey(0)
cv.destroyAllWindows()
floodFill共包含7个参数:
1.操作的图像
2.掩模
3.起始的像素点
4.填充的颜色
5.loDiff:填充颜色的低值(起始像素点处颜色减去该值)
6.upDiff:填充颜色的高值 (起始像素点处颜色加上该值)
7.填充的方法,彩色图像一般是FLOODFILL_FIXED_RANGE 指定颜色填充
下面是我个人的理解:
运行该函数时,首先找到图像上的起始像素点,从该点开始,将其附近满足填充颜色范围(起始像素点处颜色减加低高值)的像素点填充上指定颜色,直至整个封闭区域都填充完毕。
此处的封闭区域是指满足填充范围的区域,如果碰到不满足范围的区域,则会停止填充
运行代码后,结果如下:
根据代码内容,填充过程如下:
首先找到(40,30)点,以该点为起始点,该点BGR值为(0, 0, 255),减去低值为(0, 0, 155), 加上高值为(50, 50, 255),因此在该范围的像素点将被填充为红色,但白色的BGR值为(255,255,255),黑色的BGR值为(0,0,0),不在该范围内,因此在碰到黑白区域时,填充停止。所以这就解释了为什么右下角的红色没有被填充
改变填充的高低值,将颜色范围变成整个BGR区域:
cv.floodFill(copyimg, mask, (40, 30), (0, 255, 255), (100,100, 255), (255, 255, 255), cv.FLOODFILL_FIXED_RANGE)
print(src.shape)得到的是图像的垂直尺寸、水平尺寸以及通道数目,但在设置起始像素点的坐标时,却是按照(水平位置, 垂直位置)来定义的
在设置mask时,需注意要设置为h+2, w+2
除了FLOODFILL_FIXED_RANGE外,还有一种填充方法:
FLOODFILL_MASK_ONLY,mask的指定的位置为零时才填充,不为零不填充
def fill_binary():
image = np.zeros([400, 400, 3], np.uint8)
image[100:300, 100:300, :] = 255
cv.imshow("image", image)
mask = np.ones([402, 402, 1], np.uint8)
mask[101:301, 101:301] = 0
cv.floodFill(image, mask, (200, 200), (0, 0, 255), cv.FLOODFILL_MASK_ONLY)
cv.imshow("fill_binary", image)
首先定义一张图片,颜色为黑色,类型为uint8,然后将中间区域颜色设为白色
再设置mask,将整个mask区域的值设为1,中间区域的值设为0(FLOODFILL_MASK_ONLY只对0进行填充),此处仍要注意h+2!