如何实时检测对象并自动跟踪它,而不是用户必须在要跟踪的对象周围绘制边界框?

2023-12-19

我有以下代码,用户可以按p要暂停视频,请在要跟踪的对象周围绘制一个边界框,然后按 Enter(回车)以跟踪视频源中的该对象:

import cv2
import sys

major_ver, minor_ver, subminor_ver = cv2.__version__.split('.')

if __name__ == '__main__' :

    # Set up tracker.
    tracker_types = ['BOOSTING', 'MIL','KCF', 'TLD', 'MEDIANFLOW', 'GOTURN', 'MOSSE', 'CSRT']
    tracker_type = tracker_types[1]

    if int(minor_ver) < 3:
        tracker = cv2.Tracker_create(tracker_type)
    else:
        if tracker_type == 'BOOSTING':
            tracker = cv2.TrackerBoosting_create()
        if tracker_type == 'MIL':
            tracker = cv2.TrackerMIL_create()
        if tracker_type == 'KCF':
            tracker = cv2.TrackerKCF_create()
        if tracker_type == 'TLD':
            tracker = cv2.TrackerTLD_create()
        if tracker_type == 'MEDIANFLOW':
            tracker = cv2.TrackerMedianFlow_create()
        if tracker_type == 'GOTURN':
            tracker = cv2.TrackerGOTURN_create()
        if tracker_type == 'MOSSE':
            tracker = cv2.TrackerMOSSE_create()
        if tracker_type == "CSRT":
            tracker = cv2.TrackerCSRT_create()

    # Read video
    video = cv2.VideoCapture(0) # 0 means webcam. Otherwise if you want to use a video file, replace 0 with "video_file.MOV")

    # Exit if video not opened.
    if not video.isOpened():
        print ("Could not open video")
        sys.exit()

    while True:

        # Read first frame.
        ok, frame = video.read()
        if not ok:
            print ('Cannot read video file')
            sys.exit()
        
        # Retrieve an image and Display it.
        if((0xFF & cv2.waitKey(10))==ord('p')): # Press key `p` to pause the video to start tracking
            break
        cv2.namedWindow("Image", cv2.WINDOW_NORMAL)
        cv2.imshow("Image", frame)
    cv2.destroyWindow("Image");

    # select the bounding box
    bbox = (287, 23, 86, 320)

    # Uncomment the line below to select a different bounding box
    bbox = cv2.selectROI(frame, False)

    # Initialize tracker with first frame and bounding box
    ok = tracker.init(frame, bbox)

    while True:
        # Read a new frame
        ok, frame = video.read()
        if not ok:
            break
        
        # Start timer
        timer = cv2.getTickCount()

        # Update tracker
        ok, bbox = tracker.update(frame)

        # Calculate Frames per second (FPS)
        fps = cv2.getTickFrequency() / (cv2.getTickCount() - timer);

        # Draw bounding box
        if ok:
            # Tracking success
            p1 = (int(bbox[0]), int(bbox[1]))
            p2 = (int(bbox[0] + bbox[2]), int(bbox[1] + bbox[3]))
            cv2.rectangle(frame, p1, p2, (255,0,0), 2, 1)
        else :
            # Tracking failure
            cv2.putText(frame, "Tracking failure detected", (100,80), cv2.FONT_HERSHEY_SIMPLEX, 0.75,(0,0,255),2)

        # Display tracker type on frame
        cv2.putText(frame, tracker_type + " Tracker", (100,20), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (50,170,50),2);
    
        # Display FPS on frame
        cv2.putText(frame, "FPS : " + str(int(fps)), (100,50), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (50,170,50), 2);

        # Display result
        cv2.imshow("Tracking", frame)

        # Exit if ESC pressed
        k = cv2.waitKey(1) & 0xff
        if k == 27 : break

