数据集采用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()
在开发板拉流的时候遇到了该问题:
[rtsp @ 0xaaab104fd0f0] method DESCRIBE failed: 401 Unauthorized
问题原因:
'rtsp://admin:@192.168.1.112:xxx &xxx'
摄像头的网址admin是用户名,还应输入密码,格式应该是这样的:
'rstp://用户名:密码@ip地址:端口号 &xxx'
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()
①源码
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/
②修改开源仓
cd deep_sort_pytorch
patch -p1 < ../yolov3.patch
cd ..
③安装依赖
pip install -r requirements.txt
④数据集格式
deep_sort_pytorch
└── MOT16
├---train
└──MOT16-02
└──MOT16-04
└──MOT16-05
└──MOT16-09
└──MOT16-10
└──MOT16-11
└──MOT16-13
└──demo.avi
⑤模型转换
使用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
2)导出onnx文件,使用onnxsim进行常量折叠,消除动态shape,在./deep_sort_pytorch/目录下运行
python3 yolov3_deepsort.py demo.avi --cpu
pip install onnx-simplifier
python -m onnxsim yolov3.onnx yolov3-sim.onnx
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 ../../
4)使用ATC工具将ONNX模型转OM模型。
配置环境变量
source /usr/local/Ascend/ascend-toolkit/set_env.sh
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}
注:atc命令很容易受网络环境影响,经常不成功,多尝试几次。
⑥推理验证
在Deepsort_for_Pytorch目录下,执行以下命令,删除转onnx的代码并修改evaluation文件。
cd ..
patch -p0 < evaluation.patch
cd deep_sort_pytorch
将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
一般步骤如下:
①创建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()
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()