写点什么

Python OpenCV 泛洪填充,取经之旅第 21 天

发布于: 2021 年 04 月 08 日
Python OpenCV 泛洪填充,取经之旅第 21 天

学习目标

每天 1 小时,365 天成就奇迹。


今天学习 Python OpenCV 泛洪填充相关知识,泛洪填充也叫做水漫填充算法。


原理是 从一个像素点开始,将附近满足像素要求的点,全部填充成指定颜色,直到碰到不满足要求的点。


如果从概念上记忆,常见的有四邻域像素填充法,八邻域像素填充法,基于扫描线的像素填充方法。


对于这些概念,先略过,没有建立整体认知之前,学习任何基础概念都毫无价值。

函数原型

泛洪填充的语法原型如下:


floodFill(image, mask, seedPoint, newVal[, loDiff[, upDiff[, flags]]]) -> retval, image, mask, rect
复制代码


该函数包括七个参数,分别如下:


  • image:操作的图像

  • mask:掩膜,比 image 的高度多 2 个像素,宽度多 2 个像素。填充时不能穿过输入掩码中的非零像素

  • seedPoint:起始的像素点

  • newVal:新的填充值(颜色)

  • loDiff:填充颜色的低值(起始像素点处颜色减去该值)

  • upDiff:填充颜色的高值 (起始像素点处颜色加上该值)

  • flags:操作位标识符,彩色图像一般是FLOODFILL_FIXED_RANGE 指定颜色填充


关于 flags 还找到一个清晰的说明:


当为CV_FLOODFILL_FIXED_RANGE 时,待处理的像素点与种子点作比较,如果满足(s – loDiff, s + upDiff)之间(s 为种子点像素值),则填充;当为CV_FLOODFILL_MASK_ONLY 时,则 mask 不能为空,此时,函数不填充原始图像 img,而是填充掩码图像.

案例代码

测试图片如下:



测试代码如下:


import cv2 as cvimport numpy as np
# 彩色图像填充def fill_color_demo(src): img_copy = src.copy() h, w, ch = src.shape # 声明一个矩形形状,注意高度和宽度都增加 2 个像素 # np.zeros 返回一个给定形状和类型的用 0 填充的数组 mask = np.zeros([h+2, w+2], np.uint8) # 参数1,待使用泛洪填充的图像 # 参数2,掩膜,使用掩膜可以规定是在哪个区域使用该算法,如果是对于完整图像都要使用,则掩膜大小为原图行数 + 2,列数 + 2 # 掩膜,是一个二维的0矩阵,因为只有掩膜上对应为 0 的位置才能泛洪 # 参数3,泛洪填充的种子点,基于该点的像素判断和它相近颜色的像素点,是否被泛洪处理 # 参数4,泛洪区域的新颜色(BGR格式) # 参数5,种子点像素可以向下的像素值 # 参数6,种子点像素可以向上的像素值 # 参数7,泛洪算法的处理模式 cv.floodFill(img_copy, mask, (20, 20), (0, 255, 0), (50, 50, 50), (100, 100, 100), cv.FLOODFILL_FIXED_RANGE) cv.imshow("color_demo", img_copy)

if __name__ == "__main__": src = cv.imread('./25.jpg')
fill_color_demo(src) cv.waitKey() cv.destroyAllWindows()
复制代码


运行之后的效果如下:


关于在设置掩膜的时候,为什么像素要 +2,部分地方给出的解释是:当从 0 行 0 列开始泛洪填充扫描时,mask 多出来的 2 可以保证扫描的边界上的像素都会被处理。暂时先理解一下吧。


关于参数 5 与参数 6,找到如下资料:


从起始的种子点开始,用指定颜色填充与其相连的像素。连通性取决于相邻像素的颜色和亮度,像素在下列情况下被属于重新绘制的区域,公式如下。

在通俗的说明如下:


  • (20, 20):为种子点的位置;

  • (0, 255, 0):为泛洪填充颜色,绿色;

  • (50, 50, 50):以种子点像素三通道值[ b, g, r ]为基准,被填充范为在原图三通道最低值为[ b-50, g-50, r-50 ];

  • (100, 100, 100):以种子点像素三通道值[ b, g, r ]为基准,被填充范为在原图三通道最高值为[ b+100, g+100, r+100];

  • cv.FLOODFILL_FIXED_RANGE:待处理的像素点与种子点作比较,在范围之内,则填充此像素。


在原图像只有像素三通道值[ b-50, g-50, r-50 ] <= [ B , G, R] <=[ b+100, g+100, r+100]在此范围内的都会被指定绿色(0, 255, 0)填充。

二值图像填充

先看代码,注意注释部分。


import cv2 as cvimport numpy as np
def fill_binary(): # 设置一个400*400的矩形 image = np.zeros([400, 400, 3], np.uint8) # 内部填充一个白色正方形
image[100:300, 100:300, :] = 255 cv.imshow("fill_binary", image)
# 设置掩膜 mask = np.ones([402, 402], np.uint8) mask[101:301, 101:301] = 0 # mask不为0的区域不会被填充,mask为0的区域才会被填充 cv.floodFill(image, mask, (200, 200), (255, 255, 0), cv.FLOODFILL_MASK_ONLY) cv.imshow("filled_binary", image)
fill_binary()cv.waitKey(0)cv.destroyAllWindows()
复制代码


这部分代码来源网络,重点理解 FLOODFILL_MASK_ONLY 即可,该值表示从种子点开始,填充掩膜区域。

OpenCV 尾声

1 个小时又过去了,对 Python OpenCV 相关的知识点,你掌握了吗?


做为初学者,还有很多地方学习的不深入,希望你与我一起坚持下去。


空闲之余,可以订阅橡皮擦的爬虫百例课程学习爬虫知识。


想学 Python 爬虫,可以订阅橡皮擦专栏哦~ 🈲🈲🈲🈲 点击发现惊喜 🈲🈲🈲🈲


发布于: 2021 年 04 月 08 日阅读数: 48
用户头像

爬虫 100 例作者,蓝桥签约作者,博客专家 2021.02.06 加入

6 年产品经理+教学经验,3 年互联网项目管理经验; 互联网资深爱好者; 沉迷各种技术无法自拔,导致年龄被困在 25 岁; CSDN 爬虫 100 例作者。 个人公众号“梦想橡皮擦”。

评论

发布
暂无评论
Python OpenCV 泛洪填充,取经之旅第 21 天