11- OpenCV进行目标追踪 (OpenCV系列) (机器视觉)

2023-05-16

知识要点

1. OpenCV目标跟踪算法的使用大概可以分为以下几个步骤:

  1. 创建MultiTracker对象:  trackers = cv2.legacy.MultiTracker_create()

  2. 读取视频或摄像头数据:  cap = cv2.VideoCapture('./videos/soccer_02.mp4')

  3. 框选ROI区域:  roi = cv2.selectROI('frame', frame, showCrosshair = True)

  4. 添加实际的追踪算法.  tracker = OPENCV_OBJECT_TRACKERS['boosting'](), trackers.add(tracker, frame, roi)

  5. 对每一帧进行进行目标追踪: success, boxes = trackers.update(frame) 

2. 光流估计:(稀疏光流估计算法为Lucas-Kanade算法, 比较经典)

  • p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, gray, p0, None,winSize=(15,15),maxLevel=2) # p1为更新的点, st是状态
  • cv2.calcOpticalFlowPyrLK()      # 稀疏光流
  • cv2.calcOpticalFlowFarneback()     # 稠密光流

随机颜色 数组生成:

  • color = np.random.randint(0, 255, (100, 3))

参考资料:  目标追踪综述 - 知乎


12 目标追踪

12.1 OpenCV目标追踪算法介绍

OpenCV上有八种不同的目标追踪算法:

  • BOOSTING Tracker:和Haar cascades(AdaBoost)背后所用的机器学习算法相同,但是距其诞生已有十多年了。这一追踪器速度较慢,并且表现不好。(最低支持OpenCV 3.0.0)
  • MIL Tracker:比上一个追踪器更精确,但是失败率比较高。(最低支持OpenCV 3.0.0)
  • KCF Tracker:比BOOSTING和MIL都快,但是在有遮挡的情况下表现不佳。(最低支持OpenCV 3.1.0)
  • CSRT Tracker比KCF稍精确,但速度不如后者。(最低支持OpenCV 3.4.2)
  • MedianFlow Tracker:出色的跟踪故障报告。当运动是可预测的并且没有遮挡时,效果非常好,但是对于快速跳动或快速移动的物体,模型会失效。(最低支持OpenCV 3.0.0)
  • TLD Tracker:在多帧遮挡下效果最好。但是TLD的误报非常多,所以不推荐。(最低支持OpenCV 3.0.0)
  • MOSSE Tracker速度真心快,但是不如CSRT和KCF的准确率那么高,如果追求速度选它准没错(最低支持OpenCV 3.4.1)
  • GOTURN Tracker:这是OpenCV中唯一一深度学习为基础的目标检测器。它需要额外的模型才能运行。(最低支持OpenCV 3.2.0)

12.2  目标跟踪算法的使用

OpenCV目标跟踪算法的使用大概可以分为以下几个步骤:

  1. 创建MultiTracker对象.

  2. 读取视频或摄像头数据.

  3. 框选ROI区域

  4. 给MultiTracker对象添加实际的追踪算法.

  5. 对每一帧进行进行目标追踪.

下面是一个使用例子:

import cv2
import numpy as np

cap = cv2.VideoCapture('./videos/los_angeles.mp4') # 读取视频
# 定义OpenCV的七种追踪算法
OPENCV_OBJECT_TRACKERS = {
    'boosting' : cv2.legacy.TrackerBoosting_create,
    'csrt' : cv2.legacy.TrackerCSRT_create,
    'kcf' : cv2.legacy.TrackerKCF_create,
    'mil' : cv2.legacy.TrackerMIL_create,
    'tld' : cv2.legacy.TrackerTLD_create,
    'medianflow' : cv2.legacy.TrackerMedianFlow_create,
    'mosse' :cv2.legacy.TrackerMOSSE_create}
trackers = cv2.legacy.MultiTracker_create()   # 创建追踪器

