计算机视觉——OpenCV Python基于颜色识别的目标检测

发布于:2024-04-17 ⋅ 阅读:(21) ⋅ 点赞:(0)

1. 计算机视觉中的颜色空间

颜色空间在计算机视觉领域的应用非常广泛,它们在图像和视频处理、物体检测等任务中扮演着重要角色。颜色空间的主要作用是将颜色以数值形式表示出来,这样计算机算法就能够对其进行处理和分析。不同的颜色空间有着不同的特点和适用场景,下面我们来快速了解一下几种最常用的颜色空间:

  1. RGB颜色空间:这是最常用的颜色空间之一,特别是在计算机显示和数字图像处理中。RGB代表红色(Red)、绿色(Green)、蓝色(Blue),这三种基本颜色可以通过不同比例的混合来生成其他颜色。RGB颜色空间是一个三维空间,每个颜色由三个分量的强度值决定,通常范围在0到255之间。这种颜色空间直观地反映了颜色的组成,但它并不总是与人眼对颜色的感知完全一致。
    在这里插入图片描述
  2. HSV颜色空间:HSV代表色调(Hue)、饱和度(Saturation)和亮度(Value)。HSV颜色空间特别适合于颜色分割和基于颜色的物体识别任务。色调表示颜色的种类,类似于色轮上的角度,范围从0到360度;饱和度表示颜色的纯度,从0%(灰色)到100%(完全饱和的颜色);亮度表示颜色的明暗程度,从0%(黑色)到100%(白色)。HSV颜色空间将颜色信息与亮度信息分离,因此在不同的光照条件下进行颜色识别时更为鲁棒。
    在这里插入图片描述
  3. LAB颜色空间:LAB颜色空间包括亮度(L*)、从绿到红的色度(a*)以及从蓝到黄的色度(b*)。这种颜色空间的设计旨在更好地匹配人类视觉的感知特性,使得颜色之间的数值差异与我们感知到的差异更为接近。LAB颜色空间特别适合于需要精确颜色差异匹配的应用场景,如颜色编辑和校正。
    在这里插入图片描述

2. HSV颜色空间

颜色空间的选择对于计算机视觉应用的性能有着显著影响。每种颜色空间都有其独特的属性,使其适用于特定的任务和场景。HSV颜色空间在基于颜色的物体检测中特别受欢迎,原因如下:

  1. 颜色与亮度分离:HSV颜色空间的一个关键特点是它将颜色信息(色调H)与亮度信息(亮度V)分开表示。这意味着即使在光照条件发生变化的情况下,物体的颜色特征(色调和饱和度)也能保持相对稳定。这种分离使得HSV颜色空间在处理光照变化时更为鲁棒,因为可以通过调整色调和饱和度的范围来检测特定颜色的物体,而不受亮度变化的影响。

  2. 直观的颜色表示:HSV颜色空间提供了一种更接近人类对颜色感知的表示方式。色调H是颜色的基本属性,它描述了颜色的种类,如红色、绿色或蓝色。饱和度S描述了颜色的纯度,即颜色的强度或鲜艳程度。这使得在HSV空间中定义和识别颜色变得更加直观和容易。

  3. 易于调整和过滤:在HSV颜色空间中,可以通过设置色调、饱和度和亮度的阈值来创建颜色掩码,从而过滤和检测特定颜色的物体。这种方法在图像处理和计算机视觉中非常有用,尤其是在需要从复杂背景中分离出特定颜色物体的应用中。

  4. 对阴影和反射的鲁棒性:由于HSV颜色空间将颜色与亮度分离,因此在物体被阴影覆盖或反射光线时,仍然可以有效地识别物体的颜色特征。这对于在各种环境条件下进行物体检测尤为重要。

HSV颜色空间是一种将颜色以色调(Hue)、饱和度(Saturation)和值(Value)三个维度来表示的方法,这种表示方式更接近人类对颜色的感知和理解:

  1. 色调(Hue):色调是颜色的基本属性,它描述了颜色的种类。色调通常用角度值来表示,范围从0度到360度。在HSV颜色模型中,色调的度量是以色轮为基础的,其中红色通常对应于0度(或360度,因为色轮是连续的),绿色对应于120度,蓝色对应于240度。色调的这种表示方式使得颜色的选择和调整变得直观,因为它与我们在日常生活中描述颜色的方式相一致。

  2. 饱和度(Saturation):饱和度描述了颜色的纯度或强度。饱和度的值范围从0%到100%,其中0%表示完全缺乏颜色(即灰色),而100%表示完全饱和的颜色。高饱和度的颜色看起来鲜艳、生动,而低饱和度的颜色则看起来暗淡、柔和。饱和度的调整可以改变图像的整体外观,使其看起来更生动或更柔和。

  3. 值(Value):值表示颜色的明暗程度,也就是颜色的亮度。值的范围也是从0%到100%,其中0%代表纯黑色,100%代表纯白色。值的改变可以影响颜色的明暗对比,但不会影响颜色的色调和饱和度。通过调整值,可以使物体在不同光照条件下保持其颜色特征,这对于在变化的环境中进行物体检测和识别非常重要。

