大家好~ 今天给大家分享两个超实用的OpenCV颜色识别小项目,全程用Python编写,代码直接复制就能跑通,不管你是刚接触计算机视觉的新手,还是想快速实现简单颜色检测需求的开发者,这篇博客都能帮到你!

一、实战一:实时中心区域颜色识别

先给大家看一下这个功能的效果:打开摄像头后,画面中心会出现一个绿色的矩形框,把红、黄、绿、蓝四种颜色的物体放到这个框里,程序会自动识别出物体的颜色,并且在控制台打印出来,关闭摄像头只需要按一下ESC键就可以。

这个功能非常适合新手入门,代码逻辑简单,没有复杂的算法,主要是让大家熟悉OpenCV的图像读取、颜色空间转换、像素遍历等基础操作,下面我们一步步拆解代码,每一行都讲清楚,保证大家能看懂。

1.1 完整代码(直接复制就能跑)

import cv2


def get_color(img):
    H = []
    color_name = None
    img = cv2.resize(img, (640, 480))
    HSV = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    cv2.rectangle(img, (280, 180), (360, 260), (0, 255, 0), 2)
    for i in range(280, 360):
        for j in range(180, 260):
            H.append(HSV[j, i][0])

    H_min = min(H)
    H_max = max(H)

    if H_min >= 0 and H_max <= 10 or H_min >= 156 and H_max <= 180: color_name = 'red'
    elif H_min >= 26 and H_max <= 34:
        color_name = 'yellow'
    elif H_min >= 35 and H_max <= 77:
        color_name = 'green'
    elif H_min >= 100 and H_max <= 124:
        color_name = 'blue'
    print(color_name)
    return img, color_name


cap = cv2.VideoCapture(0)
while 1:
    _, frame = cap.read()
    img, cal = get_color(frame)
    cv2.imshow('', img)
    if cv2.waitKey(1) == 27:
        break

1.2 代码逐行拆解

很多新手看代码的时候,容易被一堆函数吓到,其实只要把每个函数、每一行代码的作用搞清楚,就会发现非常简单,我们从开头一步步往下讲:

1. 导入OpenCV库:import cv2,这一行是所有OpenCV项目的基础,就相当于我们打开了一个图像处理的工具箱,后面所有的操作都要靠这个库来实现。

2. 定义颜色识别函数:def get_color(img):,这个函数是整个功能的核心,作用是接收摄像头读取的图像,然后识别出图像中心区域的颜色,最后返回处理后的图像和识别出的颜色名称。

3. 初始化变量:H = [] 用来存储中心区域所有像素的“色相值”(后面会讲),color_name = None 用来存储识别出的颜色名称,初始值为None,也就是还没识别出颜色。

4. 统一图像尺寸:img = cv2.resize(img, (640, 480)),这一步非常重要!不同摄像头的分辨率不一样,读取的图像尺寸也会不同,统一调整为640×480,能避免后续识别区域偏移,保证代码在不同设备上都能正常运行。

5. 颜色空间转换:HSV = cv2.cvtColor(img, cv2.COLOR_BGR2HSV),这是颜色识别的关键一步,也是新手最容易踩坑的地方!

这里跟大家简单科普一下:OpenCV读取图像时,默认是BGR颜色空间(蓝、绿、红),而我们人眼看到的是RGB颜色空间(红、绿、蓝),更重要的是,RGB颜色空间对光照非常敏感——比如同样一个红色物体,在强光下和弱光下,RGB值会相差很大,识别准确率会大幅下降。

而HSV颜色空间就完美解决了这个问题,它把颜色拆分成三个独立的部分:H(色相,决定颜色本身,比如红、黄、蓝)、S(饱和度,决定颜色的鲜艳程度)、V(明度,决定颜色的明暗程度)。我们只需要关注H值,就能精准判断颜色,不受光照影响,这也是为什么我们要把BGR转换成HSV的原因。

6. 绘制中心识别框:cv2.rectangle(img, (280, 180), (360, 260), (0, 255, 0), 2),这一行代码的作用是在图像上画一个绿色的矩形框,作为颜色识别的区域。