while True:
    flag, frame = cap.read()
    if frame is None:
        break
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)  # 变为黑白的
    # 目标追踪, # 第一帧追踪时为空,跳过
    success, boxes = trackers.update(frame)
    # print(boxes)   # [[685. 433. 106.  84.]] 矩形位置会有调整
    # 绘制追踪到的矩形区域
    for box in boxes:
        # box是float的数据类型
        (x, y, w, h) = [int(v) for v in box]
        cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 2)
    
    cv2.imshow('frame', frame)
    key = cv2.waitKey(1)
    if key == ord('s'):
        # 框选ROI区域, 后两个参数的含义,是否包含中间十字和从中心点开始画
        roi = cv2.selectROI('frame',frame, showCrosshair = True, fromCenter = False)
        print(roi)    # (1075, 326, 46, 70)
        # 创建实际的追踪器
        tracker = OPENCV_OBJECT_TRACKERS['boosting']()
        trackers.add(tracker, frame, roi)
    elif key == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

 12.3  opencv 和深度学习结合 做目标识别

  • 目标识别?

  • 把图片变成tensor:  blob = cv2.dnn.blobFromImage(img)

  • 把图片给到网络预测net.setInput(blob)

  • 预测net.forward()

import cv2
import numpy as np

img = cv2.imread('./smallcat.jpeg')   # 读图片
# opencv 和深度学习结合
config = './bvlc_googlenet.prototxt'   # 分类文件
model = './bvlc_googlenet.caffemodel'   # 模型
net = cv2.dnn.readNetFromCaffe(config, model)

# 图片转化为tensor
blob = cv2.dnn.blobFromImage(img, 1.0, (224, 224), (104, 117, 223))
net.setInput(blob)
r = net.forward()
print(r.shape)   # (1, 1000)  1000类
# 读类别  # 看下比较明显的特征
classes = []
with open('./synset_words.txt', 'r') as fp:
    # find 函数返回字符串的索引  # strip 去掉结尾换行符号
    classes = [x[x.find(' ') + 1:].strip() for x in fp]
# 对得到的结果排序
order = sorted(r[0], reverse = True)   # 1000类

z = list(range(3))    # [0, 1, 2]  # 只要前三的概率
for i in range(3):
    # 返回满足条件的索引
    z[i] = np.where(r[0] == order[i])[0][0]
    print(f'第{i + 1}项匹配:', classes[z[i]], end = '')
    print(' 类所在行:', z[i] + 1, ' ', '可能性:', order[i])
    
cv2.imshow('img', img)
cv2.waitKey(50000)
cv2.destroyAllWindows()

第1项匹配: tabby, tabby cat 类所在行: 282   可能性: 0.2946576
第2项匹配: Egyptian cat 类所在行: 286   可能性: 0.2306798
第3项匹配: carton 类所在行: 479   可能性: 0.061365135  

13 光流估计

光流,顾名思义,光的流动比如人眼感受到的夜空中划过的流星。在计算机视觉中,定义图像中对象的移动,这个移动可以是相机移动或者物体移动引起的。具体是指,视频图像的一帧中的代表同一对象(物体)像素点移动到下一帧的移动量,使用二维向量表示.

根据是否选取图像稀疏点进行光流估计,可以将光流估计分为稀疏光流和稠密光流.

OpenCV中提供了光流估计的接口,包括 稀疏光流估计算法 cv2.calcOpticalFlowPyrLK(),和 稠密光流估计 cv2.calcOpticalFlowFarneback()。其中稀疏光流估计算法为Lucas-Kanade算法,该算法为1981年由Lucas和Kanade两位科学家提出的,最为经典也较容易理解的算法.

13.1 传统算法 Lucas-Kanade

为了将光流估计进行建模,Lucas-Kanade做了三个重要的假设:

  • 亮度恒定:同一点随着时间的变化,其亮度不会发生改变。

  • 小运动:随着时间的变化不会引起位置的剧烈变化,只有小运动情况下才能用前后帧之间单位位置变化引起的灰度变化去近似灰度对位置的偏导数。

  • 空间一致:一个场景上邻近的点投影到图像上也是邻近点,且邻近点速度一致。因为光流法基本方程约束只有一个,而要求x,y方向的速度,有两个未知变量。所以需要连立n多个方程求解。

