【python】OpenCV—Tracking(10.5)—dlib

在这里插入图片描述

文章目录

  • 1、功能描述
  • 2、代码实现
  • 3、效果展示
  • 4、完整代码
  • 5、涉及到的库函数
    • dlib.correlation_tracker()
  • 6、参考

1、功能描述

基于 dlib 库,实现指定类别的目标检测和单目标跟踪

2、代码实现

caffe 模型

https://github.com/MediosZ/MobileNet-SSD/tree/master/mobilenet

或者

链接: https://pan.baidu.com/s/1fiBz6tEQmcXdw_dtaUuAVw?pwd=pw5n
提取码: pw5n

在这里插入图片描述

输入 1x3x300x300

输出的类别数为 21

在这里插入图片描述

在这里插入图片描述

导入必要的包

from imutils.video import FPS
import numpy as np
import argparse
import imutils
import dlib
import cv2

注意 dlib 的安装

conda 或者 pip 安装,如果 build 失败的话,可以试试下载 whl 安装

https://github.com/Silufer/dlib-python/tree/main

python -V 查看 python 版本,然后找到对应版本的 whl ,pip install xxx.whl


构造参数解析并解析参数

ap = argparse.ArgumentParser()
ap.add_argument("-p", "--prototxt", required=True,
                help="path to Caffe 'deploy' prototxt file")
ap.add_argument("-m", "--model", required=True,
                help="path to Caffe pre-trained model")
ap.add_argument("-v", "--video", required=True,
                help="path to input video file")
ap.add_argument("-l", "--label", required=True,
                help="class label we are interested in detecting + tracking")
ap.add_argument("-o", "--output", type=str,
                help="path to optional output video file")
ap.add_argument("-c", "--confidence", type=float, default=0.2,
                help="minimum probability to filter weak detections")
args = vars(ap.parse_args())

涉及到 caffe 模型的 prototxt,caffemodel,输入视频,类别标签,输出视频,检测框的置信度配置

moblienet SSD 支持的类别类型如下

CLASSES = ["background", "aeroplane", "bicycle", "bird", "boat",
           "bottle", "bus", "car", "cat", "chair", "cow", "diningtable",
           "dog", "horse", "motorbike", "person", "pottedplant", "sheep",
           "sofa", "train", "tvmonitor"]

加载模型,读取视频,初始化跟踪器

print("[INFO] loading model...")
net = cv2.dnn.readNetFromCaffe(args["prototxt"], args["model"])

# 初始化视频流、dlib 相关跟踪器、输出视频写入器和预测的类标签
print("[INFO] starting video stream...")
vs = cv2.VideoCapture(args["video"])
tracker = None
writer = None
label = ""
# 启动每秒帧数估计器
fps = FPS().start()

循环读取视频帧

# 循环播放视频文件流中的帧
while True:
    # 从视频文件中获取下一帧
    (grabbed, frame) = vs.read()
    # 检查我们是否已经到达视频文件的末尾
    if frame is None:
        break
    # 调整帧大小以加快处理速度,然后将帧从 BGR 转换为 RGB 排序(dlib 需要 RGB 排序)
    frame = imutils.resize(frame, width=600)
    rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    # 如果我们应该将视频写入磁盘,请初始化写入器
    if args["output"] is not None and writer is None:
        fourcc = cv2.VideoWriter_fourcc(*"MJPG")
        writer = cv2.VideoWriter(args["output"], fourcc, 30,
                                 (frame.shape[1], frame.shape[0]), True)