给大家解释一下参数:(img)是要绘制的图像,(280, 180)是矩形框的左上角坐标,(360, 260)是右下角坐标,(0, 255, 0)是矩形框的颜色(绿色,BGR格式),2是矩形框的线条宽度。这个矩形框的大小是80×80像素,刚好在画面中心,既能避免背景干扰,又能准确捕捉目标物体。

7. 遍历中心区域像素,提取H值:

for i in range(280, 360):
    for j in range(180, 260):
        H.append(HSV[j, i][0])

这是一个双重循环,作用是遍历我们刚才画的矩形框内的所有像素,然后把每个像素的H值(色相值)添加到H列表中。这里要注意一个小细节:OpenCV的坐标原点在左上角,x轴向右,y轴向下,所以HSV[j, i][0]才是正确的像素取值方式,新手很容易写成HSV[i, j][0],导致提取的H值错误,识别失败。

8. 计算H值的最大和最小值:H_min = min(H)H_max = max(H),因为矩形框内的像素可能有轻微的颜色差异,计算最大和最小值,能更精准地判断整个区域的颜色。

9. 根据H值判断颜色:这是核心判断逻辑,我们根据HSV颜色空间中不同颜色的H值范围,来判断中心区域的颜色。

这里给大家整理了代码中用到的颜色阈值(OpenCV中H值的取值范围是0~180),大家可以直接套用:

  • 红色:H值在0~10 或 156~180(红色比较特殊,在HSV空间中分为两段,这也是新手容易忽略的点,少写一段就会导致红色识别失败);

  • 黄色:H值在26~34;

  • 绿色:H值在35~77;

  • 蓝色:H值在100~124。

这里有个小技巧:如果大家发现识别不准确,可以稍微调整这些阈值范围,比如红色的阈值可以改成0~15 或 150~180,根据自己的光照环境微调即可。

10. 打印识别结果:print(color_name),把识别出的颜色名称打印到控制台,方便我们查看识别效果。

11. 返回结果:return img, color_name,把处理后的图像(带有绿色识别框)和识别出的颜色名称返回,供后续显示使用。

12. 初始化摄像头:cap = cv2.VideoCapture(0),0表示电脑的默认摄像头,如果你的电脑有多个摄像头,可以改成1、2等,具体可以自己测试。

13. 循环读取摄像头画面:

while 1:
    _, frame = cap.read()
    img, cal = get_color(frame)
    cv2.imshow('', img)
    if cv2.waitKey(1) == 27:
        break

这是一个无限循环,作用是实时读取摄像头的画面:_, frame = cap.read() 读取每一帧画面,img, cal = get_color(frame) 调用我们刚才定义的颜色识别函数,处理画面并获取识别结果,cv2.imshow('', img) 显示处理后的画面(带有绿色识别框)。

最后一行 if cv2.waitKey(1) == 27: break 是退出条件,27是ESC键的ASCII码,按下ESC键,就会退出循环,关闭摄像头。

1.3 实操效果与常见问题解决

运行代码后,会自动打开摄像头,画面中心出现绿色矩形框,把红色物体(比如苹果)放到框里,控制台会打印“red”;把黄色物体(比如柠檬)放进去,打印“yellow”,以此类推,识别准确率还是很高的。

二、实战二:指定颜色过滤与掩码提取(进阶实用功能)

学会了基础的颜色识别,我们再来升级一个实用功能——指定颜色过滤。这个功能的效果是:打开摄像头后,只保留画面中你指定的颜色(比如绿色),其他颜色都会变成黑色,同时还会显示一个黑白掩码(白色是目标颜色,黑色是背景),非常适合后续的目标追踪、颜色分割等场景,比如工业分拣、智能小车循迹等都能用到这个功能。

这个功能比第一个稍微复杂一点,但核心还是HSV颜色空间和阈值判断,下面我们同样拆解代码,新手也能轻松看懂。

2.1 完整代码(直接复制就能跑)

import cv2
import numpy as np

cap = cv2.VideoCapture(0)

