前言:
普通播放视频的代码是有非常多劣势, 像这下面这个代码其实会出现非常多的问题,例如:容易内存泄漏;面对文件读取错误会导致整个程序崩盘;无法合成视频保存;无法显示当前帧数和视频总帧数等等。诶,反正就是不太好啦!
所以我自己编写了一个可以处理异常,稳定的视频播放类,且可以读取视频、保存视频,播放当前帧,视频总帧数、Fps等等功能!
import numpy as np import cv2 cap = capture = cv2.VideoCapture('C2.mp4') while (cap.isOpened()): ret, frame = cap.read() gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) cv2.imshow('frame', gray) cv2.waitKey(1) cap.release() cv2.destroyAllWindows()
VideoTracker.py
# --time**2022.8.13 # --** worker:江子良 import cv2 import time import torch import warnings import numpy as np from PIL import Image from loguru import logger import os os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE" class VideoTracker(object): def __init__(self, cam=-1, video_path='', save_path='', use_frame=[0, -1], display=True): self.display = display self.use_frame = use_frame self.video_path = video_path self.cam = cam if self.cam != -1: print("Using webcam :" + str(self.cam)) self.vdo = cv2.VideoCapture(self.cam) else: print("Using video :" + str(self.video_path)) self.vdo = cv2.VideoCapture() self.save_path = save_path self.frame_interval = 1 self.use_cuda = True use_cuda = self.use_cuda and torch.cuda.is_available() if not use_cuda: warnings.warn("Running in cpu mode which maybe very slow!", UserWarning) def __enter__(self): if self.cam != -1: ret, frame = self.vdo.read() assert ret, "Error: Camera error" self.im_width = frame.shape[0] self.im_height = frame.shape[1] self.count_frame = int(-1) else: assert os.path.isfile(self.video_path), "Path error" self.vdo.open(self.video_path) self.im_width = int(self.vdo.get(cv2.CAP_PROP_FRAME_WIDTH)) self.im_height = int(self.vdo.get(cv2.CAP_PROP_FRAME_HEIGHT)) self.count_frame = int(self.vdo.get(cv2.CAP_PROP_FRAME_COUNT)) assert self.vdo.isOpened() if self.save_path != '': os.makedirs(self.save_path, exist_ok=True) # path of saved video and results self.save_video_path = os.path.join(self.save_path, "results.avi") # create video writer fourcc = cv2.VideoWriter_fourcc(*'MJPG') self.writer = cv2.VideoWriter(self.save_video_path, fourcc, 24, (self.im_width, self.im_height)) # logging logger.info("Save results to {}".format(self.save_path)) return self def __exit__(self, exc_type, exc_value, exc_traceback): if exc_type: print(exc_type, exc_value, exc_traceback) def run(self): idx_frame = 0 all_costTime = 0 while self.vdo.grab(): idx_frame += 1 if idx_frame % self.frame_interval: continue if idx_frame < self.use_frame[0]: continue if idx_frame > self.use_frame[1] and self.use_frame[1] != -1: break start = time.time() ref, ori_im = self.vdo.retrieve() if ref is True: # start your code from here # -----------end----------- if self.display: cv2.imshow("frame", ori_im) if cv2.waitKey(1) & 0xFF == ord('q'): break if self.save_path: self.writer.write(ori_im) # logging end = time.time() all_costTime += end - start if self.display: if self.cam != -1: logger.info("frame schedule:<{}/-1> ({:.2f} ms), fps: {:.03f}" .format(idx_frame, end - start, 1 / (end - start))) else: logger.info("frame schedule:<{}/{}> ({:.2f} ms), fps: {:.03f}" .format(idx_frame, self.count_frame, end - start, 1 / (end - start))) logger.info("ALL_COST_TIME:{:.3f}s".format(all_costTime))
How to use?
#using camer from VideoCapture import VideoTracker if __name__ == '__main__': # select the camer you want to use with VideoTracker(cam=0) as vdo_trk: vdo_trk.run() #using video from VideoCapture import VideoTracker if __name__ == '__main__': # select the video you want to use with VideoTracker(video_path='test.mp4',use_frame=[0, -1]) as vdo_trk: vdo_trk.run() # save video
只需要在VideoTracker中设置参数save_path,save_path是要存放保存视频的位置,如:'datasets/out_video/'
【OUTPUT】