Sending OpenCV2 Videowrite input to buffer instead of file - python

I would like to write openCV2 videorecorder output to a buffer in the memory rather than to a file on my hard drive. Following that i could write out to a file or not (and this way save a flash based object from over use). I've tried pyfilesystem and i've tried things like IO and StringIO, but VideoRecorder does not accept these saying it was looking for a String or Unicode type and instead found a (_IOTextWrapper, IOString, etc....) type.

I get now what you mean, however that would somehow tend to break the purpose of VideoWriter I suppose. It's job is to write the video on the disk. However, I agree, it would be nice to have a Video class that then we could manipulate within cv2.
Meanwhile, lucky for us, video's are nothing but sequences of frames, which are but numpy arrays. We can do a lot with those so here's the general idea I'd propose:
import numpy as np
import cv2
def save_to_vid(video):
path = ".../output.avi"
height , width , layers = video[0].shape
out = cv2.VideoWriter(path, cv2.cv.FOURCC("X", "V", "I", "D"),
20.0, (width, height))
for frame in frames:
out.write(frame)
out.release()
##CAPTURING SOME TEST FRAMES
cap = cv2.VideoCapture(0)
frames = list() #THIS IS YOUR VIDEO
while(cap.isOpened()):
ret, frame = cap.read()
if ret==True:
frame = cv2.flip(frame,0)
frames.append(frame)
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
cap.release()
cv2.destroyAllWindows()
#SOMETIMES LATER IN THE RPOGRAM
doYouWantToSave = True
if doYouWantToSave:
save_to_vid(frames)
else:
del frames
Of course this all can be done smarter I suppose by creating your own class Video and then instantiating that and handling it as an object in your code. Video could have a method "writeToFile" as well. It could even be scripted a bit smarter to save some space, or work as an actual buffer if that's exactly what you need.

Related

OpenCV VideoWriter writes corrupted video files

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.

OpenCV load video from url

I have a video file (i.e. https://www.example.com/myvideo.mp4) and need to load it with OpenCV.
Doing the equivalent with an image is fairly trivial:
imgReq = requests.get("https://www.example.com/myimage.jpg")
imageBytes = np.asarray(bytearray(data), dtype=np.uint8)
loadedImage = cv2.imdecode(image, cv2.IMREAD_COLOR)
I would like to do something similar to the following (where loadedVideo will be similar to what OpenCV returns from cv2.VideoCapture):
videoReq = requests.get("https://www.example.com/myimage.mp4")
videoBytes = np.asarray(bytearray(data), dtype=np.uint8)
loadedVideo = cv2.videodecode(image, cv2.IMREAD_COLOR)
But cv2.videodecode does not exist. Any ideas?
Edit: Seeing as this may be a dead end with only OpenCV, I'm open for solutions that combine other imaging libraries before loading into OpenCV...if such a solution exists.
It seems that cv2.videocode is not a valid OpenCV API either in OpenCV 2.x or OpenCV 3.x.
Below is a sample code it works in OpenCV 3 which uses cv2.VideoCapture class.
import numpy as np
import cv2
# Open a sample video available in sample-videos
vcap = cv2.VideoCapture('https://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_2mb.mp4')
#if not vcap.isOpened():
# print "File Cannot be Opened"
while(True):
# Capture frame-by-frame
ret, frame = vcap.read()
#print cap.isOpened(), ret
if frame is not None:
# Display the resulting frame
cv2.imshow('frame',frame)
# Press q to close the video windows before it ends if you want
if cv2.waitKey(22) & 0xFF == ord('q'):
break
else:
print "Frame is None"
break
# When everything done, release the capture
vcap.release()
cv2.destroyAllWindows()
print "Video stop"
You may check this Getting Started with Videos tutorial for more information.
Hope this help.
You will have to read the video using VideoCapture. there is no other way around that for now. unless you define it yourself.
remember a video is a combination of images changing at defined frame rate.
So You can read each frame in a while loop. as you apply the imdecode function.
import numpy as np
import cv2
cap = cv2.VideoCapture('https://www.example.com/myimage.mp4')
while(cap.isOpened()):
ret, image = cap.read()
loadedImage = cv2.imdecode(image, cv2.IMREAD_COLOR)
cv2.imshow('frame',loadedImage)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()

python - Output by OpenCV VideoWriter empty

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.

OpenCV: Without modifications, input video file smaller than output file

I am currently using OpenCV in python to read from a video .mp4 file which is ~300kb in size, 1min and 20sec long. I have noticed that if I read each frame from the file, and write said frame to a new file using OpenCV's functionalities, my new video copy is ~50Mb... can someone explain how this is possible and how to fix it?
The codec for both files is the same: H.264
Below is the code:
import numpy as np
import cv2
cap = cv2.VideoCapture('/Users/video.mp4')
# Define the codec and create VideoWriter object
fourcc = cv2.VideoWriter_fourcc(*'avc1')
out = cv2.VideoWriter('output.mp4',fourcc, 50.0, (160, 210))
while(cap.isOpened()):
ret, frame = cap.read()
if ret==True:
out.write(frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
# Release everything if job is finished
cap.release()
out.release()
cv2.destroyAllWindows()

NO video file was saved by using Python and OpenCV on my Raspberry PI

I have two pieces of codes. Here is the first one. It was mainly copied from save a video section on OpenCV-Python tutorial website, but I modified a little bit.
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
cap.set(7,200)
out = cv2.VideoWriter('output.avi',cv2.cv.CV_FOURCC('X','V','I','D'), 20.0, (640,480))
while(cap.isOpened()):
ret, frame = cap.read()
if ret==True:
out.write(frame)
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
cap.release()
cv2.destroyAllWindows()
Second one is here:
import cv
cv.NamedWindow('camera',1)
cap = cv.CaptureFromCAM(0)
fps = 20
fourcc = cv.CV_FOURCC('X','V','I','D')
cv.SetCaptureProperty(cap,cv.CV_CAP_PROP_FRAME_COUNT,200)
out = cv.CreateVideoWriter('output.avi',fourcc,fps,(640,480))
while True
img = cv.QueryFrame(out,img)
cv.WriteFrame(out,img)
cv.ShowImage('camera',img)
if cv.WaitKey(1) & 0xFF == ord('q'):
break
cv.DestroyAllWindows()
Neither of them can make a video file saved or destroy the window in the end. No errors occurred in shell after running the code. I used Python 2.7.6 and OpenCV 2.3.1. Can somebody help me? Thanks a lot.
PS: I am not sure whether my method to set frame numbers correct or not.
It may have several reasons. Check the following:
Check that you can encode with XVID, maybe try with MJPEG first.
Set width and height of your input video by cap.set(3,640) and cap.set(4,480)

Categories

Resources