如何优化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
相关产品推荐
相关产品推荐

