YOLOv5+单目跟踪(python)

news2024/12/26 23:36:23

YOLOv5+单目跟踪(python)

  • 1. 目标跟踪
  • 2. 测距模块
    • 2.1 设置测距模块
    • 2.2 添加测距
  • 3. 主代码
  • 4. 实验效果

相关链接
1. YOLOv5+单目测距(python)
2. YOLOv7+单目测距(python)
3. YOLOv7+单目跟踪(python)
4. 具体效果已在Bilibili发布,点击跳转

工程代码在文章末尾

1. 目标跟踪

用yolov5实现跟踪步骤比较简单,去官网下载deepsort源码,这里有个版本对应关系
DeepSort v3.0 ~YOLOv5 v5.0-------------------DeepSort v4.0 ~ YOLOv5 v6.1
在这里插入图片描述

下载完DeepSort之后去YOLO官网下载相应的YOLO版本,然后把下载的YOLO拖进DeepSort文件夹里,并把YOLO文件夹改名为yolov5,接下来把环境装好,然后运行代码 track.py ,此时如果不出问题就完成了普通检测
也可以用终端运行命令python track.py --source 1.mp4 --show-vid --save-vid --yolo_weights yolov5/weights/yolov5s.pt
请添加图片描述

2. 测距模块

2.1 设置测距模块

测距部分之前已经写过了,具体见这篇文章,我们在Deepsort文件夹里创建一个名为distance.py的文件,或者直接把测距那篇文章里的distance.py文件拖进来也可以
distance.py

foc = 1990.0        # 镜头焦距
real_hight_person = 66.9   # 行人高度
real_hight_car = 57.08      # 轿车高度

# 自定义函数,单目测距
def person_distance(h):
    dis_inch = (real_hight_person * foc) / (h - 2)
    dis_cm = dis_inch * 2.54
    dis_cm = int(dis_cm)
    dis_m = dis_cm/100
    return dis_m

def car_distance(h):
    dis_inch = (real_hight_car * foc) / (h - 2)
    dis_cm = dis_inch * 2.54
    dis_cm = int(dis_cm)
    dis_m = dis_cm/100
    return dis_m

2.2 添加测距

接下来调用测距代码到主代码 track.py 文件中,先在代码开头导入库,添加

from distance import person_distance,car_distance

与测距那篇文章不同,由于跟踪代码自带画框,我们只需要将测距模块写进画框这里,具体如下(注释部分是我添加修改的)

def draw_boxes(img, bbox, identities=None, offset=(0, 0)):
    for i, box in enumerate(bbox):
        x1, y1, x2, y2 = [int(i) for i in box]
        h = y2 - y1   # 计算边框像素点高度
        dis_m = person_distance(h)  # 调用函数,计算行人实际距离
        x1 += offset[0]
        x2 += offset[0]
        y1 += offset[1]
        y2 += offset[1]
        # box text and bar
        id = int(identities[i]) if identities is not None else 0
        color = compute_color_for_labels(id)
        label = '{}{:d}'.format("", id)
        label = label + "  "+"dis:"+str(dis_m)+"m"    # 将距离添加进标签
        t_size = cv2.getTextSize(label, cv2.FONT_HERSHEY_PLAIN, 0, 1)[0]  
        cv2.rectangle(img, (x1, y1), (x2, y2), color, 1)  
        cv2.rectangle(img, (x1, y1), (x1 + t_size[0] + 3, y1 + t_size[1] + 4), color, -1)
        cv2.putText(img, label, (x1, y1 +
                t_size[1] + 1), cv2.FONT_HERSHEY_PLAIN, 1, [255, 255, 255], 2) 
    return img

3. 主代码

import sys
import threading
import random

from yolov5.utils.plots import plot_one_box

sys.path.insert(0, './yolov5')

from yolov5.utils.google_utils import attempt_download
from yolov5.models.experimental import attempt_load
from yolov5.utils.datasets import LoadImages, LoadStreams
from yolov5.utils.general import check_img_size, non_max_suppression, scale_coords, \
    check_imshow,xyxy2xywh
