基于物体颜色的目标检测与跟踪

Posted 有品位的小丑

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于物体颜色的目标检测与跟踪相关的知识,希望对你有一定的参考价值。

目录

一、项目内容

(1)利用摄像头,根据物体颜色,实现目标检测
(2)根据目标移动轨迹,绘制跟踪路径
(3)参考OpenCV中文官方文档(http://woshicver.com/),了解opencv在python中的应用
(4)思维导图:

二、项目分析

目标检测与跟踪项目是利用opencv2模块,通过颜色选择器提取出需要跟踪的颜色在HSV颜色空间中的具体数值范围,将提出出的数值以列表形式输入主函数参数里,再调用摄像头探测的该颜色的物体并计算出物体中心点,进行跟踪并绘制出其移动轨迹。

三、主要使用模块

① OpenCV 是其支持多语言、跨平台,功能强大。OpenCV-Python为OpenCV提供了Python接口,旨在解决计算机视觉问题的Python专用库。使得使用者在Python中能够调用C/C++,在保证易读性和运行效率的前提下,实现所需的功能。
② NumPy是Python的一种开源的数值计算扩展。这种工具可用来存储和处理大型矩阵,比Python自身的嵌套列表结构要高效的多(该结构也可以用来表示矩阵),支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。

四、选用HSV颜色空间

① HSI与 HSV非常相似,仅用亮度替代了明度。二者区别在于,一种纯色的明度等于白色的明度,而纯色的亮度等于中度灰的亮度。
② RGB和CMY颜色空间都是面向硬件的,而HSV颜色空间是面向用户的。 HSV模型对应于圆柱坐标系的一个圆锤形子集。圆锤的顶面对应于V=1,代表的颜色较亮。色调H由绕V轴的旋转角给定,红色对应于角度0°,绿色对应于角度120°,蓝色对应于角度240°。每一种颜色和它的补色相差180°
③ HSV的色相范围为[0,179],饱和度范围为[0,255],值范围为[0,255]

五、代码实现与分析

1. 颜色选择器:

该部分主要功能是用于选择跟踪物体的HSV颜色范围值并提取出来

1、导入代码需要使用的第三方库:cv2和numpy。

2、利用VideoCapture函数调用电脑摄像头,并设置视频流中帧的宽度和高度以及图像的亮度。

3、定义回调函数:
回调函数主要是为了降低函数之间调用的耦合性,即模块及模块之间信息或参数依赖的程度,从而实现解耦。

4、创建名为“HSV”的窗口,并设置其长宽。

5、设置窗口滑动条,设置数值上下界,以及滑块初始位置:

涉及两个函数,分别是:cv2.createTrackbar()和cv2.getTrackbarPos(),前者可用于创建一个可以调整数值的滑动条,后者用于更新当前滑块在轨迹的位置。
createTrackbar(参数1,参数2,参数3,参数4,参数5)
getTrackbarPos(参数1,参数2,参数3,参数4,参数5)
参数1:滑动条轨迹名
参数2:滑动条依附的窗口名
参数3:滑块的位置,创建时,滑块初始位置就是这个变量当前的值
参数4:轨迹的最大值
参数5:回调函数

6、利用循环,读取视频每一帧,并将其转变为HSV颜色模型,调节滑动块数值,分别将调节的HSV最小值和最大值转换为一个一维数组。

7、创建掩膜,利用上一步得到的一维数组设置HSV的阈值。

8、将掩膜和图像逐像素相加,并将掩膜转换为BGR颜色模型。

9、按水平方向堆叠,利用hstack函数将原图,掩膜和前两者相加后的视频帧显示出来。

10、完成所有操作后,释放系统资源。

相关代码:

import cv2 as cv
import numpy as np
cap = cv.VideoCapture(0)
cap.set(3, 200)  # 宽
cap.set(4, 200)   # 高
cap.set(10, 1000)   # 亮度

def nothing(a):
    pass

cv.namedWindow('HSV')
cv.resizeWindow('HSV', 640, 280)
cv.createTrackbar('H_min', 'HSV', 0, 179, nothing)
cv.createTrackbar('S_min', 'HSV', 0, 255, nothing)
cv.createTrackbar('V_min', 'HSV', 0, 255, nothing)
cv.createTrackbar('H_max', 'HSV', 179, 179, nothing)
cv.createTrackbar('S_max', 'HSV', 255, 255, nothing)
cv.createTrackbar('V_max', 'HSV', 255, 255, nothing)
ret = True
while ret == True:
    ret, img = cap.read() # 读取帧
    imgHSV = cv.cvtColor(img, cv.COLOR_BGR2HSV)

    h_min = cv.getTrackbarPos('H_min', 'HSV')
    s_min = cv.getTrackbarPos('S_min', 'HSV')
    v_min = cv.getTrackbarPos('V_min', 'HSV')
    h_max = cv.getTrackbarPos('H_max', 'HSV')
    s_max = cv.getTrackbarPos('S_max', 'HSV')
    v_max = cv.getTrackbarPos('V_max', 'HSV')
    print([h_min, s_min, v_min, h_max, s_max, v_max])
# 选取颜色范围
    lower = np.array([h_min, s_min, v_min])  # 转换为一维数组
    upper = np.array([h_max, s_max, v_max])
    mask = cv.inRange(imgHSV, lower, upper) # 设置HSV的阈值
    result = cv.bitwise_and(img, img, mask=mask) # 将掩膜和图像逐像素相加
    mask = cv.cvtColor(mask, cv.COLOR_GRAY2BGR)
    show = np.hstack([img, mask, result]) # 按水平方向(列顺序)堆叠数组构成一个新的数组堆叠的数组需要具有相同的维度
    cv.imshow('show', show)
    if cv.waitKey(1)& 0xFF == ord('q'):
        break
# 完成所有操作后,释放捕获器
cap.release()
cv.destroyAllWindows()

2. 实现检测并跟踪绘制移动轨迹:

利用颜色选择器所提取的数值,对摄像头所检测到的对应物体进行跟踪并绘制其移动轨迹

1、创建列表,用于存放颜色选择器得到的HSV数值以及设置对应的用于绘制移动轨迹的RGB颜色数值。

2、将列表里对应的HSV最小值和最大值转换为一个一维数组,并创建掩膜。

3、利用findContours函数找出图像轮廓
contours, hierarchy = cv.findContours(参数1,参数2,参数3)
参数1:单通道图像矩阵,
参数2:cv.RETR_EXTERNAL只检测最外围轮廓,包含在外围轮廓内的内围轮廓被忽略
参数3:cv.CHAIN_APPROX_NONE 保存物体边界上所有连续的轮廓点到contours向量内

4、计算轮廓面积,并判断面积大于500时,利用drawContours()函数画出图像轮廓。

5、利用boundingRect函数计算轮廓最外面的矩形边框,并计算出矩形的中心点坐标值。

6、通过返回的中心点坐标值,在视频帧的对应位置画出来

7、利用循环,更新视频流帧中每帧中心点位置,形成目标移动轨迹

相关核心代码:

import cv2 as cv
import numpy as np
cap = cv.VideoCapture(0)
cap.set(3, 800)  # 宽
cap.set(4, 600)   # 高
cap.set(10, 1000)   # 亮度
# 通过颜色选择器提取的颜色:橙,紫,绿
"""mycolors = [[5, 107, 0, 19, 255, 255],
            [133, 56, 0, 159, 156, 255],
            [57, 76, 0, 100, 255, 255],
            [90, 48, 0, 118, 255, 255]]
mycolorvalues = [[51, 153, 255],
                 [255, 0, 255],
                 [0, 255, 0],
                 [255, 0, 0]]"""
mycolors = [[0, 24, 41, 27, 186, 198]]
mycolorvalues = [[51, 153, 255]]
mypoints = [] # [x, y, color_id]
def findcolor(img, mycolors, mycolorvalues):
    imgHSV = cv.cvtColor(img, cv.COLOR_BGR2HSV)
    count = 0
    newpoints = []
    for color in mycolors:
        lower = np.array(color[0:3])
        upper = np.array(color[3:6])
        mask = cv.inRange(imgHSV, lower, upper)
        # getContours(mask)
        x, y = getContours(mask)
        cv.circle(imgresult, (x, y), 5, mycolorvalues[count], cv.FILLED) # 图片,中心点,半径,颜色,cv.FILLED为填充
        if x != 0 and y != 0:
            newpoints.append([x, y, count])
        count += 1
        # print(getContours(mask))
        # cv.imshow(str(color), mask)
    return newpoints

def getContours(img):
    contours, hierarchy = cv.findContours(img, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_NONE) # 找出图像轮廓
    x, y, w, h = 0, 0, 0, 0
    for cnt in contours:
        area = cv.contourArea(cnt) # 计算轮廓面积
        if area > 500:
            cv.drawContours(imgresult, cnt, -1, (255, 0, 0), cv.FILLED) # 画出图像轮廓
            peri = cv.arcLength(cnt, True) # 计算轮廓周长 参数2:表示轮廓是否封闭
            approx = cv.approxPolyDP(cnt, 0.02*peri, True)
            x, y, w, h = cv.boundingRect(approx)
    return x+w//2, y+h//2

def drawoncanvas(mypoints, mycolorvalues):
    for point in mypoints:
        cv.circle(imgresult, (point[0], point[1]), 5, mycolorvalues[point[2]], cv.FILLED)
while True:
    success, img = cap.read()
    imgresult = img.copy()
    newpoints = findcolor(img, mycolors, mycolorvalues)
    if len(newpoints) != 0:
        for newp in newpoints:
            mypoints.append(newp)
    if len(mypoints) != 0:
        drawoncanvas(mypoints, mycolorvalues)

    cv.imshow("Video", imgresult)

    if cv.waitKey(1) & 0xFF == ord('q'):
        break
cap.release()
cv.destroyAllWindows()

六、测试结果

(1)首先利用颜色选择器选出手机黑屏状态下的颜色,将得到的HSV数值加入主函数mycolors参数列表中([51, 17, 29, 163, 251, 69]),并在mycolorvalues参数中添加跟踪点的bgr颜色值([0, 0, 255])

(2)运行主函数,由图可知,蓝色区域为跟踪物体,红色为物体中心点,随着物体移动,红色中心点连成一条线,即物体移动轨迹:
初始态:

手机移动的轨迹:

(3)再次利用颜色选择器选出天猫精灵的颜色,将得到的HSV数值加入主函数mycolors参数列表中([170, 104, 89, 179, 255, 255]),并在mycolorvalues参数中添加跟踪点的bgr颜色值([0, 255, 0])

(4)运行主函数,此次将上述的两样物体同时展示,下图可知此程序也能很好的实现多物体检测与跟踪。检测结果容易受摄像头中其他同颜色的事物所影响,后续还需要继续加以改进。

以上是关于基于物体颜色的目标检测与跟踪的主要内容,如果未能解决你的问题,请参考以下文章

目标检测基于matlab GUI背景差分算法视频运动物体跟踪含Matlab源码 1915期

opencv运动车里检测跟踪轨迹不对

计算机视觉中的物体检测方法

opencv 目标跟踪一定要把被跟踪的物体圈出来吗?

[AI开发]基于深度学习的视频多目标跟踪实现

opencv 怎么识别出红色物体呀