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

如何优化OpenCV中HSV不连续红色范围检测的冗余代码?

问题描述

我使用Python基于HSV色彩空间检测图像中的不同颜色,红色的HSV范围是不连续的:

lower_red = np.array([0,100,100])
upper_red = np.array([10, 255, 255])
lower_red2 = np.array([161,100,100])
upper_red2 = np.array([179, 255, 255])

因此必须通过mask = cv2.bitwise_or(mask_1, mask_2)合并两个范围的掩码。

目前我用for循环遍历颜色列表,红色是唯一的例外,只能通过硬编码索引处理,代码不够优雅,希望找到更优的实现方式。

原相关代码片段:

if i != 3 and i != 4:
    mask = cv2.inRange (img_hsv, colours[i][0], colours[i][1])
elif i == 3: # Red color 
    mask_1 = cv2.inRange (img_hsv, colours[3][0], colours[3][1])
    mask_2 = cv2.inRange (img_hsv, colours[4][0], colours[4][1])
    mask = cv2.bitwise_or(mask_1, mask_2)
else: 
    continue   
解决方案:重构颜色配置与统一逻辑

最直观且易扩展的方式是重构颜色数据结构,让每个颜色可以对应多个HSV范围,然后统一处理所有颜色的掩码生成逻辑,彻底去掉硬编码的索引判断。

步骤1:重构颜色配置

将原来的colours数组改为嵌套列表,每个元素对应一个颜色的HSV范围列表(单范围颜色就放一个元素,多范围颜色放多个元素):

colours = [
    # 蓝色:单个HSV范围
    [(lower_blue, upper_blue)],
    # 绿色:单个HSV范围
    [(lower_green, upper_green)],
    # 黄色:单个HSV范围
    [(lower_yellow, upper_yellow)],
    # 红色:两个HSV范围
    [(lower_red, upper_red), (lower_red2, upper_red2)],
    # 黑色:单个HSV范围
    [(lower_black, upper_black)]
]

步骤2:统一掩码生成逻辑

遍历重构后的颜色列表,对每个颜色的所有HSV范围生成掩码并按位或合并,无需再区分特殊颜色:

for color_ranges in colours:
    # 初始化全0掩码
    mask = np.zeros(img_hsv.shape[:2], dtype=np.uint8)
    # 遍历当前颜色的所有HSV范围,合并掩码
    for lower, upper in color_ranges:
        current_mask = cv2.inRange(img_hsv, lower, upper)
        mask = cv2.bitwise_or(mask, current_mask)
    
    # 后续轮廓检测与绘制逻辑保持不变
    colourcnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2] 
    if len(colourcnts) > 0:
        coloured_cnt = max(colourcnts, key=cv2.contourArea)
        cntArea = cv2.contourArea(coloured_cnt)
        if cntArea > 400: 
            x, y, w, h = cv2.boundingRect(coloured_cnt)
            cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2)
优化后的完整代码
import cv2
import numpy as np

# 假设ori_img是已加载的原始图像
img = ori_img.copy()
img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 转换为HSV色彩空间

# 定义各颜色的HSV范围
lower_blue = np.array([120, 50, 20])
upper_blue = np.array([158, 255, 255])
lower_green = np.array([25,52,70])
upper_green = np.array([102,255,255])
lower_yellow = np.array([20,100,100])
upper_yellow = np.array([30,255,255])

lower_red = np.array([0,100,100])
upper_red = np.array([10, 255, 255])
lower_red2 = np.array([161,100,100])
upper_red2 = np.array([179, 255, 255])

lower_black = np.array([0, 0, 0])
upper_black = np.array([179, 255, 72])

# 重构颜色配置:每个颜色对应一个HSV范围列表
colours = [
    [(lower_blue, upper_blue)],
    [(lower_green, upper_green)],
    [(lower_yellow, upper_yellow)],
    [(lower_red, upper_red), (lower_red2, upper_red2)],
    [(lower_black, upper_black)]
]

for color_ranges in colours:
    # 生成当前颜色的掩码(支持多范围合并)
    mask = np.zeros(img_hsv.shape[:2], dtype=np.uint8)
    for lower, upper in color_ranges:
        current_mask = cv2.inRange(img_hsv, lower, upper)
        mask = cv2.bitwise_or(mask, current_mask)
    
    # 寻找轮廓并过滤面积过小的区域
    colourcnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2] 
    if len(colourcnts) > 0:
        coloured_cnt = max(colourcnts, key=cv2.contourArea)
        cntArea = cv2.contourArea(coloured_cnt)
        if cntArea > 400: 
            x, y, w, h = cv2.boundingRect(coloured_cnt)
            cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2)

# 显示结果
cv2.imshow("Color Detection Result", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

优化优势

  • 代码更简洁易读,去掉了冗余的条件判断
  • 扩展性极强:后续新增需要多范围的颜色时,只需在colours中添加对应的范围列表即可
  • 逻辑统一,降低维护成本

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 05:42:06