在python opencv中加快在4K 25 fps视频上循环投资回报的创建

时间:2019-08-02 21:33:45

标签: python opencv

我正在以25 fps拍摄2小时长的4K MP4视频。我正在python 3中使用openCV。从视频中,我需要提取3个循环ROI。

由于存在大量帧(212831),因此在64 GB RAM工作站上使用以下代码逐帧处理整个视频需要24小时。有什么方法可以加快处理速度或解决方法,其效果与类似效果略有不同吗?

这是代码。

import numpy as np
import cv2
import sys
import time

# name of source video and paths
video = 'C0023_2hanalysis'
input_vidpath = 'path_to_video/' + video + '.MP4'
output_vidpath = 'path_to_video/' + video + '-withROI.MP4'
codec = 'avc1'

# set ROI coordinates extrapolated from last video frame as well as fixed     parameters for analysis (radius)
x = 1188 # in pixels
y = 1204 # in pixels
radius = 75

# set parameters for output video as identical to input
fps = 25.0
scaling = 1.0 # output vs input video speed (?) 

## import video
cap = cv2.VideoCapture(input_vidpath)
if cap.isOpened() == False:
    sys.exit('Video file cannot be read! Please check input_vidpath to ensure it is correctly pointing to the video file')

## Video writer class to output video
fourcc = cv2.VideoWriter_fourcc(*codec) # concatenate the 4 chars to a fourcc code, i.e. the 4-char name of the codec used to compress the frames
# adjust output frame size to scaling if any is applied
#(frame shape is given as height,width , so the output needs to be re-ordered to match VideoWriter arguments)
o_height = cap.read()[1].shape[0]
o_width = cap.read()[1].shape[1]
output_framesize = (int(o_width*scaling),int(o_height*scaling)) 
out = cv2.VideoWriter(filename = output_vidpath, fourcc = 0x7634706d, fps = fps, frameSize = output_framesize, isColor = True)

## apply ROI frame by frame and thread them back into output video
start = time.time()
f = -1
last = 0
while(True):
    # Capture frame-by-frame
    ret, frame = cap.read() #'return' value (T/F) and frame

    this = cap.get(1) # get 'CV_CAP_PROP_POS_FRAMES'
    if ret == True:
        #frame = cv2.resize(frame, None, fx = scaling, fy = scaling, interpolation = cv2.INTER_LINEAR) # no need to resize in this case

        # Apply mask to area of interest
        mask = np.zeros((o_height,o_width), np.uint8)
        mask = cv2.circle(mask,(x,y),radius,255,thickness=-1) #image, row and column coord of centre of circle, radius, color (black), thickness
        frame[mask ==  0] = 0

        out.write(frame)
        key = cv2.waitKey(1) & 0xFF

        # if the `q` key was pressed, break from the loop
        if key == ord("q"):
            break

        f += 1
        if f%1000==0:
            print(f)


    if last == this:
        break

    last = this

## When everything done, release the capture
cap.release()
out.release()
cv2.destroyAllWindows()
cv2.waitKey(1)

## End time and duration
end = time.time()
duration = end - start
print("--- %s seconds ---" %duration)

1 个答案:

答案 0 :(得分:2)

这是一个常见错误。要尽可能快地处理帧,请不要调用waitKey(1)。该功能基本上是在处理完每个帧后增加短暂的睡眠,并且睡眠时间比处理时间长得多。

您只需要删除它,并且如果您想在中间停下来,仍然可以终止该过程。

import numpy as np
import cv2
import sys
import time

# name of source video and paths
video = 'C0023_2hanalysis'
input_vidpath = 'path_to_video/' + video + '.MP4'
output_vidpath = 'path_to_video/' + video + '-withROI.MP4'
codec = 'avc1'

# set ROI coordinates extrapolated from last video frame as well as fixed     parameters for analysis (radius)
x = 1188 # in pixels
y = 1204 # in pixels
radius = 75

# set parameters for output video as identical to input
fps = 25.0
scaling = 1.0 # output vs input video speed (?) 

## import video
cap = cv2.VideoCapture(input_vidpath)
if cap.isOpened() == False:
    sys.exit('Video file cannot be read! Please check input_vidpath to ensure it is correctly pointing to the video file')

## Video writer class to output video
fourcc = cv2.VideoWriter_fourcc(*codec) # concatenate the 4 chars to a fourcc code, i.e. the 4-char name of the codec used to compress the frames
# adjust output frame size to scaling if any is applied
#(frame shape is given as height,width , so the output needs to be re-ordered to match VideoWriter arguments)
o_height = cap.read()[1].shape[0]
o_width = cap.read()[1].shape[1]
output_framesize = (int(o_width*scaling),int(o_height*scaling)) 
out = cv2.VideoWriter(filename = output_vidpath, fourcc = 0x7634706d, fps = fps, frameSize = output_framesize, isColor = True)

## apply ROI frame by frame and thread them back into output video
start = time.time()
f = -1
last = 0
while(True):
    # Capture frame-by-frame
    ret, frame = cap.read() #'return' value (T/F) and frame

    this = cap.get(1) # get 'CV_CAP_PROP_POS_FRAMES'
    if ret == True:
        #frame = cv2.resize(frame, None, fx = scaling, fy = scaling, interpolation = cv2.INTER_LINEAR) # no need to resize in this case

        # Apply mask to area of interest
        mask = np.zeros((o_height,o_width), np.uint8)
        mask = cv2.circle(mask,(x,y),radius,255,thickness=-1) #image, row and column coord of centre of circle, radius, color (black), thickness
        frame[mask ==  0] = 0

        out.write(frame)

        f += 1
        if f%1000==0:
            print(f)


    if last == this:
        break

    last = this

## When everything done, release the capture
cap.release()
out.release()
cv2.destroyAllWindows()
cv2.waitKey(1)

## End time and duration
end = time.time()
duration = end - start
print("--- %s seconds ---" %duration)