cv2.calcOpticalFlowPyrLK(): 参数:

  • prevImage 前一帧图像

  • nextImage 当前帧图像

  • prevPts 待跟踪的特征点向量

  • winSize 搜索窗口的大小

  • maxLevel 最大的金字塔层数

返回值:

  • nextPts 输出跟踪特征点向量

  • status 特征点是否找到,找到的状态为1,未找到的状态为0

import numpy as np
import cv2

cap = cv2.VideoCapture('./test.avi')  # 读取视频
ret, old_frame = cap.read()  # 获取第一帧的图片
old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)  # 变成黑白图

# 检测角点
feature_params = dict(maxCorners = 100,
                      qualityLevel = 0.3,
                      minDistance = 7)
p0 = cv2.goodFeaturesToTrack(old_gray, mask = None, **feature_params)

# 创建mask
mask = np.zeros_like(old_frame)
# 随机颜色
color = np.random.randint(0, 255, (100, 3))
while True:
    ret, frame = cap.read()
    if frame is None:
        break
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    # 光流估计, p1为更新的点, st是状态
    p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, gray, p0, None,
                                           winSize = (15, 15), maxLevel = 2) 
    # print(p1.shape, '==', st.shape)   # (31, 1, 2) == (31, 1)
    
    # 哪些点找到了哪些没找到
    good_new = p1[st == 1]
    good_old = p0[st == 1]
    # print(good_new.shape, good_old.shape)   # (38, 2) (38, 2)
    # 绘制轨迹
    for i, (new, old) in enumerate(zip(good_new, good_old)):
        a, b = new.ravel()
        c, d = old.ravel()
        mask = cv2.line(mask, (int(a), int(b)), (int(c), int(d)),
                        color[i].tolist(), 2) # 画线,随机颜色
        frame = cv2.circle(frame, (int(a), int(b)), 5, color[i].tolist(), -1)
        
    img = cv2.add(frame, mask)
    cv2.imshow('frame', img)
    key = cv2.waitKey(10)
    if key == ord('q'):
        break
    # 更新每一帧
    old_gray = gray.copy()
    p0 = good_new.reshape(-1, 1, 2)
    # print('p0de', p0.shape)   # p0de (38, 1, 2)
cap.release()
cv2.destroyAllWindows()

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