from yolov5.utils.torch_utils import select_device, time_synchronized
from deep_sort_pytorch.utils.parser import get_config
from deep_sort_pytorch.deep_sort import DeepSort
import argparse
import os
import platform
import shutil
import time
from pathlib import Path
import cv2
import torch
import torch.backends.cudnn as cudnn

from yolov5.utils.plots import plot_one_box
palette = (2 ** 11 - 1, 2 ** 15 - 1, 2 ** 20 - 1)
from distance import person_distance,car_distance

def xyxy_to_xywh(*xyxy):
    """" Calculates the relative bounding box from absolute pixel values. """
    bbox_left = min([xyxy[0].item(), xyxy[2].item()])
    bbox_top = min([xyxy[1].item(), xyxy[3].item()])
    bbox_w = abs(xyxy[0].item() - xyxy[2].item())
    bbox_h = abs(xyxy[1].item() - xyxy[3].item())
    x_c = (bbox_left + bbox_w / 2)
    y_c = (bbox_top + bbox_h / 2)
    w = bbox_w
    h = bbox_h
    return x_c, y_c, w, h

def xyxy_to_tlwh(bbox_xyxy):
    tlwh_bboxs = []
    for i, box in enumerate(bbox_xyxy):
        x1, y1, x2, y2 = [int(i) for i in box]
        top = x1
        left = y1
        w = int(x2 - x1)
        h = int(y2 - y1)
        tlwh_obj = [top, left, w, h]
        tlwh_bboxs.append(tlwh_obj)
    return tlwh_bboxs


def compute_color_for_labels(label):
    """
    Simple function that adds fixed color depending on the class
    """
    color = [int((p * (label ** 2 - label + 1)) % 255) for p in palette]
    return tuple(color)

def draw_boxes(img, bbox, identities=None, offset=(0, 0)):
    for i, box in enumerate(bbox):
        x1, y1, x2, y2 = [int(i) for i in box]
        h = y2 - y1
        dis_m = person_distance(h)  # 调用函数,计算行人实际高度
        x1 += offset[0]
        x2 += offset[0]
        y1 += offset[1]
        y2 += offset[1]
        # box text and bar
        id = int(identities[i]) if identities is not None else 0
        color = compute_color_for_labels(id)
        label = '{}{:d}'.format("", id)
        label = label + "  "+"dis:"+str(dis_m)+"m"
        t_size = cv2.getTextSize(label, cv2.FONT_HERSHEY_PLAIN, 0, 1)[0]  #修改字符,原设置: 2,2
        cv2.rectangle(img, (x1, y1), (x2, y2), color, 1)  # 修改线框为1, 原设置:3
        cv2.rectangle(img, (x1, y1), (x1 + t_size[0] + 3, y1 + t_size[1] + 4), color, -1)
        cv2.putText(img, label, (x1, y1 +
                t_size[1] + 1), cv2.FONT_HERSHEY_PLAIN, 1, [255, 255, 255], 2) #修改 2,.,2
    return img