3.基于颜色的物体检测

在这里插入图片描述
现在的目标是检测图像中的高尔夫球。创建一个名为color_detection_image.py的新文件,并添加以下代码:

import cv2

# 读取图像
image = cv2.imread("examples/1.jpg")

# 从BGR转换为HSV颜色空间
hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

第一步是读取图像并将其从BGR转换为HSV颜色空间。可以使用cv2.cvtColor()函数,并使用cv2.COLOR_BGR2HSV标志从BGR转换为HSV颜色空间。现在,定义想要检测的颜色范围。在这个例子中,将检测球的白色。可以通过定义HSV颜色空间的下限和上限来实现这一点。
对于白色,下限是(75, 0, 99),上限是(179, 62, 255)。可以更改这些值以检测其他颜色。这里创建了一个简单的Python脚本(一个HSV颜色选择器),这能获取的颜色的HSV值。要获取上面图像中白色高尔夫球的下限和上限,可以运行hsv_color_picker_images.py脚本,然后调整值直到获得所需的结果。这是的图像的一个示例:
在这里插入图片描述

# 白色下限和上限
lower_limit = np.array([
    75,
    0,
    99
])

upper_limit = np.array([
    179,
    62,
    255
])

# 为指定的颜色范围创建掩码
mask = cv2.inRange(hsv_image, lower_limit, upper_limit)

# 从掩码图像中获取边界框
bbox = cv2.boundingRect(mask)

然后使用cv2.inRange()函数为指定的颜色范围创建掩码。该函数接受HSV图像和颜色范围的下限和上限作为输入,并返回一个二进制掩码图像。然后可以使用cv2.boundingRect()函数获取图像中物体的边界框。该函数接受掩码图像作为输入,并返回边界框坐标(x, y, w, h),其中(x, y)是边界框的左上角,而(w, h)是边界框的宽度和高度。

# 如果我们得到一个边界框,使用它在图像上绘制一个矩形
if bbox is not None:
    print("物体检测到")
    x, y, w, h = bbox
    cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
else:
    print("物体未检测到")

cv2.imshow('图像', image)
cv2.waitKey(0)

在这里插入图片描述

4.视频中颜色的物体检测

# 初始化视频捕获对象
cap = cv2.VideoCapture("examples/1.mp4")

# 获取视频流中帧的宽度、高度和fps。
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = int(cap.get(cv2.CAP_PROP_FPS))

# 初始化FourCC和视频编写器对象
fourcc = cv2.VideoWriter_fourcc(*'XVID')
output = cv2.VideoWriter('output.mp4', fourcc, fps, (frame_width, frame_height))

使用cv2.VideoCapture()函数初始化视频捕获对象。将视频文件的路径作为输入。然后使用cv2.CAP_PROP_FRAME_WIDTH、cv2.CAP_PROP_FRAME_HEIGHT和cv2.CAP_PROP_FPS属性获取视频流中帧的宽度、高度和fps。然后可以初始化cv2.VideoWriter对象来写入输出视频。将输出视频文件的路径、FourCC代码、fps和帧的宽度和高度作为输入。

现在,让逐帧读取视频并对每一帧执行基于颜色的物体检测:

while True:
    ret, frame = cap.read()

    if not ret:
        print("没有更多帧可读,退出...")
        break

    # 从BGR转换为HSV颜色空间
    hsv_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

读取视频后,循环遍历帧并检查帧是否成功读取,使用ret变量。如果帧未成功读取,打印一条消息,表示没有更多帧可读并退出循环。如果帧成功读取,使用cv2.cvtColor()函数将帧的颜色空间从BGR转换为HSV。现在,检测的定义颜色范围。

# 蓝色下限和上限
lower_limit = np.array([
    99,
    135,
    51
])

upper_limit = np.array([
    116,
    226,
    255
])

mask = cv2.inRange(hsv_frame, lower_limit, upper_limit)

bbox = cv2.boundingRect(mask)

然后为指定的颜色范围创建掩码并获取帧中物体的边界框。然后使用边界框坐标在帧上绘制一个矩形(如果边界框不为空)并显示帧。将帧写入输出视频文件并检查用户是否按下了q键。如果退出循环。