Home > Blockchain >  Trying to plot data onto video, but OpenCV VideoWriter produces Empty File (No Prior Solutions Work)
Trying to plot data onto video, but OpenCV VideoWriter produces Empty File (No Prior Solutions Work)

Time:12-18

I'm trying to open a video, read in a frame, draw a data curve on it, then save that frame to a video file. The input files are *.MOV formats from a variety of cameras, and I would really like to avoid converting them before this.

import numpy
import cv2
import matplotlib.pyplot as plt
cap = cv2.VideoCapture(filename)
print(cap.isOpened())
fourcc = cv2.VideoWriter_fourcc('X', 'V', 'I', 'D')
fig = plt.figure()
fig.subplots_adjust(0,0,1,1)
plt.axis('off')
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
fig.canvas.draw()
out = cv2.VideoWriter(filename.replace('.','splined.'),fourcc, fps, fig.canvas.get_width_height()[::-1])
plt.close(fig)
for x in range(Startframe, Stopframe): 
    print(x)
    cap.set(cv2.CAP_PROP_POS_FRAMES,x)
    a,img=cap.read(0)
    fig = plt.figure()
    fig.subplots_adjust(0,0,1,1)
    plt.axis('off')
    plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    plt.plot(TimeSplines[1,:,x-Startframe],TimeSplines[0,:,x-Startframe])
    fig.canvas.draw()
    img2 = numpy.fromstring(fig.canvas.tostring_rgb(), dtype=numpy.uint8,sep='')
    img2 = img2.reshape(fig.canvas.get_width_height()[::-1]   (3,))
    img2 = cv2.cvtColor(img2, cv2.COLOR_RGBA2BGRA)
    plt.close(fig)
    out.write(img2)
cap.release()
out.release()

The code runs without errors, but returns an empty file. I'm using matplotlib because I haven't found any way to plot data curves onto a video file in openCV - I found something called plot2d, but I can't find any examples of successful codes, nor can I even call it, so I gave up. I've tried fourCC codes of XVID, DIVX, and MP4V (and lowercase mp4v), all without success. I've looked at every other question like this on here, and none work for me.

CodePudding user response:

I could identified two issues:

  • The video size argument of cv2.VideoWriter should be (width, height) and not (height, width).
    Replace out = cv2.VideoWriter(filename.replace('.','splined.'),fourcc, fps, fig.canvas.get_width_height()[::-1]) with:

     out = cv2.VideoWriter(filename.replace('.','splined.'),fourcc, fps, fig.canvas.get_width_height())
    
  • cv2.VideoWriter does not support BGRA color format (at least not for the relevant codec).
    Replace img2 = cv2.cvtColor(img2, cv2.COLOR_RGBA2BGRA) with:

     img2 = cv2.cvtColor(img2, cv2.COLOR_RGBA2BGR)
    

Using XVID codec issues a warning message.
It is recommended to replace fourcc = cv2.VideoWriter_fourcc('X', 'V', 'I', 'D') with:

fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')

Here is the code I used for testing:

import numpy
import cv2
import matplotlib.pyplot as plt

filename = 'in1.mp4'
Startframe = 1
Stopframe = 10
fps = 1

TimeSplines = numpy.random.randint(100, size=(2, 100, 100))

cap = cv2.VideoCapture(filename)
print(cap.isOpened())

a,img=cap.read(0)

#fourcc = cv2.VideoWriter_fourcc('X', 'V', 'I', 'D')
fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
fig = plt.figure()
fig.subplots_adjust(0,0,1,1)
plt.axis('off')
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
fig.canvas.draw()
#out = cv2.VideoWriter(filename.replace('.','splined.'),fourcc, fps, fig.canvas.get_width_height()[::-1])
out = cv2.VideoWriter(filename.replace('.','splined.'),fourcc, fps, fig.canvas.get_width_height())
plt.close(fig)

for x in range(Startframe, Stopframe):
    print(x)
    cap.set(cv2.CAP_PROP_POS_FRAMES,x)
    a,img=cap.read(0)
    fig = plt.figure()
    fig.subplots_adjust(0,0,1,1)
    plt.axis('off')
    plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    plt.plot(TimeSplines[1,:,x-Startframe],TimeSplines[0,:,x-Startframe])
    fig.canvas.draw()
    img2 = numpy.fromstring(fig.canvas.tostring_rgb(), dtype=numpy.uint8,sep='')
    img2 = img2.reshape(fig.canvas.get_width_height()[::-1]   (3,))
    #img2 = cv2.cvtColor(img2, cv2.COLOR_RGBA2BGRA)
    img2 = cv2.cvtColor(img2, cv2.COLOR_RGBA2BGR)
    plt.close(fig)
    out.write(img2)

    cv2.imshow('img2', img2)
    cv2.waitKey(1000)

cap.release()
out.release()
cv2.destroyAllWindows()
  • Related