11- OpenCV进行目标追踪 (OpenCV系列) (机器视觉) 的相关文章

  • 相机姿态估计(OpenCV PnP)

    我正在尝试使用网络摄像头从具有已知全球位置的四个基准点的图像中获取全局姿态估计 我检查了许多 stackexchange 问题和一些论文 但似乎无法得到正确的解决方案 我得到的位置数字是可重复的 但与相机移动绝不成线性比例 仅供参考 我正在
  • cv2.cv.BoxPoints(rect) 返回什么?

    rect cv2 minAreaRect largest contour rect rect 0 0 self scale down rect 0 1 self scale down rect 1 0 self scale down rec
  • 带有 OpenCV 的增强现实 SDK [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 使用 openCV 和 python 检测物体

    我正在尝试使用 OpenCV 和 Python 检测下图中的白点 我尝试使用函数 cv2 HoughCircles 但没有成功 我需要使用不同的方法吗 这是我的代码 import cv2 cv import numpy as np impo
  • 为什么这些双精度数的返回值为-1.#IND?

    I have double score cvMatchContourTrees CT1 CT2 CV CONTOUR TREES MATCH I1 0 0 cout lt
  • brew 链接 jpeg 问题

    我正在尝试安装opencv在 Mac OSX Lion 上 brew install opencv 我收到以下错误 以及其他一些类似的错误 Error The linking step did not complete successful
  • 计算两个描述符之间的距离

    我正在尝试计算已计算的两个描述符之间的距离 欧几里得或汉明 问题是我不想使用匹配器 我只想计算两个描述符之间的距离 我正在使用 OpenCV 2 4 9 并且我的描述符存储在 Mat 类型中 Mat descriptors1 Mat des
  • 如何在opencv python中为图像添加边框

    如果我有如下图所示的图像 如何在图像周围添加边框 以便最终图像的整体高度和宽度增加 但原始图像的高度和宽度保持在中间 下面的代码添加了一个大小恒定的边框10像素到原始图像的所有四个边 对于颜色 我假设您想要使用背景的平均灰度值 这是我根据图
  • 来自 OpenCV 的外部参数

    我正在使用 OpenCV 来校准立体相机对 我拍摄了各种校准照片 并且使用 cv2 calibrateCamera 对内在参数进行了令人满意的拟合 然而 目前尚不清楚如何获取外部参数 该函数仅返回cameraMatrix 尽管它很有用 但实
  • 使用opencv计算深度视差图

    我无法使用 opencv 从视差图计算深度 我知道两个立体图像中的距离是用以下公式计算的z baseline focal disparity p 但我不知道如何使用地图计算视差 我使用的代码如下 为我提供了两个图像的视差图 import n
  • OpenCV 仅围绕大轮廓绘制矩形?

    第一次发帖 希望我以正确的方式放置代码 我正在尝试检测和计算视频中的车辆 因此 如果您查看下面的代码 我会在阈值处理和膨胀后找到图像的轮廓 然后我使用 drawContours 和矩形在检测到的轮廓周围绘制一个框 我试图在 drawCont
  • 来自连接到远程机器的相机的 Opencv 流

    我正在用 python 开发一个 wx 应用程序 用于流式传输和显示来自两个不同网络摄像头的视频 这工作正常 但现在我需要在不同的场景中执行此操作 其中两个摄像头连接在通过网络连接的 Windows 上运行的单独计算机中 我的应用程序将在机
  • opencv形态扩张滤波器作为最大滤波器

    就像中值滤波器的定义一样 我可以将 最大滤波器 定义为局部窗口 例如dst x y max 3x3 局部窗口像素 但我在opencv中找不到这样的过滤器 最接近的是 dilate 函数 然后我使用 dilate 函数的默认配置 但结果不正确
  • 如何在 OpenCV 中从 YUV 文件读取帧?

    如何在 OpenCV 中从 YUV 文件读取帧 我编写了一个非常简单的 python 代码来从二进制文件读取 YUV NV21 流 import cv2 import numpy as np class VideoCaptureYUV de
  • OpenCV Visual Studio ntdll.dll

    我尝试在 Visual Studio 2013 上使用 OpenCV 2 4 10 创建一个项目 但由于以下异常 到目前为止我运气不佳 请建议帮助 TIA letstryitonemoretime exe Win32 Loaded C Us
  • OpenCV 2.3 与 VS 2008 - 鼠标事件

    强制性 我是新手 有一份涉及编程的工作 并且我一边工作一边自学 不用说 作为一名老师 我经常犯彻底的错误 我现在所处的位置 我创建了 Graph 类 它 令人惊讶的是 制作了图表 但现在我想通过单击鼠标来修改图形 但我似乎无法让鼠标处理程序
  • 创建 OpenCV 的 mouseCallback 函数的基于类的实现时遇到问题

    正如标题所示 我在基于类的 C 结构中实现 OpenCV 的 mouseCallback 函数时遇到了一些麻烦 请允许我解释一下 我定义了一个名为 BriskMatching 的类 在其中创建了一个名为 mouseCallback 的成员函
  • 如何去除给定图像中的噪声,使 ocr 输出完美?

    我已经对这个孟加拉文本图像进行了大津阈值处理 并使用 tesseract 进行 OCR 但输出非常糟糕 我应该应用什么预处理来消除噪音 我也想校正图像 因为它有轻微的倾斜 我的代码如下 import tesserocr from PIL i
  • 从包含带边框的表格的图像中提取表格结构

    我正在尝试提取下表中的单元格位置 应用自适应阈值处理后 我能够获得细胞位置周围的轮廓 并且 HoughLines 获得垂直和水平结构元素 这是我的代码 img cv2 imread os path join img path file im
  • OpenCV 跟踪器:模型未在函数 init 中初始化

    在视频的第一帧 我运行一个对象检测器 它返回对象的边界框 如下所示

随机推荐