现在,我不让用户暂停视频并在对象周围绘制边界框,而是如何使其能够自动检测我感兴趣的特定对象(在我的例子中是牙刷),只要它被引入视频源,然后跟踪它?

I found this https://heartbeat.fritz.ai/detecting-objects-in-videos-and-camera-feeds-using-keras-opencv-and-imageai-c869fe1ebcdb文章讨论了如何使用 ImageAI 和 Yolo 检测视频中的对象。

from imageai.Detection import VideoObjectDetection
import os
import cv2

execution_path = os.getcwd()

camera = cv2.VideoCapture(0) 

detector = VideoObjectDetection()
detector.setModelTypeAsYOLOv3()
detector.setModelPath(os.path.join(execution_path , "yolo.h5"))
detector.loadModel()

video_path = detector.detectObjectsFromVideo(camera_input=camera,
                                output_file_path=os.path.join(execution_path, "camera_detected_1")
                                , frames_per_second=29, log_progress=True)
print(video_path)

现在,Yolo 确实可以检测牙刷,它是默认可以检测的 80 个奇怪物体之一。然而,这篇文章有两点使它对我来说不是理想的解决方案:

  1. 此方法首先分析每个视频帧(每帧大约需要 1-2 秒,因此分析来自网络摄像头的 2-3 秒视频流大约需要 1 分钟),并将检测到的视频保存在单独的视频文件中。然而,我想实时检测网络摄像头视频中的牙刷。有解决办法吗?

  2. 使用的 Yolo v3 模型可以检测所有 80 个物体,但我只想检测到 2 或 3 个物体 - 牙刷、拿着牙刷的人以及背景(如果需要的话)。那么,有没有一种方法可以通过仅选择这 2 或 3 个对象进行检测来减少模型权重?


如果您想要一个快速简单的解决方案,您可以使用更轻量级的 yolo 文件之一。您可以从此网站获取权重和配置文件(它们成对出现并且必须一起使用):https://pjreddie.com/darknet/yolo/ https://pjreddie.com/darknet/yolo/(别担心,它看起来是草图,但没关系)

使用较小的网络可以获得更高的 fps,但精度也会较差。如果这是您愿意接受的权衡,那么这是最容易做的事情。

这是一些用于检测牙刷的代码。第一个文件只是一个类文件,有助于使 Yolo 网络的使用更加无缝。第二个是“主”文件,用于打开 VideoCapture 并向网络提供图像。

yolo.py

import cv2
import numpy as np

