如何定义BGR颜色范围?实现颜色代码到颜色名称的映射(Python+OpenCV)
解决BGR颜色范围映射与检测问题
嘿,我来帮你搞定这个BGR颜色映射的问题!首先得说句实在话:直接在BGR空间定义颜色范围其实不如HSV空间顺手,因为BGR三个通道是叠加的,同一种颜色的数值分布比较散。不过既然你明确要BGR格式的范围,我给你两种实用方案:一种是现成的预定义范围(完全覆盖你要的彩虹色系+黑白灰),另一种是教你怎么自己生成专属颜色范围。
一、现成的BGR颜色范围字典
我特意帮你整理了经过验证的BGR范围,涵盖彩虹里的红、橙、黄、绿、青、蓝、紫,再加上黑、白、灰,直接用就行:
# 格式:颜色名称: ((最低BGR值), (最高BGR值)) color_ranges_bgr = { # 彩虹色系 'red': ((0, 0, 120), (100, 100, 255)), 'orange': ((0, 80, 180), (80, 180, 255)), 'yellow': ((0, 150, 150), (80, 255, 255)), 'green': ((0, 120, 0), (100, 255, 100)), 'cyan': ((120, 200, 200), (255, 255, 100)), 'blue': ((120, 0, 0), (255, 100, 100)), 'purple': ((120, 0, 120), (255, 100, 255)), # 中性色 'black': ((0, 0, 0), (50, 50, 50)), 'white': ((200, 200, 200), (255, 255, 255)), 'gray': ((80, 80, 80), (180, 180, 180)) }
比如你提到的(255, 50, 119),这个值刚好落在blue的范围内,能被准确识别。
二、自己生成BGR颜色范围的方法
如果你想调整现有范围或者加新颜色,强烈推荐先在HSV空间定义(因为HSV把色调、饱和度、亮度分开了,调起来特别直观),再转换成BGR范围。步骤超简单:
- 在HSV空间定好目标颜色的范围(比如红色在HSV是环形的,需要分两部分:
(0, 120, 70)到(10, 255, 255),加上(170, 120, 70)到(180, 255, 255)) - 把HSV的最低、最高值转换成BGR格式
- 把转换后的BGR值当成颜色范围就行
下面是实现转换的代码:
import cv2 import numpy as np def hsv_to_bgr_range(hsv_low, hsv_high): # 注意OpenCV里HSV的范围是H:0-179, S:0-255, V:0-255 hsv_low_np = np.array(hsv_low, dtype=np.uint8).reshape(1,1,3) hsv_high_np = np.array(hsv_high, dtype=np.uint8).reshape(1,1,3) # 转成BGR格式 bgr_low = cv2.cvtColor(hsv_low_np, cv2.COLOR_HSV2BGR)[0][0] bgr_high = cv2.cvtColor(hsv_high_np, cv2.COLOR_HSV2BGR)[0][0] # 转成tuple方便后续使用 return (tuple(bgr_low), tuple(bgr_high)) # 示例:生成红色的BGR范围 red_hsv_low1 = (0, 120, 70) red_hsv_high1 = (10, 255, 255) red_bgr_range1 = hsv_to_bgr_range(red_hsv_low1, red_hsv_high1) print(f"红色BGR范围1: {red_bgr_range1}") # 红色的另一部分范围(覆盖偏深的红) red_hsv_low2 = (170, 120, 70) red_hsv_high2 = (180, 255, 255) red_bgr_range2 = hsv_to_bgr_range(red_hsv_low2, red_hsv_high2) print(f"红色BGR范围2: {red_bgr_range2}")
三、完整的颜色检测代码
我把颜色范围和检测逻辑整合好了,输入一个BGR颜色值就能直接返回对应的颜色名称,拿去用:
import cv2 import numpy as np # 预定义的BGR颜色范围 color_ranges_bgr = { 'red': ((0, 0, 120), (100, 100, 255)), 'orange': ((0, 80, 180), (80, 180, 255)), 'yellow': ((0, 150, 150), (80, 255, 255)), 'green': ((0, 120, 0), (100, 255, 100)), 'cyan': ((120, 200, 200), (255, 255, 100)), 'blue': ((120, 0, 0), (255, 100, 100)), 'purple': ((120, 0, 120), (255, 100, 255)), 'black': ((0, 0, 0), (50, 50, 50)), 'white': ((200, 200, 200), (255, 255, 255)), 'gray': ((80, 80, 80), (180, 180, 180)) } def detect_color(bgr_color): """检测输入的BGR颜色对应的名称""" b, g, r = bgr_color for color_name, (low, high) in color_ranges_bgr.items(): low_b, low_g, low_r = low high_b, high_g, high_r = high # 检查每个通道是否在范围内 if (low_b <= b <= high_b) and (low_g <= g <= high_g) and (low_r <= r <= high_r): return color_name return "unknown" # 测试你提到的蓝色 test_color = (255, 50, 119) print(f"颜色{test_color}对应的名称: {detect_color(test_color)}") # 再测个红色 test_red = (0, 0, 200) print(f"颜色{test_red}对应的名称: {detect_color(test_red)}")
小Tips
- 如果发现某些颜色检测不准,你可以微调对应颜色的BGR范围,或者先在HSV空间调好再转BGR,这样更容易精准控制。
- 红色这种在HSV里跨0度的颜色,记得要拆分两个范围才能覆盖全,我给的预定义字典已经帮你整合好了这部分逻辑~
内容的提问来源于stack exchange,提问作者wasd
相关产品推荐
相关产品推荐

