如何用Python OpenCV实现Hard Light与HSL混合模式的灰度图着色?
灰度图着色优化方案求助
需求说明
- 处理对象:可能带有Alpha通道的灰度图(仅含亮度信息,无色彩)
- 着色目标:用指定RGB颜色生成保留原灰度图明暗特征的单色调图像
- 边界情况:若无灰度信息(或输入为纯色/空白图),则生成与原图尺寸一致的目标颜色填充图
现有问题
我尝试的代码生成结果过暗,无法达到GIMP 2的着色效果:
import cv2 import numpy as np def colorize(img, rgb): grey = img[..., 0] channels = [grey * (channel / 256) for channel in rgb[::-1]] if img.shape[2] == 4: channels.append(img[..., 3]) return np.dstack(channels).astype(np.uint8)
注:原图像使用cv2.IMREAD_UNCHANGED加载(带透明度),目标RGB值为(128, 192, 255)
研究方向与现有实现
经分析,正确的着色方式有两种:
- Hard Light混合模式:创建目标颜色的填充图,与原图以Hard Light模式融合
- HSL色彩替换:将原图的色相(Hue)和饱和度(Saturation)替换为目标颜色的对应分量,保留原图的亮度(Lightness)
我已自行实现了部分混合模式,但纯numpy实现效率不足,无法满足GUI实时着色需求:
import numpy as np import cv2 def scale_down(base: np.ndarray, top: np.ndarray) -> np.ndarray: return base / 255, top / 255 def scale_up(img: np.ndarray) -> np.ndarray: return (img * 255).astype(np.uint8) def blend_overlay(base: np.ndarray, top: np.ndarray) -> np.ndarray: mask = base >= 0.5 result = np.zeros_like(base) result[~mask] = (mult_2 := (2 * base * top))[~mask] result[mask] = (2 * base + 2 * top - mult_2 - 1)[mask] return result def blend_hardlight(base: np.ndarray, top: np.ndarray) -> np.ndarray: return blend_overlay(top, base) def blend_multiply(base: np.ndarray, top: np.ndarray) -> np.ndarray: return base * top def blend_screen(base: np.ndarray, top: np.ndarray) -> np.ndarray: return base + top - base * top def blend_softlight(base: np.ndarray, top: np.ndarray) -> np.ndarray: return (1 - 2 * top) * base**2 + 2 * base * top def blend_colorburn(base: np.ndarray, top: np.ndarray) -> np.ndarray: result = np.zeros_like(base) result[ones := base == 1.0] = 1 result[zeros := top == 0.0] = 0 mask = (~ones == ~zeros) == (ones == 0) result[mask] = 1 - np.minimum(1, (1 - base[mask]) / top[mask]) return result
求助内容
寻求基于cv2和numpy的高效实现:
- Hard Light混合模式的灰度图着色方案
- HSL色彩替换模式的灰度图着色方案
注:该功能用于Python+PyQt6开发的AI井字棋游戏,需支持GUI元素的实时自定义着色
内容的提问来源于stack exchange,提问作者Ξένη Γήινος
相关产品推荐
相关产品推荐

