提问人:diegobc11 提问时间:11/16/2023 最后编辑:diegobc11 更新时间:11/18/2023 访问量:75
在 Opencv 中保持原始颜色强度的同时更改颜色
Change colors while maintining intensity of the original color in Opencv
问:
我想将推土机的颜色更改为特定的十六进制颜色(在本例中为红色),同时保留强度(光线对推土机的影响)。
我只想改变它的黄色部分,到目前为止,我已经创建了一个具有浅黄色和深黄色调下限和上限的蒙版,并提取了该蒙版,但是我不知道如何将红色应用于蒙版并保持颜色的相对强度,而不仅仅是所有相同的红色色调。
像下图这样的东西会很棒(如果可能的话,质量会更好,因为似乎有一些颜色设置不正确)
我已经看到了一些使用 HSV 的解决方法,但没有什么能真正完成这项工作。
到目前为止,我的代码涉及创建一个蒙版来提取我想要更改的颜色并将该蒙版转换为 HSV 颜色以保持颜色的强度,之后我尝试修改 HSV 以获得所需的颜色,但是它并不精确,没有确切的方法将 HSV 更改为我想要的十六进制或 rgb 颜色?
import cv2
import numpy as np
import os
import math
from numpy import inf
# set the bounds for the light and dark shade of color you want to mask
lower_yellow = np.array([20, 100, 100])
upper_yellow = np.array([30, 255, 255])
all_images = sorted(os.listdir('data/audi_a6'))
for i, image in enumerate(all_images):
print(image, end='\r')
img = cv2.imread(f'data/lego/{image}')
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
yellow_mask = cv2.inRange(hsv, lower_yellow, upper_yellow)
inv_mask = cv2.bitwise_not(yellow_mask)
h, s, v = cv2.split(hsv)
h = np.mod(h - h + 182, 180)
s = np.clip(s + 120, 0, 255)
v = np.clip(v, 0, 255)
hsv = cv2.merge([h, s, v])
bgr = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
result = cv2.bitwise_or(cv2.bitwise_and(img, img, mask=inv_mask), cv2.bitwise_and(bgr, bgr, mask=yellow_mask))
# Save the result
cv2.imwrite(f'output_change_color/lego/frame_{i:03}.jpg', result)
答:
你似乎很难区分黄色的机器和它下面的“泥泞的轨道”。解决这些问题的一种方法是查看不同的颜色空间,看看哪一个是很好的鉴别器。因此,我将您的图像转换为许多不同的色彩空间,并为您并排拆分各个通道:
因此,您可以查看每个色彩空间的每个通道,看看哪一个最适合您。例如,的第三个通道,或 的第二个通道 ...CIELab
HCL
评论
uint8
float
我只需要做一件事就可以让你的代码产生预期的结果。黄色像素的 H 通道约为 25。我们希望它改为 0。所以我们需要减去 25: .H - H_yellow + H_red
但是由于是一个数组,减去 25 将导致一些像素环绕到 255,这不是 H 的有效值(OpenCV 将其定义为 8 位图像的 0-180 范围内)。因此,如果添加 0,我们添加 180,则操作可以执行正确的操作:h
uint8
np.mod()
h = np.mod(h + 180 - 25, 180)
这显然不是通用的。为了更通用地做到这一点,我们最好使用浮点运算进行算术运算,因为无需担心溢出或换行。这还有另一个优点:OpenCV 不会将 HSV 空间量化为整数值,从而可以进行更精确的重建。但请记住,H 现在在 0-360 范围内,S 和 V 在 0-1 范围内。
img = cv2.imread(image)
imgf = img.astype(np.float32) / 255
hsv = cv2.cvtColor(imgf, cv2.COLOR_BGR2HSV)
h, s, v = cv2.split(hsv)
h = np.mod(h + h_target - h_source, 360)
s = np.clip(s + s_taget - s_source, 0, 1)
hsv = cv2.merge([h, s, v])
imgf = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
bgr = (imgf * 255).astype(np.uint8)
[注意,我们不碰V。
评论
h_source = np.mean(h[yellow_mask])
h_source
s_source
评论