魔术棒填充颜色
这篇教学会介绍 OpenCV 的 floodFill 方法 ( 洪水填充、魔术棒填充 ),透过这个方法,可以将图像中某个像素周围颜色类似的像素,填满相同的颜色,实现类似 Photoshop 或其他绘图软件中的“魔术棒填充”功能。
快速导览:
因为程序中的 OpenCV 会需要使用镜头或 GPU,所以请使用本机环境 ( 参考:使用 Python 虚拟环境 ) 或使用 Anaconda Jupyter 进行实作 ( 参考:使用 Anaconda ) ,并安装 OpenCV 函数库 ( 参考:OpenCV 函数库 )。
floodFill 的用法
floodFill 方法可以将图像中某个像素周围颜色类似的像素 ( 定义颜色最高与最低之间的范围 ),填满相同的颜色,使用后会直接改变来源图像,使用方法如下:
cv2.floodFill(img, mask, seedPoint, newVal, loDiff, upDiff, flags)
相关参数说明如下:
| 参数 | 说明 |
|---|---|
| img | 要改变的图像。 |
| mask | 遮罩,大小必须为图像的长宽+2。 |
| seedPoint | 像素座标 (x, y)。 |
| newVal | 新的填色 ( 不支援透明度 )。 |
| loDiff | 颜色数值往下的差异范围。 |
| upDiff | 颜色数值往上的差异范围。 |
| flags | cv2.FLOODFILL_FIXED_RANGE 套用到原始图片 ( 填满对应 mask 中颜色为 0 的部分 ),FLOODFILL_MASK_ONLY 套用到 mask。 |
使用 floodFill 快速填色
为了避免使用后改变了原始图像 ( 使用 floodFill 会直接改变原始图像 ),可以额外定义一个函数进行处理,函数一开始先复制来源图像,处理后再将图像回传,处理的过程如下:
- seedPoint 取得图像 (100, 10) 位置的颜色信息。
- newVal 预备将类似 ( 并链接在一起 ) 的颜色换成红色 (0,0,255)。
- 颜色范围往下蓝色 100,绿色 100,红色 60,例如原始颜色 (100,100,100),则往下到 (0,0,40) 都会被选取。
- 颜色范围往上蓝色 100,绿色 100,红色 100,例如原始颜色 (100,100,100),则往下到 (200,200,200) 都会被选取。
import cv2
import numpy as np
img = cv2.imread('japan.jpeg')
def floodFill(source, mask, seedPoint, newVal, loDiff, upDiff, flags=cv2.FLOODFILL_FIXED_RANGE):
result = source.copy()
cv2.floodFill(result, mask=mask, seedPoint=seedPoint, newVal=newVal, loDiff=loDiff, upDiff=upDiff, flags=flags)
return result
h, w = img.shape[:2] # 取得原始影像的長寬
mask = np.zeros((h+2,w+2,1), np.uint8) # 製作 mask,長寬都要加上 2
output = floodFill(img, mask, (100,10), (0,0,255), (100,100,60), (100,100,100))
cv2.imshow('oxxostudio', output)
cv2.waitKey(0)
cv2.destroyAllWindows()
完成后执行,就可以看到图像的某一部分变成了红色。
延续上方的程序,如果遮罩中有白色有黑色,则会填满对应到黑色的区域。
import cv2
import numpy as np
img = cv2.imread('japan.jpeg')
def floodFill(source, mask, seedPoint, newVal, loDiff, upDiff, flags=cv2.FLOODFILL_FIXED_RANGE):
result = source.copy()
cv2.floodFill(result, mask=mask, seedPoint=seedPoint, newVal=newVal, loDiff=loDiff, upDiff=upDiff, flags=flags)
return result
h, w = img.shape[:2]
mask = np.zeros((h+2,w+2,1), np.uint8) # 全黑遮罩
mask = 255 - mask # 變成全白遮罩
mask[0:100,0:200] = 0 # 江左上角長方形變成黑色
output = floodFill(img, mask, (100,10), (0,0,255), (100,100,60), (200,200,200))
cv2.imshow('oxxostudio', output)
cv2.waitKey(0)
cv2.destroyAllWindows()
微信扫码关注
抖音扫码关注