本文将介绍OpenCV对物体颜色识别并框选出来准确对颜色进行较大范围框选,统一使用绿色边界框显示。识别物体内部的颜色边缘轮廓,以白色为边缘,对物体的框选更加细致。并在窗口中的边框旁打印上颜色对应的英文字母的代码(本文以视频为例。如需摄像头实时识别可将程序中 cap = cv2.VideoCapture("111.mp4")改为 cap = cv2.VideoCapture("0"))。

 这是原视频: 

这是经处理后的视频:

OpenCV对物体颜色识别

1.首先要对颜色范围做一些了解这是颜色识别的重中之重,下面是一些常用颜色:

   (1)红色(Red): 由于红色位于色相环的两端(0°和360°附近),所以有两个范围: 低值范围:H:0-10(对应0°-20°) 或者 高值范围:H:170-180(对应340°-360°)

   (2)绿色(Green): 绿色的色相大约在120°(普通HSV),对应OpenCV的60,实际范围可能在36-70(即普通HSV的72°-140°)之间,但核心绿色在60左右。

   (3)蓝色(Blue): 蓝色的色相在240°(普通HSV),对应OpenCV的120,实际范围在100-130(普通HSV200°-260°)之间。

   (4)黄色(Yellow): 黄色的色相在60°(普通HSV),对应OpenCV的30,实际范围在26-35(普通HSV52°-70°)之间。

   (5)橙色(Orange,即橘黄色): 橙色的色相在30°(普通HSV)附近,对应OpenCV的15,实际范围在11-25(普通HSV22°-50°)之间。

   (6)紫色(Purple): 紫色的色相大约在270°(普通HSV),对应OpenCV的135,实际范围在131-160(普通HSV262°-320°)之间,但注意不要与红色或蓝色重叠。

但是,由于实际应用中的光照和物体差异,这些范围可能需要调整。因此,根据搜索结果的描述,结合OpenCV的实际情况,可以给出如下范围:

注意:下面给出的范围是OpenCV中的数值(H:0-180, S:0-255, V:0-255),并且是每个颜色的大致范围。

通常,饱和度(S)和明度(V)的下限可以设为50-100以上以避免太暗或太灰的区域,上限为255。但是具体的上下限可以根据实际图像调整。

以下是一个表格总结:

颜色 H(色相) 范围 S(饱和度) 范围 V(明度) 范围 应用说明
红色 [0, 10]
[170, 180]
100-255 50-255 需检测两个区间(色环两端)
蓝色 [100, 130] 100-255 50-255 稳定区域
绿色 [35, 80] 80-255 40-255 较宽范围(包含浅绿到深绿)
黄色 [20, 35] 100-255 120-255 明度要求较高
橘黄色 [5, 20] 150-255 100-255 高饱和度区域
紫色 [125, 160] 100-255 50-200 避免亮度过高(可能偏粉)

 接下来进入主题:

(1)载入opencv,载入库,对识别物体颜色进行范围定义。(注:红色有两个范围: 低值范围:H:0-10(对应0°-20°) 或者 高值范围:H:170-180(对应340°-360°)),并对识别时框选颜色英文字母进行设置。

import cv2
import numpy as np    #载入opencv载入库

# 颜色范围定义 (HSV格式)
color_ranges = {
    'red': ([0, 120, 70], [10, 255, 255]),
    'red2': ([170, 120, 70], [180, 255, 255]),  # 红色在HSV中有两部分
    'green': ([40, 40, 40], [80, 255, 255]),
    'blue': ([90, 50, 50], [130, 255, 255]),
    'yellow': ([20, 100, 100], [40, 255, 255]),
    'orange': ([10, 100, 100], [20, 255, 255]),
    'purple': ([130, 40, 40], [170, 255, 255])
}

