使用Python实现图像颜色区间转换:将红色转为绿色并保留细节
红色系颜色转换(保留细节)实现方案
原有代码问题
- 红色HSV阈值设置过窄,仅覆盖H值0~1的极窄区间,无法识别全部红色系区域
- 直接对目标区域赋值固定RGB值,丢弃了原有像素的饱和度、明度信息,导致转换后丢失所有明暗和细节
核心优化思路
- 完整覆盖HSV空间中红色的两个区间(010、170180),准确识别所有红色系内容
- 仅修改红色区域的色相(H)数值,保留原有的饱和度(S)和明度(V),自然保留图像细节和明暗层次
- 掩膜增加羽化处理,避免颜色替换后出现生硬边缘
完整实现代码
import cv2 import numpy as np import skimage.exposure # 加载图像 img = cv2.imread("test5.jpg") hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 拆分HSV三个通道单独处理 h, s, v = cv2.split(hsv) # 定义红色在OpenCV HSV空间的两个阈值区间 lower_red1 = np.array([0, 50, 50]) upper_red1 = np.array([10, 255, 255]) lower_red2 = np.array([170, 50, 50]) upper_red2 = np.array([180, 255, 255]) # 生成完整的红色区域掩膜 mask1 = cv2.inRange(hsv, lower_red1, upper_red1) mask2 = cv2.inRange(hsv, lower_red2, upper_red2) mask = mask1 + mask2 # 掩膜优化:去除噪点+边缘羽化 kernel = np.ones((3,3), np.uint8) mask = cv2.morphologyEx(mask, cv2.MORPH_ERODE, kernel) mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel) mask = cv2.GaussianBlur(mask, (0,0), sigmaX=3, sigmaY=3, borderType = cv2.BORDER_DEFAULT) mask = skimage.exposure.rescale_intensity(mask, in_range=(127.5,255), out_range=(0,255)).astype(np.uint8) # 目标色相设置,可按需修改:绿色=60、蓝色=120、黄色=30、紫色=150 target_hue = 60 # 仅替换红色区域的色相,保留原饱和度和明度 h[mask > 0] = target_hue # 合并通道并转回BGR色彩空间 new_hsv = cv2.merge([h, s, v]) result = cv2.cvtColor(new_hsv, cv2.COLOR_HSV2BGR) # 保存输出结果 cv2.imwrite("test6.jpg", result)
参数调整说明
- 红色识别范围调整:如果存在漏识别的红色区域,可适当放宽H值阈值,比如将第一个区间上限调至15,第二个区间下限调至165;如果误识别了过多非红色区域,可提高S/V的下限(把阈值中的50调整为60~70)
- 目标颜色调整:修改
target_hue的取值即可切换转换后的色系,OpenCV HSV色相取值对应关系:- 黄色:30
- 绿色:60
- 青色:90
- 蓝色:120
- 紫色:150
内容的提问来源于stack exchange,提问作者Matthew Kirkland
相关产品推荐
相关产品推荐

