You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在OpenCV中保留原颜色亮度的同时替换指定区域颜色

如何精准替换掩码区域为指定颜色并保留原亮度(OpenCV实现)

问题背景

需要将图像中推土机的黄色区域替换为指定十六进制颜色(本次为红色),同时保留该区域的光影亮度,避免颜色单一。目前已通过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)

解决方案

核心思路是保留原区域的V(亮度)通道,替换为目标颜色的H(色调)和S(饱和度)通道,既能精准匹配目标颜色,又能完整保留原有的光影层次。具体实现步骤如下:

关键修改点

  1. 精准转换目标颜色:将十六进制颜色转为OpenCV兼容的BGR格式,再转为HSV提取目标H、S值,避免手动调参的误差。
  2. 保留亮度通道:仅在掩码区域替换H和S值,完全保留原图像的V通道,确保光影效果不变。
  3. 修复路径问题:统一图像读取路径,添加输出目录自动创建逻辑,避免运行报错。

修改后的完整代码

import cv2
import numpy as np
import os

# 目标十六进制颜色转BGR(OpenCV默认使用BGR格式)
hex_color = "#FF0000"  # 本次目标为红色
# 十六进制转RGB后转为BGR顺序
rgb = tuple(int(hex_color.lstrip('#')[i:i+2], 16) for i in (0, 2, 4))
target_bgr = np.array([rgb[2], rgb[1], rgb[0]], dtype=np.uint8)
# 将目标BGR颜色转为HSV,提取目标色调(H)和饱和度(S)
target_hsv = cv2.cvtColor(np.uint8([[target_bgr]]), cv2.COLOR_BGR2HSV)[0][0]
target_h, target_s = target_hsv[0], target_hsv[1]

# 黄色区域的HSV阈值(可根据实际图像微调)
lower_yellow = np.array([20, 100, 100])
upper_yellow = np.array([30, 255, 255])  

# 获取图像列表(确保路径与读取路径一致)
all_images = sorted(os.listdir('data/audi_a6'))
# 确保输出目录存在
os.makedirs('output_change_color/lego', exist_ok=True)

for i, image in enumerate(all_images):
    print(image, end='\r')
    # 读取原图像
    img = cv2.imread(f'data/audi_a6/{image}')
    # 转为HSV颜色空间
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

    # 创建黄色区域掩码
    yellow_mask = cv2.inRange(hsv, lower_yellow, upper_yellow)
    inv_mask = cv2.bitwise_not(yellow_mask)

    # 拆分HSV通道
    h, s, v = cv2.split(hsv)
    # 仅在黄色掩码区域替换H和S为目标值,保留原亮度V
    h[yellow_mask > 0] = target_h
    s[yellow_mask > 0] = target_s
    # 合并修改后的HSV通道
    modified_hsv = cv2.merge([h, s, v])

    # 转回BGR格式
    modified_bgr = cv2.cvtColor(modified_hsv, cv2.COLOR_HSV2BGR)

    # 合并原图非掩码区域和修改后的掩码区域
    result = cv2.bitwise_or(
        cv2.bitwise_and(img, img, mask=inv_mask),
        cv2.bitwise_and(modified_bgr, modified_bgr, mask=yellow_mask)
    )

    # 保存结果
    cv2.imwrite(f'output_change_color/lego/frame_{i:03}.jpg', result)

说明

  • 若需要替换为其他颜色,仅需修改hex_color变量的十六进制值即可,无需调整HSV阈值(除非目标颜色的掩码需要重新设定)。
  • 黄色区域的HSV阈值可根据实际图像的黄色深浅微调,确保掩码精准覆盖目标区域。

内容的提问来源于stack exchange,提问作者diegobc11

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 01:10:22