resize 图片至宽为 600,转化为 RGB 输入模式,设置输出视频相关配置

    # 如果我们的相关对象跟踪器是None,我们首先需要应用一个对象检测器来为跟踪器提供实际跟踪的东西
    if tracker is None:
        # 获得帧尺寸并将帧转换为 blob
        (h, w) = frame.shape[:2]
        blob = cv2.dnn.blobFromImage(frame, 0.007843, (w, h), 127.5)
        # blob传入网络并获得检测结果
        net.setInput(blob)
        detections = net.forward()

        # 确保至少有一个检测结果
        if len(detections) > 0:
            # 找到概率最大的检测索引——为方便起见,我们只跟踪我们以最大概率找到的第一个对象;
            # 未来的示例将演示如何检测和提取*特定*对象
            i = np.argmax(detections[0, 0, :, 2])
            # 获取与对象关联的概率及其类标签
            conf = detections[0, 0, i, 2]
            label = CLASSES[int(detections[0, 0, i, 1])]

            # filter out weak detections by requiring a minimum
            # confidence
            if conf > args["confidence"] and label == args["label"]:
                # compute the (x, y)-coordinates of the bounding box
                # for the object
                box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
                (startX, startY, endX, endY) = box.astype("int")
                # construct a dlib rectangle object from the bounding
                # box coordinates and then start the dlib correlation
                # tracker
                tracker = dlib.correlation_tracker()
                rect = dlib.rectangle(startX, startY, endX, endY)
                tracker.start_track(rgb, rect)
                # draw the bounding box and text for the object
                cv2.rectangle(frame, (startX, startY), (endX, endY),
                              (0, 255, 0), 2)
                cv2.putText(frame, label, (startX, startY - 15),
                            cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 255, 0), 2)

第一帧的时候,调用目标检测模型,获取检测结果 detections

如果检测到了目标,预测的分数大于配置的阈值,且预测的类别和配置的类别一致

初始化跟踪器 tracker,可视化检测结果


否则,我们已经执行了检测,所以让我们跟踪对象

    else:
        # 更新跟踪器并抓取被跟踪对象的位置
        tracker.update(rgb)
        pos = tracker.get_position()
        # 解包位置对象
        startX = int(pos.left())
        startY = int(pos.top())
        endX = int(pos.right())
        endY = int(pos.bottom())
        # 从相关对象跟踪器中绘制边界框
        cv2.rectangle(frame, (startX, startY), (endX, endY),
                      (0, 255, 0), 2)
        cv2.putText(frame, label, (startX, startY - 15),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 255, 0), 2)

后续帧采用跟踪算法,update 更新目标坐标后,通过 get_position 获取新的坐标,并可视化


    # 检查我们是否应该将帧写入磁盘
    if writer is not None:
        writer.write(frame)
    # 显示输出帧
    cv2.imshow("Frame", frame)
    key = cv2.waitKey(1) & 0xFF
    # 如果按下了“q”键,则退出循环
    if key == ord("q"):
        break
    # 更新FPS计数器
    fps.update()

保存和可视化结果,按 q 键退出视频流


# 我们的 fps 计数器停止并且 FPS 信息显示在终端中
fps.stop()
print("[INFO] elapsed time: {:.2f}".format(fps.elapsed()))
print("[INFO] approx. FPS: {:.2f}".format(fps.fps()))
# 然后,如果我们正在写入输出视频,我们释放视频编写器
if writer is not None:
    writer.release()
# 最后,我们关闭所有 OpenCV 窗口并释放视频流
cv2.destroyAllWindows()
vs.release()

完成信息统计,释放资源

3、效果展示

train_result

cat_result

4、完整代码

# 导入必要的包
from imutils.video import FPS
import numpy as np
import argparse
import imutils
import dlib
import cv2

# 构造参数解析并解析参数
ap = argparse.ArgumentParser()
ap.add_argument("-p", "--prototxt", required=True,
                help="path to Caffe 'deploy' prototxt file")
ap.add_argument("-m", "--model", required=True,
                help="path to Caffe pre-trained model")
ap.add_argument("-v", "--video", required=True,
                help="path to input video file")
ap.add_argument("-l", "--label", required=True,
                help="class label we are interested in detecting + tracking")
ap.add_argument("-o", "--output", type=str,
                help="path to optional output video file")