while True:
    try:
        ret, frame3 = cap.read()
        hsv_image = cv2.cvtColor(frame3, cv2.COLOR_BGR2HSV)
        lower_brown = np.array([35, 43, 46])
        upper_brown = np.array([77, 255, 255])

        mask = cv2.inRange(hsv_image, lower_brown, upper_brown)
        result = cv2.bitwise_and(frame3, frame3, mask=mask)
        cv2.imshow('mask', mask)
        cv2.imshow('Filtered Image1', frame3)
        cv2.imshow('result', result)

        if cv2.waitKey(1) == 27:
            break
    except:
        pass

cap.release()
cv2.destroyAllWindows()

2.2 代码逐行拆解(重点讲和第一个功能的区别)

这个代码和第一个功能有很多相似之处,我们重点讲不同的地方,相似的地方就不再重复,节省大家的时间:

1. 导入库:除了导入cv2,还导入了numpy库(import numpy as np),numpy是Python的数值计算库,主要用来创建颜色阈值的数组,因为OpenCV的颜色阈值需要用numpy数组来表示,这也是为什么我们安装环境时要安装numpy的原因。

2. 初始化摄像头:和第一个功能一样,cap = cv2.VideoCapture(0) 调用默认摄像头。

3. 循环读取画面(加了异常处理):

while True:
    try:
        ret, frame3 = cap.read()
        # 中间代码省略
    except:
        pass

这里加了try-except异常处理,作用是防止摄像头读取失败(比如突然断开摄像头)导致程序崩溃,即使出现异常,程序也能继续运行,比第一个功能更稳定,这个小技巧大家可以记下来,以后写OpenCV程序都能用到。

另外,ret, frame3 = cap.read() 中的ret是一个布尔值,表示是否成功读取到画面,如果ret为False,说明摄像头读取失败,会触发异常处理。

4. 颜色空间转换:hsv_image = cv2.cvtColor(frame3, cv2.COLOR_BGR2HSV),和第一个功能一样,把BGR转换成HSV,避免光照干扰。

5. 设置目标颜色的HSV阈值:

lower_brown = np.array([35, 43, 46])
upper_brown = np.array([77, 255, 255])

这是这个功能的核心!我们通过设置HSV的上下限阈值,来指定要过滤的颜色。这里要注意,HSV的三个分量分别是H、S、V,所以每个数组的三个数值,分别对应H的下限、S的下限、V的下限,以及H的上限、S的上限、V的上限。

大家可能会疑惑,代码里写的是lower_brown(棕色下限),但这个阈值其实是绿色的HSV阈值(H:35~77,S:43~255,V:46~255),应该是作者写代码时命名错误,大家不用在意,重点看阈值数值即可。

这里给大家整理了几种常见颜色的HSV阈值,大家可以直接替换代码中的阈值,实现不同颜色的过滤:

  • 红色:lower_red = np.array([0, 43, 46]),upper_red = np.array([10, 255, 255]);还有一段是lower_red2 = np.array([156, 43, 46]),upper_red2 = np.array([180, 255, 255]),如果要过滤红色,需要把两个阈值的掩码合并;

  • 黄色:lower_yellow = np.array([26, 43, 46]),upper_yellow = np.array([34, 255, 255]);

  • 蓝色:lower_blue = np.array([100, 43, 46]),upper_blue = np.array([124, 255, 255]);

  • 绿色:lower_green = np.array([35, 43, 46]),upper_green = np.array([77, 255, 255])(代码中用的就是这个阈值)。

这里有个小技巧:如果不知道某个颜色的HSV阈值,可以用OpenCV自带的阈值调试工具,后面我会给大家分享,轻松获取任意颜色的阈值。

6. 生成颜色掩码:mask = cv2.inRange(hsv_image, lower_brown, upper_brown),这是颜色过滤的核心函数,作用是根据我们设置的HSV阈值,生成一个二值化的掩码图像。

简单来说,掩码图像只有黑白两种颜色:画面中符合HSV阈值的像素(目标颜色)会变成白色(像素值255),不符合阈值的像素(背景)会变成黑色(像素值0)。这个掩码就相当于一个“过滤器”,只允许目标颜色通过,后面我们会用这个掩码来提取目标颜色区域。