class Yolo:
    def __init__(self, cfg, weights, names, conf_thresh, nms_thresh, use_cuda = False):
        # save thresholds
        self.ct = conf_thresh;
        self.nmst = nms_thresh;

        # create net
        self.net = cv2.dnn.readNet(weights, cfg);
        print("Finished: " + str(weights));
        self.classes = [];
        file = open(names, 'r');
        for line in file:
            self.classes.append(line.strip());

        # use gpu + CUDA to speed up detections
        if use_cuda:
            self.net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA);
            self.net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA);

        # get output names
        layer_names = self.net.getLayerNames();
        self.output_layers = [layer_names[i[0]-1] for i in self.net.getUnconnectedOutLayers()];

    # runs detection on the image and draws on it
    def detect(self, img, target_id):
        # get detection stuff
        b, c, ids, idxs = self.get_detection_data(img, target_id);

        # draw result
        img = self.draw(img, b, c, ids, idxs);
        return img, len(idxs);

    # returns boxes, confidences, class_ids, and indexes (indices?)
    def get_detection_data(self, img, target_id):
        # get output
        layer_outputs = self.get_inf(img);

        # get dims
        height, width = img.shape[:2];

        # filter thresholds and target
        b, c, ids, idxs = self.thresh(layer_outputs, width, height, target_id);
        return b, c, ids, idxs;

    # runs the network on an image
    def get_inf(self, img):
        # construct a blob
        blob = cv2.dnn.blobFromImage(img, 1 / 255.0, (416,416), swapRB=True, crop=False);

        # get response
        self.net.setInput(blob);
        layer_outputs = self.net.forward(self.output_layers);
        return layer_outputs;

    # filters the layer output by conf, nms and id
    def thresh(self, layer_outputs, width, height, target_id):
        # some lists
        boxes = [];
        confidences = [];
        class_ids = [];

        # each layer outputs
        for output in layer_outputs:
            for detection in output:
                # get id and confidence
                scores = detection[5:];
                class_id = np.argmax(scores);
                confidence = scores[class_id];

                # filter out low confidence
                if confidence > self.ct and class_id == target_id:
                    # scale bounding box back to the image size
                    box = detection[0:4] * np.array([width, height, width, height]);
                    (cx, cy, w, h) = box.astype('int');

                    # grab the top-left corner of the box
                    tx = int(cx - (w / 2));
                    ty = int(cy - (h / 2));

                    # update lists
                    boxes.append([tx,ty,int(w),int(h)]);
                    confidences.append(float(confidence));
                    class_ids.append(class_id);

        # apply NMS
        idxs = cv2.dnn.NMSBoxes(boxes, confidences, self.ct, self.nmst);
        return boxes, confidences, class_ids, idxs;

    # draw detections on image
    def draw(self, img, boxes, confidences, class_ids, idxs):
        # check for zero
        if len(idxs) > 0:
            # loop over indices
            for i in idxs.flatten():
                # extract the bounding box coords
                (x,y) = (boxes[i][0], boxes[i][1]);
                (w,h) = (boxes[i][2], boxes[i][3]);

                # draw a box
                cv2.rectangle(img, (x,y), (x+w,y+h), (0,0,255), 2);

                # draw text
                text = "{}: {:.4}".format(self.classes[class_ids[i]], confidences[i]);
                cv2.putText(img, text, (x, y-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,255), 2);
        return img;

main.py

import cv2
import numpy as np

# this is the "yolo.py" file, I assume it's in the same folder as this program
from yolo import Yolo

# these are the filepaths of the yolo files
weights = "yolov3-tiny.weights";
config = "yolov3-tiny.cfg";
labels = "yolov3.txt";

# init yolo network
target_class_id = 79; # toothbrush
conf_thresh = 0.4; # less == more boxes (but more false positives)
nms_thresh = 0.4; # less == more boxes (but more overlap)
net = Yolo(config, weights, labels, conf_thresh, nms_thresh);

# open video capture
cap = cv2.VideoCapture(0);

# loop
done = False;
while not done:
    # get frame
    ret, frame = cap.read();
    if not ret:
        done = cv2.waitKey(1) == ord('q');
        continue;

    # do detection
    frame, _ = net.detect(frame, target_class_id);

    # show
    cv2.imshow("Marked", frame);
    done = cv2.waitKey(1) == ord('q');

如果您不想使用重量较轻的文件,有几个选项可供您选择。

如果您有 Nvidia GPU,则可以使用 CUDA彻底地提高你的帧率。即使是普通的 nvidia GPU 也比仅在 CPU 上运行快几倍。

绕过持续运行检测的成本的常见策略是仅使用它来最初捕获目标。您可以使用神经网络的检测来初始化对象跟踪器,类似于人在对象周围绘制边界框。对象跟踪器速度更快,并且无需不断地对每一帧进行全面检测。

如果您在单独的线程中运行 Yolo 和对象跟踪,那么您可以像相机一样快地运行。您需要存储帧的历史记录,以便当 Yolo 线程完成一帧时,您可以检查旧帧以查看您是否已经在跟踪对象,这样您就可以在相应的帧上快速启动对象跟踪器-转发它让它赶上。这个程序并不简单,您需要确保正确管理线程之间的数据。不过,对于熟悉多线程来说,这是一个很好的练习,这是编程中的一大进步。

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