ap.add_argument("-c", "--confidence", type=float, default=0.2,
                help="minimum probability to filter weak detections")
args = vars(ap.parse_args())

# 初始化MobileNet SSD训练好的类标签列表
CLASSES = ["background", "aeroplane", "bicycle", "bird", "boat",
           "bottle", "bus", "car", "cat", "chair", "cow", "diningtable",
           "dog", "horse", "motorbike", "person", "pottedplant", "sheep",
           "sofa", "train", "tvmonitor"]
# 从磁盘加载我们的序列化模型
print("[INFO] loading model...")
net = cv2.dnn.readNetFromCaffe(args["prototxt"], args["model"])

# 初始化视频流、dlib 相关跟踪器、输出视频写入器和预测的类标签
print("[INFO] starting video stream...")
vs = cv2.VideoCapture(args["video"])
tracker = None
writer = None
label = ""
# 启动每秒帧数估计器
fps = FPS().start()

# 循环播放视频文件流中的帧
while True:
    # 从视频文件中获取下一帧
    (grabbed, frame) = vs.read()
    # 检查我们是否已经到达视频文件的末尾
    if frame is None:
        break
    # 调整帧大小以加快处理速度,然后将帧从 BGR 转换为 RGB 排序(dlib 需要 RGB 排序)
    frame = imutils.resize(frame, width=600)
    rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    # 如果我们应该将视频写入磁盘,请初始化写入器
    if args["output"] is not None and writer is None:
        fourcc = cv2.VideoWriter_fourcc(*"MJPG")
        writer = cv2.VideoWriter(args["output"], fourcc, 30,
                                 (frame.shape[1], frame.shape[0]), True)

    # 如果我们的相关对象跟踪器是None,我们首先需要应用一个对象检测器来为跟踪器提供实际跟踪的东西
    if tracker is None:
        # 获得帧尺寸并将帧转换为 blob
        (h, w) = frame.shape[:2]
        blob = cv2.dnn.blobFromImage(frame, 0.007843, (w, h), 127.5)
        # blob传入网络并获得检测结果
        net.setInput(blob)
        detections = net.forward()

        # 确保至少有一个检测结果
        if len(detections) > 0:
            # 找到概率最大的检测索引——为方便起见,我们只跟踪我们以最大概率找到的第一个对象;
            # 未来的示例将演示如何检测和提取*特定*对象
            i = np.argmax(detections[0, 0, :, 2])
            # 获取与对象关联的概率及其类标签
            conf = detections[0, 0, i, 2]
            label = CLASSES[int(detections[0, 0, i, 1])]

            # filter out weak detections by requiring a minimum
            # confidence
            if conf > args["confidence"] and label == args["label"]:
                # compute the (x, y)-coordinates of the bounding box
                # for the object
                box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
                (startX, startY, endX, endY) = box.astype("int")
                # construct a dlib rectangle object from the bounding
                # box coordinates and then start the dlib correlation
                # tracker
                tracker = dlib.correlation_tracker()
                rect = dlib.rectangle(startX, startY, endX, endY)
                tracker.start_track(rgb, rect)
                # draw the bounding box and text for the object
                cv2.rectangle(frame, (startX, startY), (endX, endY),
                              (0, 255, 0), 2)
                cv2.putText(frame, label, (startX, startY - 15),
                            cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 255, 0), 2)

    # 否则,我们已经执行了检测,所以让我们跟踪对象
    else:
        # 更新跟踪器并抓取被跟踪对象的位置
        tracker.update(rgb)
        pos = tracker.get_position()
        # 解包位置对象
        startX = int(pos.left())
        startY = int(pos.top())
        endX = int(pos.right())
        endY = int(pos.bottom())
        # 从相关对象跟踪器中绘制边界框
        cv2.rectangle(frame, (startX, startY), (endX, endY),
                      (0, 255, 0), 2)
        cv2.putText(frame, label, (startX, startY - 15),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 255, 0), 2)
    # 检查我们是否应该将帧写入磁盘
    if writer is not None:
        writer.write(frame)
    # 显示输出帧
    cv2.imshow("Frame", frame)
    key = cv2.waitKey(1) & 0xFF
    # 如果按下了“q”键,则退出循环
    if key == ord("q"):
        break
    # 更新FPS计数器
    fps.update()