def detect(opt):
    out, source, yolo_weights, deep_sort_weights, show_vid, save_vid, save_txt, imgsz, evaluate = \
        opt.output, opt.source, opt.yolo_weights, opt.deep_sort_weights, opt.show_vid, opt.save_vid, \
            opt.save_txt, opt.img_size, opt.evaluate
    webcam = source == '0' or source.startswith(
        'rtsp') or source.startswith('http') or source.endswith('.txt')


    # initialize deepsort
    cfg = get_config()
    cfg.merge_from_file(opt.config_deepsort)
    attempt_download(deep_sort_weights, repo='mikel-brostrom/Yolov5_DeepSort_Pytorch')
    deepsort = DeepSort(cfg.DEEPSORT.REID_CKPT,
                        max_dist=cfg.DEEPSORT.MAX_DIST, min_confidence=cfg.DEEPSORT.MIN_CONFIDENCE,
                        nms_max_overlap=cfg.DEEPSORT.NMS_MAX_OVERLAP, max_iou_distance=cfg.DEEPSORT.MAX_IOU_DISTANCE,
                        max_age=cfg.DEEPSORT.MAX_AGE, n_init=cfg.DEEPSORT.N_INIT, nn_budget=cfg.DEEPSORT.NN_BUDGET,
                        use_cuda=True)

    # Initialize
    device = select_device(opt.device)

    # The MOT16 evaluation runs multiple inference streams in parallel, each one writing to
    # its own .txt file. Hence, in that case, the output folder is not restored
    if not evaluate:
        if os.path.exists(out):
            pass
            shutil.rmtree(out)  # delete output folder
        os.makedirs(out)  # make new output folder
    half = device.type != 'cpu'  # half precision only supported on CUDA

    # Load model
    model = attempt_load(yolo_weights, map_location=device)  # load FP32 model
    stride = int(model.stride.max())  # model stride
    imgsz = check_img_size(imgsz, s=stride)  # check img_size
    names = model.module.names if hasattr(model, 'module') else model.names  # get class names
    if half:
        model.half()  # to FP16

    # Set Dataloader
    vid_path, vid_writer = None, None
    # Check if environment supports image displays
    if show_vid:
        show_vid = check_imshow()

    if webcam:
        cudnn.benchmark = True  # set True to speed up constant image size inference
        dataset = LoadStreams(source, img_size=imgsz, stride=stride)
    else:
        dataset = LoadImages(source, img_size=imgsz)

    # Get names and colors
    names = model.module.names if hasattr(model, 'module') else model.names
    colors = [[random.randint(0, 255) for _ in range(3)] for _ in names]

    # Run inference
    if device.type != 'cpu':
        model(torch.zeros(1, 3, imgsz, imgsz).to(device).type_as(next(model.parameters())))  # run once
    t0 = time.time()

    save_path = str(Path(out))
    # extract what is in between the last '/' and last '.'
    txt_file_name = source.split('/')[-1].split('.')[0]
    txt_path = str(Path(out)) + '/' + txt_file_name + '.txt'

    for frame_idx, (path, img, im0s, vid_cap) in enumerate(dataset):
        img = torch.from_numpy(img).to(device)
        img = img.half() if half else img.float()  # uint8 to fp16/32
        img /= 255.0  # 0 - 255 to 0.0 - 1.0
        if img.ndimension() == 3:
            img = img.unsqueeze(0)

        # Inference
        t1 = time_synchronized()
        pred = model(img, augment=opt.augment)[0]

        # Apply NMS
        pred = non_max_suppression(
            pred, opt.conf_thres, opt.iou_thres, classes=opt.classes, agnostic=opt.agnostic_nms)
        t2 = time_synchronized()

        # Process detections
        for i, det in enumerate(pred):  # detections per image
            if webcam:  # batch_size >= 1
                p, s, im0 = path[i], '%g: ' % i, im0s[i].copy()
            else:
                p, s, im0 = path, '', im0s

            s += '%gx%g ' % img.shape[2:]  # print string
            save_path = str(Path(out) / Path(p).name)

            if det is not None and len(det):
                # Rescale boxes from img_size to im0 size
                det[:, :4] = scale_coords(
                    img.shape[2:], det[:, :4], im0.shape).round()

                # Print results
                for c in det[:, -1].unique():
                    n = (det[:, -1] == c).sum()  # detections per class
                    s += '%g %ss, ' % (n, names[int(c)])  # add to string

                xywh_bboxs = []
                confs = []

                # Adapt detections to deep sort input format
                for *xyxy, conf, cls in det:
                    # to deep sort format
                    x_c, y_c, bbox_w, bbox_h = xyxy_to_xywh(*xyxy)
                    xywh_obj = [x_c, y_c, bbox_w, bbox_h]
                    xywh_bboxs.append(xywh_obj)
                    confs.append([conf.item()])



                xywhs = torch.Tensor(xywh_bboxs)
                confss = torch.Tensor(confs)

                # pass detections to deepsort
                outputs = deepsort.update(xywhs, confss, im0)

                # draw boxes for visualization
                if len(outputs) > 0:
                    bbox_xyxy = outputs[:, :4]
                    identities = outputs[:, -1]
                    draw_boxes(im0, bbox_xyxy, identities)
                    # to MOT format
                    tlwh_bboxs = xyxy_to_tlwh(bbox_xyxy)

                    # Write MOT compliant results to file
                    if save_txt:
                        for j, (tlwh_bbox, output) in enumerate(zip(tlwh_bboxs, outputs)):
                            bbox_top = tlwh_bbox[0]
                            bbox_left = tlwh_bbox[1]
                            bbox_w = tlwh_bbox[2]
                            bbox_h = tlwh_bbox[3]
                            identity = output[-1]
                            with open(txt_path, 'a') as f:
                                f.write(('%g ' * 10 + '\n') % (frame_idx, identity, bbox_top,
                                                            bbox_left, bbox_w, bbox_h, -1, -1, -1, -1))  # label format

            else:
                deepsort.increment_ages()

            # Print time (inference + NMS)
            print('%sDone. (%.3fs)' % (s, t2 - t1))

            # Stream results
            if show_vid:
                cv2.namedWindow("Webcam", cv2.WINDOW_NORMAL)
                cv2.resizeWindow("Webcam", 1280, 720)
                cv2.moveWindow("Webcam", 0, 100)
                cv2.imshow("Webcam", im0)
                #cv2.imshow(p, im0)
                if cv2.waitKey(1) == ord('q'):  # q to quit
                    raise StopIteration

            # Save results (image with detections)
            if save_vid:
                if vid_path != save_path:  # new video
                    vid_path = save_path
                    if isinstance(vid_writer, cv2.VideoWriter):
                        vid_writer.release()  # release previous video writer
                    if vid_cap:  # video
                        fps = vid_cap.get(cv2.CAP_PROP_FPS)
                        w = int(vid_cap.get(cv2.CAP_PROP_FRAME_WIDTH))
                        h = int(vid_cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
                    else:  # stream
                        fps, w, h = 30, im0.shape[1], im0.shape[0]
                        save_path += '.mp4'

                    vid_writer = cv2.VideoWriter(save_path, cv2.VideoWriter_fourcc(*'mp4v'), fps, (w, h))
                vid_writer.write(im0)

    if save_txt or save_vid:
        print('Results saved to %s' % os.getcwd() + os.sep + out)
        if platform == 'darwin':  # MacOS
            os.system('open ' + save_path)
    print('Done. (%.3fs)' % (time.time() - t0))


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--yolo_weights', type=str, default='yolov5/weights/yolov5s.pt', help='model.pt path')
    parser.add_argument('--deep_sort_weights', type=str, default='deep_sort_pytorch/deep_sort/deep/checkpoint/ckpt.t7', help='ckpt.t7 path')
    # file/folder, 0 for webcam
    #parser.add_argument('--source', type=str, default='0', help='source')
    parser.add_argument('--source', type=str, default='1.mp4', help='source')
    parser.add_argument('--output', type=str, default='output', help='output folder')  # output folder
    parser.add_argument('--img-size', type=int, default=640, help='inference size (pixels)')
    parser.add_argument('--conf-thres', type=float, default=0.4, help='object confidence threshold')
    parser.add_argument('--iou-thres', type=float, default=0.5, help='IOU threshold for NMS')
    parser.add_argument('--fourcc', type=str, default='mp4v', help='output video codec (verify ffmpeg support)')
    parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
    parser.add_argument('--show-vid', action='store_true', help='display tracking video results')
    parser.add_argument('--save-vid', action='store_true', help='save video tracking results')
    parser.add_argument('--save-txt', action='store_true', help='save MOT compliant results to *.txt')
    # class 0 is person, 1 is bycicle, 2 is car... 79 is oven
    #parser.add_argument('--classes', nargs='+', type=int, help='filter by class')
    parser.add_argument('--classes', nargs='+', default=[0], type=int, help='filter by class')
    parser.add_argument('--agnostic-nms', action='store_true', help='class-agnostic NMS')
    parser.add_argument('--augment', action='store_true', help='augmented inference')
    parser.add_argument('--evaluate', action='store_true', help='augmented inference')
    parser.add_argument("--config_deepsort", type=str, default="deep_sort_pytorch/configs/deep_sort.yaml")
    args = parser.parse_args()
    args.img_size = check_img_size(args.img_size)

    with torch.no_grad():
        detect(args)

4. 实验效果

同理,运行 track.py 或者用终端运行命令python track.py --source 1.mp4 --show-vid --save-vid --yolo_weights yolov5/weights/yolov5s.pt

代码打包下载
链接1:https://download.csdn.net/download/qq_45077760/87715776
链接2:https://github.com/up-up-up-up/yolov5_Monocular_ranging

博客主页有更多有关测距的内容

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JDBC详解(一):JDBC概述

JDBC概述 前言一、数据的持久化1、概念2、应用 二、Java中的数据存储技术三、JDBC介绍四、JDBC体系结构五、JDBC程序编写步骤 前言 本博主将用CSDN记录软件开发求学之路上亲身所得与所学的心得与知识,有兴趣的小伙伴可以关注博主!也许一个人独行&#…

全志 Orange Pi相关网站集

Orange Pi 系统安装的常识 看到有教程说android系统需要用win32diskimager才能成功烧写运行镜像名称与版本的对应关系 ubuntu版本号代号16.04Xenial Xerus(好客的非洲地鼠)18.04Bionio Beaver (仿生海狸}20.04Focal Fossa (类似…

DFIG控制10-b: 双馈发电机的转矩方程推导

DFIG控制10-b 双馈发电机的转矩方程推导 接上DFIG控制10: 双馈发电机的动态模型_Fantasy237的博客,DFIG的转矩方程和推导。 (字数限制,只能放在新的一篇博文里了。。) 转矩方程 定子αβ静止坐标系 从三相坐标系下…

Linux网络套接字(二)

学习任务: 继网络套接字(一),继续学习套接字socket编程接口(已经学习了socket和bind),实现TCP客户端/服务器(单连接版本, 多进程版本, 多线程版本,进程或线程池版本),并且…

JavaScript(JS)-1.JS基础知识

1.JavaScript概念 (1)JavaScript是一门跨平台,面向对象的脚本语言,来控制网页行为的,它能使网页可交互 (2)W3C标准:网页主要由三部分组成 ①结构:HTML负责网页的基本结构(页面元素和内容)。 …

SPI协议——同步全双工串行通信方式

文章目录 前言一、简要介绍1、优点2、缺点 二、信号线和连接方式1、四根信号线2、连接方式2.1 多NSS形式2.2 菊花链形式 三、SPI配置1、时钟极性CPOL2、时钟相位CPHA3、四种模式4、数据大小5、其他配置参数 四、通信过程 前言 2023.4.22 阴 一、简要介绍 SPI:Seri…

什么是分组卷积、深度可分离卷积?附上深度可分离卷积代码

文章目录 分组卷积 Group Converlution1、由来和用途2、常规卷积和分组卷积的区别2.1、常规卷积:常规卷积的运算量: 2.2、分组卷积: 3、分组卷积的作用4、深度可分离卷积总结:先做分组卷积,再做1 x 1卷积深度可分离卷积代码 参考博…

【U-Net】训练自己的数据集

代码用的是b导的 整个训练流程也是根据b导的视频来的 源码地址:https://github.com/bubbliiiing/unet-pytorch 博客地址:https://blog.csdn.net/weixin_44791964/article/details/108866828 # 一、准备数据集 1、使用labelme软件标注数据,得…

深度学习 -- 什么是张量 pytorch中张量的几种创建方法

前言 在学习深度学习的过程中,遇到的第一个概念就是张量,张量在pytorch中的计算十分重要,所以本篇博客记录本人学习张量的过程,以及自己的理解。 张量是什么? 张量是一个多维数组,它是标量、向量、矩阵的…

SpringBoot的创建及配置文件

文章目录:一.Spring项目的创建(1)SpringBoot的含义 (2)SpringBoot的优点 (3)项目目录的运行和介绍 二.SpringBoot的配置文件 (1)配置文件的作用 (2&#xff0…

E5--Aurora 8/10Bip核实现光纤接口通信2023-04-22

1.场景 使用两块开发板A和B,通过光纤接口将在A板上ROM中存储的图片数据转发到B板并显示在B板连接的显示屏上,实现光纤接口通信。 具体场景是,由于A735T片上资源有限,因此ROM IP存储了一张1024*600(LVDS屏幕&#xff0…

集成光子学在计算领域的机会与挑战【光子学公开课 第133期】

没有听懂,自己浅浅记录一下 背景 深度学习与大模型带来的算力需求(需要的算力指数型提高) 解决方案 算力池化和算力网络 传统的主机服务,可能会存在闲置资源。 ->改变商业模式:不是出售硬件服务,…

【Makefile通用模板】入门必看篇,超详细

工程目录 假如我们有以下目录结构&#xff1a; . ├── inc │ ├── add.h │ └── sub.h ├── main.c └── src├── add.c└── sub.c文件中的内容如下&#xff1a; //main.c #include <stdio.h> #include "add.h" #include "sub.h&q…

nodejs+vue 智慧餐厅点餐餐桌预订系统

现在社会的生活节奏越来越快&#xff0c;人们对互联网的需求也越来越大&#xff0c;不仅要求使用方便&#xff0c;而且对于功能及扩展性也有了更高的要求&#xff0c;最能达到要求莫过于利用计算机网络&#xff0c;将所需功能要求和计算机网络结合起来&#xff0c;就形成了本智…

FOSSASIA Summit 的参会为 openEuler 全球化注入强心剂

2023年4月15日&#xff0c;亚洲顶级开源盛会FOSSASIA Summit 2023在新加坡落幕。openEuler作为白金赞助级别参会。 自2009年成立以来&#xff0c;除因疫情中断3年之外&#xff0c;FOSSASIA Summit已累计举办11年。作为亚洲年度开源技术旗舰活动&#xff0c;FOSSASIA Summit吸引…

C/C++ 常见编译器说明

文章目录 window下常用的编译器如何获取MSVCMinGW Linux和MaxOS下的编译器gcc和g的区别 window下常用的编译器 window下并不提供原生的类似gcc/g的类unix系统下的C/C编译器。常用的是 MSVC&#xff08;Microsoft Visual C/C&#xff09;编译器&#xff0c;在我们安装完visual …

python 获取脚本所在存储目录

获取.py文件所在目录 问题背景问题原因解决方法 问题背景 项目需要使用到当前脚本所在的目录然后保存文件 我像之前一样&#xff0c;使用了os.getcwd() 去获取脚本目录&#xff0c;保存文件&#xff0c;程序正常运行&#xff0c;但设定路径下没有任何文件&#xff0c;没有头脑…

读 AI学者生存策略

链接&#xff1a;https://arxiv.org/pdf/2304.06035.pdf 作者&#xff1a;Julian Togelius and Georgios N. Yannakakis 随着大模型 和 大数据的出现&#xff0c; AI研究者 都会感到焦虑。 没有计算资源 &#xff0c;没有标注的人力&#xff0c;很难做出突破性的研究。即使很多…

FFmpeg 中 RTSP推流桌面和Android设备延时测试

文章目录 1. FFMPEG 推流&#xff1a;1.1 FFmpeg 源码准备1.2 RTSP 推流服务器 2. 执行流程2.1 启动服务器2.2 执行桌面推流2.3 播放 3. 安卓测试 1. FFMPEG 推流&#xff1a; 1.1 FFmpeg 源码准备 官网&#xff0c;GitHub&#xff0c;CSDN中选一个就好&#xff1a; ● 官网…

在线图片编辑网站汇总

目录 前言一、在线抠图工具1. 佐糖2. remove.bg3. Clipping Magic4. 起兮深深5. BgSub6. 改图神器7. PIXLR 二、其他工具1. 压缩图2. AI人工智能图片放大 前言 本文收录了多个可以在线抠图、在线编辑图片的网站。 一、在线抠图工具 1. 佐糖 官网&#xff1a;链接 特点&#x…