这里给新手提个醒:如果生成的掩码全黑或全白,说明阈值设置有问题,要么是阈值范围超出了HSV的有效区间(H:0~179,S/V:0~255),要么是颜色空间没转换(还是BGR格式),可以检查一下这两个地方,这也是新手最容易踩的坑之一。

7. 提取目标颜色区域:result = cv2.bitwise_and(frame3, frame3, mask=mask),这行代码的作用是,将原图像和掩码进行按位与操作,只保留掩码中白色区域对应的原图像像素,也就是只保留目标颜色,其他区域都变成黑色。

举个例子:如果我们设置的是绿色阈值,那么result图像中,只有绿色的物体是清晰可见的,其他颜色的物体和背景都会变成黑色,这样就能精准提取出我们想要的颜色区域。

8. 显示三个窗口:

cv2.imshow('mask', mask)  # 显示掩码图像(黑白)
cv2.imshow('Filtered Image1', frame3)  # 显示原图像
cv2.imshow('result', result)  # 显示过滤后的图像(只保留目标颜色)

运行代码后,会弹出三个窗口,分别显示原图像、掩码图像和过滤后的图像,大家可以直观地看到颜色过滤的效果,非常清晰。

9. 退出条件和资源释放:和第一个功能类似,按下ESC键退出循环,最后用cap.release() 释放摄像头资源,cv2.destroyAllWindows() 关闭所有OpenCV窗口,避免程序卡死,这也是第二个功能比第一个功能更完善的地方。

2.3 实操效果与常见问题解决

运行代码后,弹出三个窗口:原图像窗口显示摄像头实时画面,掩码窗口显示黑白图像(白色是绿色区域),过滤结果窗口只显示绿色物体,其他区域都是黑色,效果非常明显。如果想过滤其他颜色,只需要替换代码中的HSV阈值即可。

四、总结与拓展:这两段代码能用到哪些地方?

今天给大家分享的两段代码,虽然简单,但实用性非常强,不管是新手练手,还是实际项目应用,都能用到,下面给大家拓展一下它们的应用场景,让大家知道学完这些能做什么。

1. 新手练手:这两段代码涵盖了OpenCV的核心基础操作(图像读取、颜色空间转换、像素遍历、掩码生成、窗口显示),是新手入门OpenCV的绝佳案例,看懂、跑通这两段代码,就能掌握OpenCV图像处理的基础技能,为后续学习更复杂的项目(比如人脸识别、目标追踪)打下基础。

2. 趣味小项目:可以基于这两段代码,开发一些趣味小项目,比如颜色识别小游戏(让用户猜颜色,程序判断对错)、智能调色板(提取画面中的颜色,生成对应的RGB值)、简易颜色分拣模拟器等,既能巩固知识,又能增加学习的乐趣。

3. 实际应用场景:

  • 工业分拣:在流水线上安装摄像头,通过颜色识别,自动分拣不同颜色的产品(比如分拣红色和蓝色的零件);

  • 智能小车循迹:在小车上安装摄像头,通过颜色过滤,识别路面上的颜色轨迹(比如黑色轨迹),实现自动循迹;

  • 垃圾分类:结合颜色识别和形状识别,自动区分不同颜色的垃圾(比如红色的塑料瓶、绿色的易拉罐);

  • 目标追踪:通过颜色过滤提取目标物体,然后结合跟踪算法,实现对目标物体的实时追踪(比如追踪红色的小球)。

最后,给大家说一句心里话:学习OpenCV不用一开始就追求复杂的算法,先从简单的小项目入手,把基础操作练熟,遇到问题多调试、多查资料,慢慢就能掌握技巧。今天分享的两段代码,大家一定要亲自跑一遍,修改一下参数、替换一下阈值,感受一下OpenCV的魅力,相信大家都能学会。

如果大家在运行代码的过程中遇到问题,或者有其他的需求(比如想优化代码、拓展功能),可以在评论区留言,我会一一回复大家,帮助大家解决问题。

另外,大家可以收藏这篇博客,以后需要用到颜色识别功能的时候,直接复制代码,稍微修改一下就能用,非常方便。后续我还会分享更多OpenCV实战项目,关注我,一起学习、一起进步!

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