# 我们的 fps 计数器停止并且 FPS 信息显示在终端中
fps.stop()
print("[INFO] elapsed time: {:.2f}".format(fps.elapsed()))
print("[INFO] approx. FPS: {:.2f}".format(fps.fps()))
# 然后,如果我们正在写入输出视频,我们释放视频编写器
if writer is not None:
    writer.release()
# 最后,我们关闭所有 OpenCV 窗口并释放视频流
cv2.destroyAllWindows()
vs.release()

测试脚本1

python .\track.py -p .\mobilenet_ssd\MobileNetSSD_deploy.prototxt -m .\mobilenet_ssd\MobileNetSSD_deploy.caffemodel -v .\cat.mp4 -l cat -o cat_result.mp4

测试脚本2

python .\track.py -p .\mobilenet_ssd\MobileNetSSD_deploy.prototxt -m .\mobilenet_ssd\MobileNetSSD_deploy.caffemodel -v .\train.mp4 -l aeroplane -o train_result.mp4

5、涉及到的库函数

dlib.correlation_tracker()

dlib.correlation_tracker 是 Dlib 库中的一个功能,用于实现目标跟踪(Object Tracking)。

dlib.correlation_tracker 基于判别式相关滤波器(Discriminative Correlation Filter, DCF)的方法,这种方法通过训练一个滤波器来区分目标对象和背景,从而实现高效的跟踪。

使用 dlib.correlation_tracker 跟踪目标通常涉及以下几个步骤:

  • 初始化跟踪器:首先,你需要创建一个 correlation_tracker 对象。这通常是在你已知目标对象在第一帧中的位置时进行的。
  • 设置目标区域:你需要指定一个矩形区域(通常通过左上角和右下角的坐标或者通过中心点和尺寸)来标识目标对象在第一帧中的位置。
  • 更新跟踪器:对于后续的视频帧,你需要将新的帧传递给跟踪器,并让它更新目标的位置。这个过程会不断重复,直到视频结束或者跟踪失败。
  • 获取跟踪结果:每次更新后,你可以从跟踪器中获取当前帧中目标对象的位置。

以下是一个简单的示例,展示了如何使用 dlib.correlation_tracker 进行目标跟踪:

import dlib
import cv2
 
# 加载视频
cap = cv2.VideoCapture('video.mp4')
 
# 读取第一帧
ret, frame = cap.read()
 
# 选择目标区域(这里需要手动选择或者通过某种方法自动选择)
rect = dlib.rectangle(50, 50, 200, 200)  # 示例矩形,需要替换为实际的目标位置
 
# 创建跟踪器
tracker = dlib.correlation_tracker()
tracker.start_track(frame, rect)
 
while cap.isOpened():
    ret, frame = cap.read()
    if not ret:
        break
 
    # 更新跟踪器
    tracker.update(frame)
 
    # 获取跟踪结果
    rect = tracker.get_position()
 
    # 在帧上绘制跟踪结果
    cv2.rectangle(frame, (rect.left(), rect.top()), (rect.right(), rect.bottom()), (0, 255, 0), 2)
 
    # 显示结果
    cv2.imshow('Tracking', frame)
 
    # 按下 'q' 键退出
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
 
# 释放资源
cap.release()
cv2.destroyAllWindows()

注意事项

  • 目标初始化:目标在第一帧中的位置对于跟踪器的性能至关重要。如果初始化不准确,跟踪可能会失败。
  • 视频质量:视频的质量(如分辨率、帧率、光照条件等)也会影响跟踪器的性能。
  • 遮挡和快速移动:当目标被遮挡或者快速移动时,跟踪器可能会遇到困难。虽然 dlib.correlation_tracker 已经在很多场景下表现良好,但在这些情况下可能需要更复杂的策略。

