本期更新全是乾貨
首先説一下我們跑完訓練好的跟蹤器之後,可能想自己製作一個視頻,然後運用到跟蹤當中,這期博主帶大家一步一步的完成這個目標,看很多博客沒有系統的製作,並且過程比較繁瑣,沒有統一的説明。這次給大家帶些福利,節省大家科研工作的時間!歡迎大家積極討論!
注:博主也是花了很多時間,所以,如果説對大家有用,給博主點點關注,謝謝!
視頻採集
攝像頭單獨視頻採集的代碼博主放在這裏,供大家使用(常用的.avi和.mp4格式)
import cv2
cap = cv2.VideoCapture(0)
# Define the codec and create VideoWriter object
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('C:\\Users\\26254\\Desktop\\save_webcam_video.avi', fourcc, 20.0, (640, 480))#注意路徑
while cap.isOpened():
ret, frame = cap.read()
if not ret:
print("Can't receive frame (stream end?). Exiting ...")
break
# write frame
out.write(frame)
cv2.imshow('webcam', frame)
# press key 'q' to quit
if cv2.waitKey(1) == ord('q'):
break
# Release everything if job is finished
cap.release()
out.release()
cv2.destroyAllWindows()
視頻轉化為圖像代碼
然後可以將視頻轉化為圖片的代碼,供大家使用
import cv2
from cv2 import VideoWriter, VideoWriter_fourcc, imread, resize
import os
from PIL import Image
def Video2Pic():#視頻轉換為圖片
videoPath = "C:/Users/HK/Desktop/shipin/cup.avi" # 讀取視頻路徑,還有格式'.mp4'
imgPath = "C:/Users/HK/Desktop/shipin/cup/" # 保存圖片路徑
cap = cv2.VideoCapture(videoPath)
# fps = cap.get(cv2.CAP_PROP_FPS) # 獲取幀率
# width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) # 獲取寬度
# height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) # 獲取高度
suc = cap.isOpened() # 是否成功打開
frame_count = 0
while suc:
frame_count += 1
suc, frame = cap.read()
cv2.imwrite(imgPath + str(frame_count).zfill(4)+'.jpg', frame)#注jpg格式可以換為png格式
cv2.waitKey(1)
cap.release()
print("視頻轉圖片結束!")
def Pic2Video():
imgPath = "youimgPath" # 讀取圖片路徑
videoPath = "youvideoPath" # 保存視頻路徑
images = os.listdir(imgPath)
fps = 25 # 每秒25幀數
# VideoWriter_fourcc為視頻編解碼器 ('I', '4', '2', '0') —>(.avi) 、('P', 'I', 'M', 'I')—>(.avi)、('X', 'V', 'I', 'D')—>(.avi)、('T', 'H', 'E', 'O')—>.ogv、('F', 'L', 'V', '1')—>.flv、('m', 'p', '4', 'v')—>.mp4
fourcc = VideoWriter_fourcc(*"MJPG")
image = Image.open(imgPath + images[0])
videoWriter = cv2.VideoWriter(videoPath, fourcc, fps, image.size)
for im_name in range(len(images)):
frame = cv2.imread(imgPath + images[im_name]) # 這裏的路徑只能是英文路徑
# frame = cv2.imdecode(np.fromfile((imgPath + images[im_name]), dtype=np.uint8), 1) # 此句話的路徑可以為中文路徑
print(im_name)
videoWriter.write(frame)
print("圖片轉視頻結束!")
videoWriter.release()
cv2.destroyAllWindows()
# 此處添加上述兩個函數
if __name__ == '__main__':
Video2Pic()
# Pic2Video()
圖片轉化為視頻代碼
由圖片轉化為視頻的代碼,大家幀率按照需求來定吧
import os
import cv2
# image path
im_dir = '/media/mrtrying/ysdtracker/test/tracker_benchmark_v1.0/tmp/imgs/bike1_1'
# im_dir = '/home/mrtrying/shiyan/shujuji/cup'
# output video path
video_dir = '/home/mrtrying/shiyan/shujuji'
if not os.path.exists(video_dir):
os.makedirs(video_dir)
# set saved fps
fps = 20
# get frames list
frames = sorted(os.listdir(im_dir))
# w,h of image
img = cv2.imread(os.path.join(im_dir, frames[0]))
img_size = (img.shape[1], img.shape[0])
# get seq name
seq_name = os.path.dirname(im_dir).split('/')[-1]
# splice video_dir
# video_dir = os.path.join(video_dir, seq_name + '.avi')
# fourcc = cv2.VideoWriter_fourcc('M', 'J', 'P', 'G')
video_dir = os.path.join(video_dir, seq_name + '.mp4')
fourcc = cv2.VideoWriter_fourcc('M', 'p', '4', 'V')
# also can write like:fourcc = cv2.VideoWriter_fourcc(*'MJPG')
# if want to write .mp4 file, use 'MP4V'
videowriter = cv2.VideoWriter(video_dir, fourcc, fps, img_size)
for frame in frames:
f_path = os.path.join(im_dir, frame)
image = cv2.imread(f_path)
videowriter.write(image)
print(frame + " has been written!")
videowriter.release()
視覺跟蹤demo所需要的代碼
這裏就是訓練好的跟蹤器,需要加載訓練好的模型才可以,用於測試單獨序列的代碼,也比較簡單
from __future__ import absolute_import
import os
import sys
sys.path.append(os.getcwd())
import glob
import numpy as np
import argparse
import cv2
import torch
from xxx import Tracker#加載所構建的跟蹤器,這裏需要大家加入自己的跟蹤器
import multiprocessing
multiprocessing.set_start_method('spawn',True)
model_path = 'models/ysdtracker_20.pth'
gpu_id = 0
def get_axis_aligned_bbox(region):
""" convert region to (cx, cy, w, h) that represent by axis aligned box
"""
# nv = region.size
nv = 4
if nv == 8:
cx = np.mean(region[0::2])
cy = np.mean(region[1::2])
x1 = min(region[0::2])
x2 = max(region[0::2])
y1 = min(region[1::2])
y2 = max(region[1::2])
A1 = np.linalg.norm(region[0:2] - region[2:4]) * \
np.linalg.norm(region[2:4] - region[4:6])
A2 = (x2 - x1) * (y2 - y1)
s = np.sqrt(A1 / A2)
w = s * (x2 - x1) + 1
h = s * (y2 - y1) + 1
else:
x = region[0]
y = region[1]
w = region[2]
h = region[3]
cx = x+w/2
cy = y+h/2
return cx, cy, w, h
def cxy_wh_2_rect(pos, sz):
return np.array([pos[0]-sz[0]/2, pos[1]-sz[1]/2, sz[0], sz[1]]) # 0-index
### 測試圖片視頻序列
# image and init box
image_files = sorted(glob.glob('/home/mrtrying/shiyan/shujuji/OTB2015/Basketball/img/*.jpg')) #測試序列的路徑
init_rbox = [198,214,34,81]
init_rbox = list(map(int, init_rbox))
tracker=Tracker(model_path,0)#這裏就是構建和加載測試數據集構建的跟蹤器,需要自己加載
[cx, cy, w, h] = get_axis_aligned_bbox(init_rbox)
# tracker init
target_pos, target_sz = np.array([cx, cy]), np.array([w, h])
im = cv2.imread(image_files[0]) # HxWxC
state = tracker.init(im,init_rbox)
# tracking and visualization
toc = 0
for f, image_file in enumerate(image_files):
im = cv2.imread(image_file)
tic = cv2.getTickCount()
state = tracker.update(im) # track
bbox = list(map(int, state))
toc += cv2.getTickCount()-tic
cv2.rectangle(im, (bbox[0], bbox[1]), (bbox[0]+bbox[2], bbox[1]+bbox[3]), (0, 255, 255), 3)
cv2.imshow('demo', im)
cv2.waitKey(1)
print('Tracking Speed {:.1f}fps'.format((len(image_files)-1)/(toc/cv2.getTickFrequency())))
下面的代碼主要是測試自己所採集的視頻,需要注意的是視頻要為avi格式,mp4格式要報錯,同時保存為圖像,為後面的gif動圖做準備,
from __future__ import absolute_import
import os
import sys
sys.path.append(os.getcwd())
import glob
import numpy as np
import argparse
import cv2
import torch
from xxx import Tracker#這裏需要改動的是:需要加載自己測試數據集是所用到的跟蹤器
import multiprocessing
multiprocessing.set_start_method('spawn',True)
model_path = 'models/ysdtracker_20.pth'
gpu_id = 0
###測試自己拍攝的視頻
def get_frames(video_name):
if not video_name:
cap = cv2.VideoCapture(0)
# warmup
for i in range(5):
cap.read()
while True:
ret, frame = cap.read()
if ret:
yield frame
else:
break
elif video_name.endswith('avi') or \
video_name.endswith('mp4'):
cap = cv2.VideoCapture(args.video_name)
while True:
ret, frame = cap.read()
if ret:
yield frame
else:
break
else:
images = glob(os.path.join(video_name, '*.jp*'))
images = sorted(images,
key=lambda x: int(x.split('/')[-1].split('.')[0]))
for img in images:
frame = cv2.imread(img)
yield frame
video='/home/mrtrying/shiyan/mytest/myEI/save.avi'#加載自己的視頻路徑
parser = argparse.ArgumentParser(description='tracking demo')
parser.add_argument('--video_name', default=video, type=str,
help='videos or image files')
args = parser.parse_args()
def main():
# build tracker
tracker=Tracker(model_path,0)
first_frame = True
if args.video_name:
video_name = args.video_name.split('/')[-1].split('.')[0]
else:
video_name = 'webcam'
cv2.namedWindow(video_name, cv2.WND_PROP_FULLSCREEN)
pic = "/home/mrtrying/shiyan/mytest/myEI/pic/"#保存圖像到指定路徑下
c = 0#用來建立幀數,為了能夠跟蹤過程中的每一幀都可以保存
for frame in get_frames(args.video_name):
if first_frame:
try:
init_rect = cv2.selectROI(video_name, frame, False, False)
except:
exit()
tracker.init(frame, init_rect)
first_frame = False
else:
outputs = tracker.update(frame) #這裏的只能送入幀數
c = c + 1
bbox = list(map(int, outputs))
cv2.rectangle(frame, (bbox[0], bbox[1]),
(bbox[0]+bbox[2], bbox[1]+bbox[3]),
(0, 0, 255), 3)
cv2.imshow(video_name, frame)
# cv2.imwrite('video_name.jpg',frame)
cv2.imwrite(pic + video_name + str(c) + '_' + '.jpg',frame)
cv2.waitKey(40)
if __name__ == '__main__':
main()
視覺跟蹤自己的demo產生gif
import imageio
import glob
def main():
c = 0
image_listall = sorted(glob.glob('/home/mrtrying/shiyan/mytest/myEI/pic/*.jpg'))#用於長度的計算
image_list_ = []
frames = []
duration = 0.01
for i in range(len(image_listall)):
c = c + 1
image_list_.append(sorted(glob.glob('/home/mrtrying/shiyan/mytest/myEI/pic/save{}_.jpg'.format(c))))
for image_list in image_list_:
for image_name in image_list:
frames.append(imageio.imread(image_name))
gif_name = '/home/mrtrying/shiyan/mytest/myEI/demo.gif'
imageio.mimsave(gif_name, frames, 'GIF', duration=duration)
if __name__ == '__main__':
main()
最後説一句,博主不易,請大家點點關注!