# 颜色对应的字母和显示颜色
color_info = {
    'red': ('R', (0, 0, 255)),
    'green': ('G', (0, 255, 0)),
    'blue': ('B', (255, 0, 0)),
    'yellow': ('Y', (0, 255, 255)),
    'orange': ('O', (0, 165, 255)),
    'purple': ('P', (128, 0, 128))}

 (2)将图像从BGR色彩空间转换到HSV色彩空间。

  • frame`: 输入的图像(OpenCV默认以BGR格式读取)。
  • `cv2.cvtColor()`: OpenCV的色彩空间转换函数。
  • `cv2.COLOR_BGR2HSV`: 转换标志,指定从BGR到HSV的转换。
def detect_colors(frame):
    # 转换为HSV颜色空间
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

 (3)对每种颜色进行处理:

        创建掩膜将颜色范围的下限值转换为OpenCV可识别的无符号8位整数数组  Python列表 → OpenCV兼容数组

        去除噪声将二值化掩膜(mask)进行形态学开运算处理,作用是去除噪声斑点+平滑物体边界,让颜色检测结果更准确。

 # 对每种颜色进行处理
    for color_name, (lower, upper) in color_ranges.items():
        # 创建颜色掩膜
        lower = np.array(lower, dtype=np.uint8)  #将颜色范围的下限值转换为OpenCV
可识别的无符号8位整数数组  Python列表 → OpenCV兼容数组
        
        upper = np.array(upper, dtype=np.uint8)
        mask = cv2.inRange(hsv, lower, upper)
        
        # 如果处理红色,需要合并两个红色范围
        if color_name == 'red':
            lower2 = np.array(color_ranges['red2'][0], dtype=np.uint8)
            upper2 = np.array(color_ranges['red2'][1], dtype=np.uint8)
            mask2 = cv2.inRange(hsv, lower2, upper2)
            mask = cv2.bitwise_or(mask, mask2)
            color_name = 'red'  # 统一使用red作为键
# 形态学操作去除噪声
        kernel = np.ones((5, 5), np.uint8)
#二值化掩膜(mask)进行形态学开运算处理,作用是去除噪声斑点+平滑物体边界,让颜色检测结果更准确。
        mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
        mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)

 (4)创建查找轮廓并对边界框进行设置:

# 查找轮廓
        contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        
        # 为每个轮廓绘制边界框和边缘
        for cnt in contours:
            # 忽略小面积区域
            if cv2.contourArea(cnt) < 500:
                continue
                
            # 获取大致边界框 (绿色)
            x, y, w, h = cv2.boundingRect(cnt)
            cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)
            
            # 获取更精确的边缘 (白色)
            epsilon = 0.02 * cv2.arcLength(cnt, True)
            approx = cv2.approxPolyDP(cnt, epsilon, True)
            cv2.drawContours(frame, [approx], -1, (255, 255, 255), 1)
            
            # 显示颜色字母 (使用原始颜色名称,不包括red2)
            if color_name in color_info:
                letter, text_color = color_info[color_name]
                cv2.putText(frame, letter, (x, y-10), 
                           cv2.FONT_HERSHEY_SIMPLEX, 0.9, text_color, 2)
    
    return frame

 (5)读取视频文件对之前设置进行绘制并展示出来:

      本文以视频为例。如需摄像头实时识别可将程序中 cap = cv2.VideoCapture("111.mp4")改为 cap = cv2.VideoCapture("0")

# 主程序
def main():
    # 可以选择摄像头或视频文件
    cap = cv2.VideoCapture("111.mp4")  # 0表示默认摄像头,视频:支持常见格式如 .mp4, .avi,需确保路径正确且文件存在。
    
    while True:
        ret, frame = cap.read()
        if not ret:
            break
            
        # 检测并绘制颜色
        result = detect_colors(frame)
        
        # 显示结果
        cv2.imshow('Color Detection', result)
        
        # 按q退出
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
            
    cap.release()
    cv2.destroyAllWindows()

if __name__ == '__main__':
    main()

  本文用的是vscode配置python开发环境编写opencv。通过将视频转换为 HSV、定义红色蓝黄橘黄紫色的范围、查找轮廓,框选显现颜色首写字母并展示出来,这种方法对于计算机视觉中的颜色识别任务非常强大。

这是完整代码:

import cv2
import numpy as np

# 颜色范围定义 (HSV格式)
color_ranges = {
    'red': ([0, 120, 70], [10, 255, 255]),
    'red2': ([170, 120, 70], [180, 255, 255]),  # 红色在HSV中有两部分
    'green': ([40, 40, 40], [80, 255, 255]),
    'blue': ([90, 50, 50], [130, 255, 255]),
    'yellow': ([20, 100, 100], [40, 255, 255]),
    'orange': ([10, 100, 100], [20, 255, 255]),
    'purple': ([130, 40, 40], [170, 255, 255])
}

# 颜色对应的字母和显示颜色
color_info = {
    'red': ('R', (0, 0, 255)),
    'green': ('G', (0, 255, 0)),
    'blue': ('B', (255, 0, 0)),
    'yellow': ('Y', (0, 255, 255)),
    'orange': ('O', (0, 165, 255)),
    'purple': ('P', (128, 0, 128))
}

def detect_colors(frame):
    # 转换为HSV颜色空间
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    
    # 对每种颜色进行处理
    for color_name, (lower, upper) in color_ranges.items():
        # 创建颜色掩膜
        lower = np.array(lower, dtype=np.uint8)  #将颜色范围的下限值转换为
        #OpenCV可识别的无符号8位整数数组  Python列表 → OpenCV兼容数组
        
        upper = np.array(upper, dtype=np.uint8)
        mask = cv2.inRange(hsv, lower, upper)
        
        # 如果处理红色,需要合并两个红色范围
        if color_name == 'red':
            lower2 = np.array(color_ranges['red2'][0], dtype=np.uint8)
            upper2 = np.array(color_ranges['red2'][1], dtype=np.uint8)
            mask2 = cv2.inRange(hsv, lower2, upper2)
            mask = cv2.bitwise_or(mask, mask2)
            color_name = 'red'  # 统一使用red作为键
        
        # 形态学操作去除噪声
        kernel = np.ones((5, 5), np.uint8)
        #二值化掩膜(mask)进行形态学开运算处理,
        # 作用是去除噪声斑点+平滑物体边界,让颜色检测结果更准确。
        mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
        mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
        
        # 查找轮廓
        contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        
        # 为每个轮廓绘制边界框和边缘
        for cnt in contours:
            # 忽略小面积区域
            if cv2.contourArea(cnt) < 500:
                continue
                
            # 获取大致边界框 (绿色)
            x, y, w, h = cv2.boundingRect(cnt)
            cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)
            
            # 获取更精确的边缘 (白色)
            epsilon = 0.02 * cv2.arcLength(cnt, True)
            approx = cv2.approxPolyDP(cnt, epsilon, True)
            cv2.drawContours(frame, [approx], -1, (255, 255, 255), 1)
            
            # 显示颜色字母 (使用原始颜色名称,不包括red2)
            if color_name in color_info:
                letter, text_color = color_info[color_name]
                cv2.putText(frame, letter, (x, y-10), 
                           cv2.FONT_HERSHEY_SIMPLEX, 0.9, text_color, 2)
    
    return frame

# 主程序
def main():
    # 可以选择摄像头或视频文件
    cap = cv2.VideoCapture("111.mp4")  # 0表示默认摄像头,视频:支持常见格式如 .mp4, .avi,需确保路径正确且文件存在。
    
    while True:
        ret, frame = cap.read()
        if not ret:
            break
            
        # 检测并绘制颜色
        result = detect_colors(frame)
        
        # 显示结果
        cv2.imshow('Color Detection', result)
        
        # 按q退出
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
            
    cap.release()
    cv2.destroyAllWindows()

if __name__ == '__main__':
    main()

 感谢阅读观看!!

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