I used the following page from OpenCV 3.0.0 tutorial: Tutorial in docs
When I tried to use the example that saves videos, it doesn't work.
It displays the content from the webcam, and also creates a file called output.avi, but when I checked the size of ouput.avi, it was zero bytes.
I also tried using different codecs, like YUY2.
I use Python 2.7.8 and OpenCV 3.0.0
and Windows 8.1
I had the same problem and I solved it by specifying the video output resolution to exactly the same as input:
cap = cv2.VideoCapture('vtest.avi')
...
out = cv2.VideoWriter('output.avi',fourcc, 20.0,(int(cap.get(3)),int(cap.get(4))))
Of course make sure you got ffmpeg installed and working.
Replacing:
fourcc = cv2.VideoWriter_fourcc(*'XVID')
With:
fourcc = cv2.VideoWriter_fourcc('M','J','P','G')
Worked for me...
More generally:
Look up the fourcc code of the video compression format you're after here, and whatever the code is - for instance 'FMP4' for FFMpeg - plug it in in the following manner:
cv2.VideoWriter_fourcc('F','M','P','4')
I was struggling with this problem for a few hours then I realized that I had typed the image's shape wrong.
It is (width, height), ie:
(image.shape[1], image.shape[0])
and not
(image.shape[0], image.shape[1])
This is how my working code looks like finally... (I am on a Windows machine):
video_path = FILENAME + '.avi'
size = images[0].shape[1], images[0].shape[0] ## <<<--- NOTICE THIS
video = cv2.VideoWriter(video_path,cv2.VideoWriter_fourcc(*'DIVX'), 60, size)
for img in images:
video.write(img)
cv2.destroyAllWindows()
video.close()
Make sure you are using the correct fourcc 4-byte code. The example on the tutorial has:
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('output.avi',fourcc, 20.0, (640,480))
This XVID code may only work for linux. The documentation above the example states (in the tutorial):
"In Windows: DIVX (More to be tested and added)." So if you haven't, try replacing the fourcc line above with:
fourcc = cv2.VideoWriter_fourcc(*'DIVX')
I use cv2.VideoWriter on linux quite often and it always works. So if the above doesn't work you can always try it on a linux vm.
In my case, I thought the codec was an obstacle but it wasn't. Instead, adjusting the dimensions being consumed by videoWriter() did the trick:
(ok, frame) = cv2.VideoCapture(videoPath).read()
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter(output, fourcc, 10.0, (1280, 720))
(1280,720) was used because frame.shape from my video outputs (1280, 720, 3). It made avi to mp4 and vice versa possible. Didn't have to worry about reconciling the codec.
Check the resolution of your images!
I was trying with odd-shaped images (1284x709) and ended up with unreadable videos of 1k in size. After resizing my image to the closest 'common' resolution:
image = cv2.resize(image, (1280,720)),
it worked just fine.
I suspect there are a lot of reasons video writing fails silently, and in my case, my frame was a composite of a 3 channel image and a 4 channel image (transparent overlay). Converting the end result to BGR format as follows allowed the video to save successfully.
width = 1280
height = 720
FPS = 30
fourcc = VideoWriter_fourcc(*'avc1')
video = VideoWriter('output.mp4', fourcc, float(FPS), (width, height))
for img in images:
frame = cv2.cvtColor(img, cv2.COLOR_BGRA2BGR)
video.write(frame)
video.release()
It should be a problem with the codec you're using.
Have you tried:
cv.CV_FOURCC('i', 'Y', 'U', 'V')
This one worked for me.
On windows 7 and using Python 2.7 and OpenCV 2.4.8, I experienced the fact that if the file NAME is "output.mpg" would not write.
I solved it by changing to "output.avi".
I have the exact same issue. I am using OpenCV in C++, but I believe you can still pass -1 instead of choosing the codec so you can have a drop down menu of the available codecs even in python. From there I tried all different codecs and just like Leonard Zhou, the IYUV codec was the one that worked for me. Also note that it was the only one that worked even though I could use XVID just fine on another machine with the same code and same codec installer.
EDIT:
What I suggested worked as a patch, the main issue was solved on my end by adding the opencv_ffmpeg dll in the executable's folder.
I changed the Video writer size to my screen resolution size and it worked.
here is the solution.
out = cv2.VideoWriter("output.avi", fourcc, 5.0, (1920, 1080))
It worked for me after I assigned the actual frame size and not what I thought the size was:
ret, frame = cap.read()
height, width, channels = frame.shape
codec = cv2.VideoWriter_fourcc(*"DIVX")
out=cv2.VideoWriter('new.avi',codec ,20.0,(width, height))
And put out.write(frame) inside the while loop before cv2.imshow("Frame", frame).
To state the obvious, make sure you're giving not only a correct path, but also a video name.
i.e. path/'video.avi' and not just path/. It will fail silently otherwise.
I had same issue that the video file was being created without any errors but it won't run and had a size of few KBs. Here's how I resolved it;
Make sure you have passed FPS argument in float value.
The output resolution needs to be same as of input video resolution.
In my case I am resizing the image, but saving video with original size instead of new size.
After trying hours to find the error, I finally found it. So here are some things to keep in mind. (For Linux users particularly)
Use this codec ("MJPG").
cv2.VideoWriter_fourcc(*'MJPG')
Do not forget to write the Boolean value as final argument (True for RGB and False for GrayScale) in
cv2.VideoWriter(path, fourcc, float(frameRate), frameSize, True)
The argument, frameSize required by cv2.VideoWriter is a tuple of form (width, height) and not (height, width) which is the shape of image array if you open the image using cv2.read or Image.open. So don't forget to invert it.
The above methods work only for RGB frames/images. Incase you are trying to write a grayscale image, pass a parameter 0 to the VideoWriter():
fourcc = cv2.VideoWriter_fourcc(*"MJPG")
out = cv2.VideoWriter('output.avi', fourcc, 30, size, 0)
I tried by creating its exe using pyinstaller Recorder.py it worked for me.
Remember before using pyinstaller you have to pip install pyinstaller.
Related
Edit: The problem was fixed after using VLC media player. The standard windows media player could not read the videos.
I am attempting to take a video, run it through an object detector, add the bounding boxes, and output the video with the bounding boxes. However, I'm having a strange problem where the video I output cannot be viewed. I get a "Server execution failed" error when attempting to play the video on my local windows 10 machine. I am developing through SSH on ubuntu 20.04 with the vs code remote development extension.
Here is some OpenCV code that does not work with my setup. The video is written to the disk, and OpenCV is able to read frames from output5.avi, however the output5.avi file cannot be opened as I described.
import cv2
cap = cv2.VideoCapture("video.mov")
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
fourcc = cv2.VideoWriter_fourcc(*'MJPG')
out = cv2.VideoWriter('output5.avi', fourcc, 30, (width, height), isColor=True)
while cap.isOpened():
# get validity boolean and current frame
ret, frame = cap.read()
# if valid tag is false, loop back to start
if not ret:
break
else:
frame = cv2.resize(frame, (width, height))
out.write(frame)
cap.release()
out.release()
I have also attempted to save the video through torchvision.io.write_video, but the exact same problem occurs. Tensorboard similarly doesn't work.
It must be something wrong with how the remote machine is set up, but I have no idea what could be wrong.
System information
OpenCV => 4.4.0.46
Operating System / Platform => MacOS Catalina 10.15.4
Compiler => Jupyter Notebook via Anaconda 4.8.3
I'm doing a computer vision task, in which my current step is to create a video based on previously created images. To do so, I'm using OpenCV like this:
fps = 25
files = natsorted([f for f in glob.glob(os.getcwd()+'/tf_files/test/*.jpg')])[:125]
size = (1920,1080)
fourcc = int(cv2.VideoWriter_fourcc(*'mp4v'))
out = cv2.VideoWriter('test.mp4',fourcc,fps=fps,frameSize=size)
for file in files:
img = cv2.imread(file)
out.write(img)
out.release()
cv2.destroyAllWindows()
The files list returns the paths of the images:
files[0]
'/Users/XXX/XXX/projects/phase_seg/tensorflow-for-poets-2/tf_files/test/0.jpg'
with the size of each file being:
cv2.imread(files[0]).shape
>>> (1080, 1920, 3)
The code does not give any errors and does actually create a video called 'test.mp4'. Moreover, if the amount of images is changed, the video does change in size as well. I can also open the images with opencv without any problem.
However, the video cannot be played, and when exported to another program, it is of length 0. I've tried different variations of fourcc like 'M','P','4','V', but without any success. What can be a possible explanation for this?
I am trying to stream and save video from my webcam with the Python script shown below but, for some reason, the 'myvideo.mp4' file has a very small size and cannot be opened with QuickTime (or other players) - it seems to be empty. However, the video stream works perfectly.
As suggested in other topics, I have tried different file formats and codecs and I pass exact fps, width and height that my webcam returns. Perhaps anyone knows what can be the issue here? Thanks in advance!
import cv2
cap = cv2.VideoCapture(0)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
fps = cap.get(cv2.CAP_PROP_FPS)
writer = cv2.VideoWriter('myvideo.mp4',cv2.VideoWriter_fourcc(*'mp4v'),fps,(width,height))
while True:
ret,frame = cap.read()
# OPERATIONS (DRAWING)
writer.write(frame)
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
writer.release()
cv2.destroyAllWindows()
I have also tried running the script as superuser but it did not help. I am using Mac.
QuickTime error:
The document “myvideo.mp4” could not be opened.
The file isn’t compatible with QuickTime Player.
Try to change fourcc(4-character code of codec used to compress the frames.)
writer = cv2.VideoWriter('myvideo.mp4',cv2.VideoWriter_fourcc(*'mp4v'),fps,(width,height))
replace it with
writer = cv2.VideoWriter('myvideo.mp4',cv2.VideoWriter_fourcc(*'XVID'),fps,(width,height))
Simply fix typo
Change
height = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
to
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
You were taking CAP_PROP_FRAME_WIDTH twice.
If the problem persists...
If this still does not help, try to swap them. It seems stupid, but helped for me. I guess that the get method somehow takes orientation into account, but then reading a frame neglects the orientation of the video (or opposite, does not matter, they are just inconsistent). I had exactly the same problem, and swapped width with height and it solved it.
Extra
A bit old list of codecs tested on mac.
I just bought a FLIR BlackFlyS USB3.0 camera. I can grap frames from the camera but I am not able to use that frame with opencv without saving them first. Is there anyone who knows how to convert them to use in opencv?
I searched on the internet about everything that include "PySpin" word and found this book.
I have tried to use PySpinCapture which is mentioned in this book but I couldn't figure it out anyway.
capture = PySpinCapture.PySpinCapture(0, roi=(0, 0, 960, 600),binningRadius=2,isMonochrome=True)
ret, frame = capture.read()
cv2.imshow("image",frame)
cv2.waitKey(0)
I expect the see the image but it throws an error
_PySpin.SpinnakerException: Spinnaker: GenICam::AccessException= Node is not writable. : AccessException thrown in node 'PixelFormat' while calling 'PixelFormat.SetIntValue()' (file 'EnumerationT.h', line 83) [-2006]
terminate called after throwing an instance of 'Spinnaker::Exception'
One year later, and not sure if my response will help, but I figured out that you can just get the RGB numpy array from a PySpin Image by using the GetData() function.
So you could do without the PySpinCapture module and just do something like the following.
import PySpin
import cv2
serial = '18475994' #Probably different for you although I also use a BlackFly USB3.0
system = PySpin.System.GetInstance()
blackFly_list = system.GetCameras()
blackFly = blackFly_list.GetBySerial(serial)
height = blackFly.Height()
width = blackFly.Width()
channels = 1
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('test_vid.avi',fourcc, blackFly.AcquisitionFrameRate(), (blackFly.Width(), blackFly.Height()), False) #The last argument should be True if you are recording in color.
blackFly.Init()
blackFly.AcquisitionMode.SetValue(PySpin.AcquisitionMode_Continuous)
blackFly.BeginAcquisition()
nFrames = 1000
for _ in range(nFrames):
im = blackFly.GetNextImage()
im_cv2_format = im.GetData().reshape(height,width,channels)
# Here I am writing the image to a Video, but once you could save the image as something and just do whatever you want with it.
out.write(im_cv2_format)
im.release()
out.release()
In this code example I want to create an AVI video file with 1000 grabbed frames. The im.GetData() returns a 1-D numpy array which can then be converted into the correct dimensions with reshape. I have seen some talks about using the UMat class, but it does not seem to be necessary to make it work in this case. Perhaps it helps performance, but I am not sure :)
I have recently started to program with opencv-python, but I got stuck when I tried to write a video using cv2. The output by the script is empty. Here's my code:
import cv2
import numpy as np
import matplotlib.pyplot as plt
cap = cv2.VideoCapture(0)
fourcc = cv2.VideoWriter_fourcc(*'h263')
out = cv2.VideoWriter('cv2_camera_output.mp4',fourcc, 20.0, (800,600))
while True:
ret, frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow('frame', frame)
cv2.imshow('gray', gray)
out.write(frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
out.release()
cv2.destroyAllWindows()
I guessed that the issue must have something to do with the fourcc codec. So I googled if there was a fourCC codec for mac (I am using OS X 10.12.3 (Sierra)), but all the suggestions didn't work for my computer, so the issue may not even be in the fourCC codec. These are the links I have visited:
OpenCV Documentation (I didn't follow this one, it was just to make sure, and it didn't work either)
GitHub Tests for FourCC codecs on OS X
Does anybody know the real issue? Any help would be great
Your frame width and height must be the same as the width and height of your VideoWriter. Just add this before out.write(frame) and you might be fine:
frame = cv2.resize(frame,(800,600))
Or change the size of your VideoWriter to the initial size of webcam frame. Mine is (640,480). I think if your OS doesn't support the format, it just won't write anything. Not even an empty file will be created. I'm on Linux and I think 'h263' doesn't work on it but 'h264' does. When I use 'h263' it just doesn't make any file.
I solved the problem. The problem simply was that I could not use the VideoWriter for grayscale, so I had to use it for the coloured frame.
Biggest problem is that h263 specifies the exact frame sizes it can encode (take a look at the possible values at https://en.wikipedia.org/wiki/H.263#Version_1_and_Annex_I) and you don't comply with that.
After resolving this issue it is possible that h263 still won't work with mp4 container on OSX (on Linux and Windows it doesn't because they use FFMPEG as backends but OSX uses another library) so I suggest that you use avi as container.
And lastly you will have to either resize your image (just like #ROAR said) or use the dimensions of the input device like this:
width = int(cap.get(3))
height = int(cap.get(4))
Although if you do the latter with h263 codec than you have to use an input device which produces frames that are compliant with the size restrictions.
My problem was actually that I did not have space left on my disk. It not did give a warning.