• Atlas 200I DK目标检测与追踪技术记录


    数据集

    数据集采用MOT系列,MOT是多目标追踪常用数据集,MOT数据集对数据集进行了分帧,如要获得视频,需要先利用opencv里的cv2.VideoWriter模块便利图片文件夹,具体代码如下:

    import os
    import cv2
     
    img_path = './img1' #图片存放路径
    
    
    # 读取第一张图片的宽度、高度和通道数(用于设置视频尺寸)
    first_image = cv2.imread(os.path.join(img_path, os.listdir(img_path)[0]))
    height, width, channels = first_image.shape
    
    # 视频保存路径和文件名
    output_path = './output.mp4'
    
    # 视频帧率
    fps = 30
    
    # 设置视频编解码器
    fourcc = cv2.VideoWriter_fourcc(*'mp4v')
    
    # 创建视频写入器
    video_writer = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
    
    # 遍历图片文件夹中的每张图片,并逐帧写入视频
    for filename in sorted(os.listdir(img_path)):
        img_path = './img1' 
        img_path = os.path.join(img_path, filename)
        frame = cv2.imread(img_path)
    
        # 将当前帧写入视频
        video_writer.write(frame)
    
    # 释放视频写入器
    video_writer.release()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    推流与拉流

    在开发板拉流的时候遇到了该问题:
    [rtsp @ 0xaaab104fd0f0] method DESCRIBE failed: 401 Unauthorized

    问题原因:

    'rtsp://admin:@192.168.1.112:xxx &xxx'
    
    • 1

    摄像头的网址admin是用户名,还应输入密码,格式应该是这样的:

    'rstp://用户名:密码@ip地址:端口号 &xxx'
    
    • 1

    摄像头拉流模板

    import cv2
    
    cap = cv2.VideoCapture(0)
    
    # 获取保存视频相关变量
    fps = cap.get(cv2.CAP_PROP_FPS)  # 获取帧数
    fourcc = cv2.VideoWriter_fourcc(*'mp4v')  # 设置视频编码类型
    outfile = 'video_result.mp4'  # 设置结果保存文件
    video_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))  # 获取原视频的高度
    video_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))  # 获取原视频的宽度
    writer = cv2.VideoWriter(outfile, fourcc, fps, (video_width, video_height))  # 获取视频写入writer
    
    try:
        while(cap.isOpened()):  # 在摄像头打开的情况下循环执行
            ret, frame = cap.read()  # 此处 frame 为 bgr 格式图片
    
            # ========================================
            # 这里放入模型前处理、推理、后处理相关代码,根据实际情况修改
            img = preprocess(frame)  # 前处理
            infer_res = infer(img)  # 推理
            img_res = postprocess(infer_res)  # 后处理
            # ========================================
    
            # 将推理结果写入视频
            writer.write(img_res)  
    except KeyboardInterrupt:
        cap.release()  # 释放摄像头资源
        writer.release()  # 释放视频写入资源
    finally:
        cap.release()
        writer.release()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    Deepsort目标追踪

    ①源码

    git clone https://github.com/ZQPei/deep_sort_pytorch.git
    cd deep_sort_pytorch
    git reset 4c2d86229b0b69316af67d519f8476eee69c9b20 --hard
    cd ..
    mv yolov3_deepsort_eval.py deep_sort_pytorch/
    cp acl_net_dynamic.py deep_sort_pytorch/detector/YOLOv3/
    mv acl_net_dynamic.py export_deep_onnx.py deep_sort_pytorch/deep_sort/deep/
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    ②修改开源仓

    cd deep_sort_pytorch
    patch -p1 < ../yolov3.patch
    cd ..
    
    • 1
    • 2
    • 3

    ③安装依赖

    pip install -r requirements.txt
    
    • 1

    ④数据集格式

    deep_sort_pytorch
       └── MOT16
           ├---train
             └──MOT16-02
             └──MOT16-04
             └──MOT16-05
             └──MOT16-09
             └──MOT16-10
             └──MOT16-11
             └──MOT16-13
       └──demo.avi
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    ⑤模型转换
    使用PyTorch将模型权重文件.pth转换为.onnx文件,再使用ATC工具将.onnx文件转为离线推理模型文件.om文件。转换命令如下:
    1)获取权重文件

    wget -P deep_sort_pytorch/detector/YOLOv3/weight/ https://pjreddie.com/media/files/yolov3.weights
    
    wget -P deep_sort_pytorch/deep_sort/deep/checkpoint https://drive.google.com/drive/folders/1xhG0kRH1EX5B9_Iz8gQJb7UNnn_riXi6 
    
    • 1
    • 2
    • 3

    2)导出onnx文件,使用onnxsim进行常量折叠,消除动态shape,在./deep_sort_pytorch/目录下运行

    python3 yolov3_deepsort.py demo.avi --cpu
    
    • 1
    pip install onnx-simplifier
    python -m onnxsim yolov3.onnx yolov3-sim.onnx
    
    • 1
    • 2

    3)将export_deep_onnx.py脚本置于deep_sort_pytorch/deep_sort/deep/路径下,进入该并运行该脚本,导出第二段onnx。

    cd deep_sort/deep/
    python export_deep_onnx.py
    mv deep.onnx ../../
    cd ../../
    
    • 1
    • 2
    • 3
    • 4

    4)使用ATC工具将ONNX模型转OM模型。
    配置环境变量

    source /usr/local/Ascend/ascend-toolkit/set_env.sh
    
    • 1

    npu-smi info查看芯片名称

    5)执行ATC命令

    atc --framework=5 --model=yolov3-sim.onnx --output=yolov3-sim --input_format=NCHW --input_shape="actual_input_1:1,3,416,416" --log=info --soc_version=Ascend${chip_name}
    
    atc --model=deep.onnx --framework=5  --output=deep_dims --input_format=ND  --input_shape="actual_input_1:-1,3,128,64" --dynamic_dims="1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16;17;18;19;20;21;22;23;24;25;26;27;28;29;30;31;32;33;34;35;36;37;38;39;40;41;42;43;44;45;46;47;48;49;50" --log=error --soc_version=Ascend${chip_name}
    
    • 1
    • 2
    • 3

    注:atc命令很容易受网络环境影响,经常不成功,多尝试几次。

    ⑥推理验证
    在Deepsort_for_Pytorch目录下,执行以下命令,删除转onnx的代码并修改evaluation文件。

    cd ..
    patch -p0 < evaluation.patch
    cd deep_sort_pytorch
    
    • 1
    • 2
    • 3

    将acl_net_dynamic.py脚本放置在detector/YOLOv3/以及deep_sort/deep目录下,将yolov3-sim.om和deep_dims.om以及我们提供的yolov3_deepsort_eval.py放在deep_sort_pytorch目录下,调用脚本yolov3_deepsort_eval.py获取精度。

    python3 yolov3_deepsort_eval.py --data_root=./MOT16/train --device=0
    
    • 1

    机器学习目标追踪

    一般步骤如下:
    ①创建MultiTracker对象.
    ②读取视频或摄像头数据.
    ③框选ROI区域
    ④给MultiTracker对象添加实际的追踪算法.
    ⑤对每一帧进行进行目标追踪.

    代码示例:

    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()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    光流方法

    OpenCV中提供了光流估计的接口,包括 稀疏光流估计算法 cv2.calcOpticalFlowPyrLK(),和 稠密光流估计 cv2.calcOpticalFlowFarneback()。其中稀疏光流估计算法为Lucas-Kanade算法。

    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()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    在这里插入图片描述

  • 相关阅读:
    LeetCode第81场双周赛
    计算机网络:差错控制
    C++11
    43期《深入浅出Pytorch》课程 - Task01:PyTorch的安装和基础知识+前置知识打卡
    《垃圾回收算法手册 自动内存管理的艺术》——内存分配(笔记)
    input()函数——输入
    数据库之元数据
    MySQL基础篇【第二篇】| 简单的查询、条件查询、排序查询
    Html5+Css3第一讲:html5+Css3基础(1)
    微信小程序入门
  • 原文地址:https://blog.csdn.net/qq_43820692/article/details/133883533