如果您希望混合类似于感知颜色混合(更接近人类预期的混合颜色),您可以在LAB 颜色空间中应用混合。
优势:
与 RGB 和 CMYK 颜色模型不同,CIELAB 旨在接近人类视觉。
我已经在我的关注answer(在底部)中演示了主体。
- 将
img 和 scr2 从 BGR 转换为 LAB 色彩空间。
- 在 LAB 色彩空间中应用
addWeighted。
- 将结果从 LAB 转换为 BGR 颜色空间。
由于scr2 的白色背景混合困扰我,我还将img 的原始像素复制到blend,其中scr2 中的像素是白色的。
这是一个完整的代码示例:
import cv2
import numpy as np
img = cv2.imread("inputImage.png")
scr2 = np.full_like(img, 255)
img_lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB) # Convert color space from BGR to LAB color space
# adding lines
cv2.line(scr2, (100, 0), (100, img.shape[1]), (0, 255, 0), 3)
cv2.line(scr2, (300, 0), (300, img.shape[1]), (255, 0, 0), 3)
cv2.line(scr2, (500, 0), (500, img.shape[1]), (0, 0, 255), 3)
scr2_lab = cv2.cvtColor(scr2, cv2.COLOR_BGR2LAB) # Convert color space from BGR to LAB color space
# blending
#blend = cv2.addWeighted(img, 0.7, scr2, 0.3, 0)
blend_lab = cv2.addWeighted(img_lab, 0.7, scr2_lab, 0.3, 0) # Blend images in LAB color space
blend = cv2.cvtColor(blend_lab, cv2.COLOR_LAB2BGR) # Convert color space from LAB to BGR color space
# Replace blended "background" white pixels of scr2 with original pixel values from img:
mask = np.all(scr2 == 255, 2).astype(np.uint8) # Mask value is 1 where 3 color channels are 255
cv2.copyTo(img, mask, blend) # Copy pixels from img to blend where mask != 0.
crop = blend[60:100, 460:530]
cv2.imwrite("crop2.png", crop)
cv2.imwrite("line2.png", blend)
# Show the results
cv2.imshow('mask', mask*255)
cv2.imshow('img', img)
cv2.imshow('blend', blend)
cv2.imshow('crop', crop)
cv2.waitKey()
cv2.destroyAllWindows()
结果:
左:crop 混合在 LAB 空间中。
右:crop 混合在 BGR 空间中。
注意:
将亮度从src2复制到blend:
根据您的评论,您似乎希望保持src2 的彩色线条的亮度,而不是将亮度与背景混合。
在 LAB 颜色空间中,L 颜色通道是亮度。
您可以将亮度从src2 复制到blend,其中src2 不是白色。
以下是代码的相关部分:
blend_lab = cv2.addWeighted(img_lab, 0.7, scr2_lab, 0.3, 0) # 在 LAB 颜色空间中混合图像
# Get the luminance channel (get NumPy slice)
scr2_luminance = scr2_lab[:, :, 0]
blend_luminance = blend_lab[:, :, 0]
blend_luminance[np.any(scr2 != 255, 2)] = scr2_luminance[np.any(scr2 != 255, 2)] # Copy the luminace from scr2_lab to blend_lab where scr2 is not white.
blend = cv2.cvtColor(blend_lab, cv2.COLOR_LAB2BGR) # Convert color space from LAB to BGR color space
结果:
crop:
blend:
注意:
我们可以在 HSV 颜色空间中将饱和度通道从 scr2 复制到 blend:
scr2_hsv = cv2.cvtColor(scr2, cv2.COLOR_BGR2HSV)
blend_hsv = cv2.cvtColor(blend, cv2.COLOR_BGR2HSV)
blend_hsv[:,:,1][np.any(scr2 != 255, 2)] = scr2_hsv[:,:,1][np.any(scr2 != 255, 2)] # Copy the saturation channel.
blend = cv2.cvtColor(blend_hsv, cv2.COLOR_HSV2BGR)
我不确定这是否有意义......