如何实时检测对象并自动跟踪它,而不是用户必须在要跟踪的对象周围绘制边界框? 的相关文章

  • 连接mysql和python.3

    我是 django 的新手 使用 django 1 5 和 python 3 3 有没有办法在 python 3 3 上安装 mysqlDB 或 有其他方法可以连接它们吗 PyMySQL https github com petehunt
  • 将上下文管理器的动态可迭代链接到单个 with 语句

    我有一堆想要链接的上下文管理器 第一眼看上去 contextlib nested看起来是一个合适的解决方案 但是 此方法在文档中被标记为已弃用 该文档还指出最新的with声明直接允许这样做 自 2 7 版起已弃用 with 语句现在支持此
  • 使用 matplotlib 绘制简单的 3d numpy 数组

    我想绘制三维 ODE 系统的数值方法的结果 我的输出采用以下形式 假设我们已经计算了三个步骤 import numpy as np v np array 1 2 3 4 5 6 7 8 9 其中每个三元组中的第一个值是 x 坐标 第二个是
  • Pytorch RuntimeError:“host_softmax”未针对“torch.cuda.LongTensor”实现

    我正在使用 pytorch 来训练模型 但是在计算交叉熵损失时我遇到了运行时错误 Traceback most recent call last File deparser py line 402 in
  • 测试从常规函数调用 python 协程(async def)

    假设我有一些异步协程 它可以获取一些数据并返回它 像这样 async def fetch data args result await some io return result 基本上 这个协程是从协程链中调用的 初始协程是通过创建任务来
  • 使用 matplotlib 在 python3 中对多个形状进行动画处理

    尝试在 python3 中使用 matplotlib 动画函数同时对多个对象进行动画处理 下面写的代码是我到目前为止的位置 我能够创建多个对象并将它们显示在图中 我通过使用包含矩形补丁函数的 for 循环来完成此操作 从这里开始 我希望通过
  • 加入语音频道(discord.py)

    当我尝试让我的机器人加入我的语音频道时 出现以下错误 await client join voice channel voice channel 产生错误的行 Traceback most recent call last File usr
  • Django 多个外键,相同的相关名称

    我想创建一个模型 1 其中具有相同其他模型 2 的多个外键 我希望这些外键具有相同的related name因为每个外键将指向 model 2 的不同实例 因为我需要所有外键的一个反向关系 也许一个例子会更明确 class Parent M
  • opencv_contrib编译错误:类没有成员

    我必须实现 SURF 算法来进行图像拼接 我在使用列出的库时遇到了问题here https stackoverflow com questions 33560251 opencv 3 0 0 ubuntu 14 04 nonfree non
  • 基于坐标合并数据框

    我有两个数据框 两个数据框都包含经度和纬度列 我想根据经度和纬度列合并这两个数据框 首先 我应用了普通merge函数 它产生空的结果数据框 我调查发现两个数据框没有相同的经度和纬度列 然后我尝试了另一个函数merge asof并将方向设置为
  • 使用卡尔曼滤波器跟踪位置和速度

    我正在使用卡尔曼滤波器 恒定速度模型 来跟踪物体的位置和速度 我测量对象的 x y 并跟踪 x y vx vy 这是有效的 但是如果在传感器读数 x y vx vy 上添加 20 mm 的高斯噪声 即使该点没有移动 只是噪声也会发生波动 对
  • 如何编写嵌套的 __init__.py 文件

    我正在努力解决嵌套问题 init py在我正在编写的Python包中 该包具有以下架构 module init py submodule1 init py source py submodule2 init py source py sub
  • 如何使用 Python 3 绕过 HTTP Error 403: Forbidden with urllib.request

    您好 不是每次都这样 但有时在尝试访问 LSE 代码时 我会收到每一个烦人的 HTTP 错误 403 禁止消息 任何人都知道我如何仅使用标准 python 模块来克服这个问题 遗憾的是没有漂亮的汤 import urllib request
  • 如何在 Tensorflow 对象检测 API 中查找边界框坐标

    我正在使用 Tensorflow 对象检测 API 代码 我训练了我的模型并获得了很高的检测百分比 我一直在尝试获取边界框坐标 但它不断打印出 100 个奇怪数组的列表 经过在线广泛搜索后 我发现数组中的数字意味着什么 边界框坐标相对于底层
  • 尝试在 Anaconda 上安装 pygame 时,Python 3.x 降级为 Python 2.7

    我正在使用 Anaconda Python 3 我正在尝试安装 pyOpenGL Vpython 和 pygame 安装 pyOpenGL 和 Vpython 就可以使用conda install 当我尝试安装 Pygame 时 使用con
  • 让网络摄像头在 OpenCV 中工作

    我正在尝试让我的网络摄像头在 Windows 7 64 位中的 OpenCV 版本 2 2 中捕获视频 但是 我遇到了一些困难 OpenCV 附带的示例二进制文件都无法检测到我的网络摄像头 最近我发现这篇文章表明答案在于重新编译一个文件 o
  • 为什么python+sqlite3特别慢?

    我尝试使用 Python 2 7 4 sqlite3 和 Firefox SQLite Manager 0 8 0 处理对同一数据库的相同请求 在小型数据库 8000 条记录 上 Python 和 Firefox 都运行得很快并且给出了相同
  • 使用 OpenCV 进行相机校准 - 如何调整棋盘方块大小?

    我正在使用 OpenCV Python 示例开发相机校准程序 来自 OpenCV 教程 http opencv python tutroals readthedocs io en latest py tutorials py calib3d
  • 让 TensorFlow 在 ARM Mac 上使用 GPU

    我已经安装了TensorFlow在 M1 上 ARM Mac 根据这些说明 https github com apple tensorflow macos issues 153 一切正常 然而 模型训练正在进行CPU 如何将培训切换到GPU
  • 选择合适的IDE

    您会推荐使用以下哪种 IDE 语言来在 Windows 下开发涉及识别手势并与操作系统交互的项目 我将使用 OpenCV 库来执行图像处理任务 之后 我将使用 win32 API 或 NET 框架与操作系统交互 具体取决于您建议的工具 性能