通过 dlib.correlation_tracker,你可以实现高效且相对准确的目标跟踪,适用于各种计算机视觉应用,如视频监控、人机交互等。

6、参考

  • 目标跟踪(4)使用dlib进行对象跟踪
  • dlib–win系统所有版本文件下载地址whl文件

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/926241.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Python数据分析】房价预测:使用线性回归模型预测波士顿房价

博客主页:小馒头学python 本文专栏: Python爬虫五十个小案例 专栏简介:分享五十个Python爬虫小案例 📝引言 📝房价预测的意义 房价预测对于房地产行业、投资者和政策制定者来说具有重要意义。通过对房价进行准确预测&#xf…

java——PV操作

PV操作通常指的是P操作和V操作,它们是信号量(Semaphore)机制中的两个基本操作,用于解决进程或线程间的同步和互斥问题。P操作(也称为wait操作或down操作)用于将信号量的值减1,如果结果为负数&am…

5. langgraph实现高级RAG (Adaptive RAG)

1. 数据准备 from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain_community.document_loaders import WebBaseLoader from langchain_community.vectorstores import Chromaurls ["https://lilianweng.github.io/posts/2023-06-23-age…

redis基础spark操作redis

Redis内存淘汰策略 将Redis用作缓存时,如果内存空间用满,就会自动驱逐老的数据。 为什么要使用内存淘汰策略呢? 当海量数据涌入redis,导致redis装不下了咋办,我们需要根据redis的内存淘汰策略,淘汰一些不那…

C++优选算法十七 多源BFS

1.单源最短路问题 一个起点一个终点。 定义:在给定加权图中,选择一个顶点作为源点,计算该源点到图中所有其他顶点的最短路径长度。 2.多源最短路问题 定义:多源最短路问题指的是在图中存在多个起点,需要求出从这些…

DDR3保姆级使用教程:ZYNQ 7010

内容:使用DDR3 IP核,向DDR3写入数据,然后再读出数据,通过串口打印。 设备:ZYNQ 7010 xc7z010clg-400-1。软件VIVADO 2018.3 (1)工程模块:一个写FIFO,一个读FIFO。一个ZYNQ IP核&am…

vue3使用monaco编辑器(VSCode网页版)

vue3使用monaco编辑器(VSCode网页版) 文章说明参考文章核心代码效果展示实践说明源码下载 文章说明 一直在找网页版的编辑器,网页版的VSCode功能很强大,这个monaco就是VSCode样式的编辑器,功能很强大,可以直…

Y20030019 基于java+jsp+mysql的微信小程序校园二手交易平台的设计与实现 源代码 文档

旅游度假区微信小程序 1.摘要2. 系统开发的目的和意义3.系统功能4.界面展示5.源码获取 1.摘要 随着移动互联网的发展,微信小程序已经成为人们生活中不可或缺的一部分。微信小程序的优点在于其快速、轻量、易用,用户无需下载即可使用,节省了用…

uniapp实现列表页面,实用美观

咨询列表页面 组件 <template><view><view class"news_item" click"navigator(item.id)" v-for"item in list" :key"item.id"><image :src"item.img_url"></image><view class"righ…

哈希表,哈希桶的实现

哈希概念 顺序结构以及平衡树中&#xff0c;元素关键码与其存储位置之间没有对应的关系&#xff0c;因此在查找一个元素 时&#xff0c;必须要经过关键码的多次比较。顺序查找时间复杂度为O(N)&#xff0c;平衡树中为树的高度&#xff0c;即 O(logN)&#xff0c;搜索的效率取决…

网络安全(三):网路安全协议

网络安全协议设计的要求是实现协议过程中的认证性、机密性与不可否认性。网络安全协议涉及网络层、传输层与应用层。 1、网络层安全与IPSec协议、IPSec VPN 1.1、IPSec安全体系结构 IP协议本质上是不安全的额&#xff0c;伪造一个IP分组、篡改IP分组的内容、窥探传输中的IP分…

Golang教程第8篇(语言条件语句)

Go 语言条件语句 条件语句需要开发者通过指定一个或多个条件&#xff0c;并通过测试条件是否为 true 来决定是否执行指定语句&#xff0c;并在条件为 false 的情况在执行另外的语句。 Go 语言 if 语句 Go 语言条件语句 Go 语言条件语句 if 语句由布尔表达式后紧跟一个或多个语…

基于MFC实现的银行模拟系统

基于MFC实现的银行模拟系统 1.软硬件运行环境 1.1 项目研究背景与意义 为了能给学生熟悉银行业务系统提供真实的操作环境, 使学生在掌握理论知识的同时熟悉银行业务的实际操作过程&#xff0c;改变其知识结构&#xff0c;培养商业银行真正需要的实用人才&#xff0c;增强学生…

Qt自定义 Widget 组件

自定义 Widget 子类 QmyBattery Qt 的 UI 设计器提供了很多 GUI 设计的界面组件&#xff0c;可以满足常见的界面设计需求。但是某些时候需要设计一些特殊的界面组件&#xff0c;而在 UI 设计器的组件面板里根本没有合适的组件&#xff0c;这时就需要设计自定义的界面组件。 所…

Flink双流Join

在离线 Hive 中&#xff0c;我们经常会使用 Join 进行多表关联。那么在实时中我们应该如何实现两条流的 Join 呢&#xff1f;Flink DataStream API 为我们提供了3个算子来实现双流 join&#xff0c;分别是&#xff1a; join coGroup intervalJoin 下面我们分别详细看一下这…

WEB攻防-通用漏洞XSS跨站绕过修复http_onlyCSP标签符号

修复&#xff1a; 1、过滤一些危险字符&#xff1b; 2、HTTP-only Cookie; 3、设置CSP&#xff08;Content Security Policy&#xff09;; 4、输入内容长度限制&#xff0c;转义等&#xff1b; XSS绕过-CTFSHOW-316到331 关卡绕过WP XSS修复-过滤函数&http_only&C…

python 生成tts语音

之前一直使用微软、或者国内大厂的接口&#xff0c;网页操作比较麻烦&#xff0c;最近发现一个python库可以完美解决&#xff0c;在这里分享给大家 在这里 GitHub - rany2/edge-tts: Use Microsoft Edges online text-to-speech service from Python WITHOUT needing Microsof…

嵌入式硬件实战提升篇(三)商用量产电源设计方案 三路电源输入设计 电源管理 多输入供电自动管理 DCDC降压

引言&#xff1a;本文你能实际的了解到实战量产产品中电源架构设计的要求和过程&#xff0c;并且从实际实践出发搞懂电源架构系统&#xff0c;你也可以模仿此架构抄板到你自己的项目&#xff0c;并结合硬件篇之前的项目以及理论形成正真的三路电源输入设计与开发板电源架构块供…

SAP SD学习笔记16 - 请求书的取消 - VF11

上一章讲了 返品处理流程中的 参照请求传票&#xff08;发票&#xff09;来生成返品传票。 SAP SD学习笔记15 - 返品处理流程2 - 参照请求传票&#xff08;发票&#xff09;来生成返品传票-CSDN博客 本章讲 请求传票的取消。 目录 1&#xff0c;请求书取消的概要 2&#xf…

CLIP-MMA: Multi-Modal Adapter for Vision-Language Models

当前的问题 CLIP-Adapter仅单独调整图像和文本嵌入&#xff0c;忽略了不同模态之间的交互作用。此外&#xff0c;适应性参数容易过拟合训练数据&#xff0c;导致新任务泛化能力的损失。 动机 图1所示。多模态适配器说明。 通过一种基于注意力的 Adapter &#xff0c;作者称之…