随机推荐

  • django.core.exceptions.ImproperlyConfigured:设置 SECRET_KEY 环境变量

    这个项目工作正常 直到我使用 environ 将 SECRET KEY 和 DEBUG 作为环境变量 当我收到此错误后 输出是 env E ecommercedj gt python manage py runserver Tracebac
  • 如何在(简单)有向图中强制形成直边?

    我有以下简单的有向图 digraph clientproxyserver Client gt Proxy label Request from Client Proxy gt Server label Forwarded Request S
  • 悬停时切换 CSS 颜色

    我正在尝试向这样的类添加突出显示颜色 common box hover function common box addClass hover me 这可行 但为什么不行 common box hover function common bo
  • 管道在kedro中找不到节点

    我正在关注管道教程 https kedro readthedocs io en latest 03 tutorial 04 create pipelines html 创建所有需要的文件 启动 kedrokedro run node pre
  • 捕获并打印完整的 Python 异常回溯,无需停止/退出程序

    我想捕获并记录异常而不退出 例如 try do stuff except Exception as err print Exception err I want to print the entire traceback here not
  • 生成一定范围内的“n”个唯一随机数[重复]

    这个问题在这里已经有答案了 我知道如何在 Python 中生成一定范围内的随机数 random randint numLow numHigh 我知道我可以将其放入循环中以生成 n 个数字 for x in range 0 n listOfN
  • Python-删除uuencoding行

    我正在处理许多文本文件 其中 其中一些 包含 uuencoding 可以是 jpg 或 pdf 或 zip of xlsx 等 我不关心嵌入的 UUencoded 数据 所以我只想丢弃这些段落并保留其余文本 我正在努力思考如何想出一种只跳过
  • 在 pandas 中,如何查询列表?

    假设我有一个将列表作为其值的 DataFrame df pd DataFrame languages en fr author Dickens Charles Austen Jane 我可以轻松查询它的字符串 df df author Di
  • 如何在 Meteor 的服务器端调试并记录自己的代码?

    没关系 这不起作用的原因 我忘记了meteor reset so debugger没有机会停下来 呃 更多信息 我正在使用Mason Chang对相关问题的回答中的方法 而不是kill s USR1 proc id 我可以看到脚本 但无法在
  • 响应式高度/宽度视频标题

    我正在为一个网站制作一个响应式 html5 视频标题 我希望它能够垂直和水平响应 仅使用 CSS 来实现响应能力 http jsfiddle net b9cpmuy9是我用于响应宽度的 借用了这里另一篇文章的视频 width 100 hei
  • C++ 视图类型:按常量传递还是按值传递?

    最近在代码审查讨论中出现了这个问题 但没有得出令人满意的结论 所讨论的类型类似于 C string view TS 它们是围绕指针和长度的简单非拥有包装器 并用一些自定义函数装饰 include
  • Spring引导测试“没有可用的合格bean类型”

    我是 Spring boot 的新手 但这是我现在面临的问题 Application java public class Application public static void main String args SpringAppli
  • 我的编译器在做什么? (优化memcpy)

    我正在 VC 2010 中使用以下设置编译一些代码 O2 Ob2 Oi Ot 但是 我在理解生成的程序集的某些部分时遇到了一些困难 我在代码中添加了一些问题作为注释 另外 现代 cpu 上通常建议的预取距离是多少 我可以在我自己的 cpu
  • pandas concat 中的级别选项

    df1 DataFrame np arange 6 reshape 3 2 index a b c columns one two df2 DataFrame 5 np arange 4 reshape 2 2 index a c colu
  • 如何使用 jQuery 创建多个 HTML 元素?

    我想做的是使用 jQuery 创建一个表分页器控件 它包含大量链接和跨度 我已经设法通过简单的字符串连接来做到这一点 但我不敢相信 jQuery 不能让这变得更优雅 我不能在这里使用 jTemplates 因为该生成具有相当多的程序逻辑 问
  • 如何将 Npp8u * 转换为 CUdeviceptr

    我是cuda驱动程序Api接口的新手 但我认为CUdeviceptr看起来像一个句柄参数 所以我对CUdeviceptr和npp8u 之间的转换感到困惑 Npp8u src unsigned char temp temp src CUdev
  • 如何获取括号内的括号

    我试图将括号保留在由括号包围的字符串内 有问题的字符串是 test blue hmmm derp 所需的数组输出是 test and blue hmmm derp 当前输出为 blue hmm and derp 我当前的代码是this ht
  • jquery 基于单选按钮启用/禁用文本框

    在我的页面 jsp 中 我有一个单选按钮组和一个文本框 最初被禁用 每当用户单击单选按钮时 应启用文本框 当用户单击其他单选按钮时 文本框应再次被禁用 我可以使用下面的代码启用最初禁用的复选框 DevGroup OTHER click fu
  • 如何在现有项目上使用 Backpack for Laravel?

    我正在用 Laravel 构建一个小应用程序 我刚刚发现 Backpack 看起来非常漂亮 我下载了它 我有许可证 但我真的不知道如何将它与我现有的文件一起使用 到目前为止有 3 个控制器 3 个模型和一些刀片文件 也许答案就在文档中的某个
  • 如何实时检测对象并自动跟踪它,而不是用户必须在要跟踪的对象周围绘制边界框?

    我有以下代码 用户可以按p要暂停视频 请在要跟踪的对象周围绘制一个边界框 然后按 Enter 回车 以跟踪视频源中的该对象 import cv2 import sys major ver minor ver subminor ver cv2