I have a folder of pkl files in 'somefile' that I need to open as videos with opencv, but I keep getting the _pickle.UnpicklingError: unpickling stack underflow error. What am I doing wrong? I know that my code isn't pretty... Please don't roast me lol
import cv2 import os import pickle import numpy as np
subdir ='somefile' files = os.listdir(subdir)
# open pkl filesfor f in files:
with open(subdir + '/' + f, 'rb') as infile:
try:
unpickled_videos = pickle.load(infile)
for video in unpickled_videos:
print('{} has been unpickled'.format(os.path.abspath(video)))
# play video from file
for video in unpickled_videos:
if video == 'eye':
# create VideoCapture object, read from input file
cap = cv2.VideoCapture('eye' + '.mp4')
# check if camera opened successfully
if (cap.isOpened() == False):
print("Error opening {}".format(os.path.abspath(video)))
# convert resolutions from float to integer
frame_width = int(cap.get(3))
frame_height = int(cap.get(4))
fps = cap.get(cv2.cv.CV_CAP_PROP_FPS)
# define codec and create VideoWriter object
fourcc = cv2.VideoWriter_fourcc(*'MJPG')
out = cv2.VideoWriter(video + '.MP4', fourcc, fps, (frame_width, frame_height), True)
# read until video is completed
while True:
# capture frame-by-frame
ret, frame = cap.read()
# display resulting frame
cv2.imshow('frame', frame)
# press Q on keyboard to exit
if cv2.waitKey(0) & 0xFF == ord('q'):
break
except FileNotFoundError:
print('{} not found!'.format(f))
pass
except EOFError:
print('End of file error')
pass
#when everything done, release video capture object and close all frames
#cap.release() out.release() cv2.destroyAllWindows()
You could try to load it as a numpy array with:
import numpy as np
data = np.load(input_filename, allow_pickle=True)
The error sounds like it could be an issue with your data. In the case that some of your data is problematic, you could wrap the call in a try/except.
Related
I have a list of videos (10 sec each) in a folder and I'm trying to loop through each action video to extract keypoints and save them as json files.
path = "path to video folder"
for file in os.listdir(path):
cap = cv2.VideoCapture(path+file)
while cap.isOpened():
try:
ret, frame = cap.read()
I ran into a problem where the extracted data has some keypoints from other videos, and I just want to run this code, end with the stop time for the video is done, pause, start next video. How can I help correct this?
If you want to process multiple videos in turn you can check the ret (success) value of cap.read() to detect the end of each file. Here is a basic example you can start with:
import os
import cv2
path = "videos"
for file in os.listdir(path):
print(file)
cap = cv2.VideoCapture(path + '/' + file)
count = 0
while True:
ret, frame = cap.read()
# check for end of file
if not ret:
break
# process frame
count += 1
print(f"{count} frames read")
cap.release()
I am using OpenCV 4.5.0 to stream a video from a USB webcam using the VideoCapture method of OpenCV. Here is the snippet of how I am reading the frames, processing them and then writing them to a file.
import cv2
import numpy as np
dev_id = 0
stream = cv2.VideoCapture(dev_id, cv2.CAP_V4L2)
fourcc = cv2.VideoWriter_fourcc(*'FMP4')
vpath = 'test.mp4'
writer = cv2.VideoWriter(vpath, fourcc, 30, (640,480), isColor=True)
if stream.isOpened():
rval, frame = stream.read()
else:
print('Could not open the stream for reading')
if not writer.isOpened():
print('Could not open the file for writing')
i = 0
while rval:
i += 1
with open('frame_{}.pkl'.format(i),'wb') as fout:
np.save(fout, frame)
writer.write(frame)
rval, frame = stream.read()
key = cv2.waitkey(1)
if key == 27: # ESC
break
writer.release()
My goal is to then read the video file that was written above and reproduce the exact same frames that I got during the live stream. I have not been able to find a way to write the live video stream to a file such that the frame extracted from the written video file matches exactly with the frame stored in the numpy array. In addition to FMP4 as the FourCC, I tried with MJPG, MP4V, XVID, LAGS, H264, MPG4. No luck so far. What am I doing wrong?
Here is how I am reading the video and comparing the frames:
vc = cv2.VideoCapture(vpath)
if vc.isOpened():
rval, frame_read = vc.read()
else:
print('Could not read video from the file')
j = 0
while rval:
j += 1
with open('frame_{}.pkl'.format(j),'rb') as fin:
frame_orig = np.load(fin)
if np.array_equal(frame_read, frame_orig):
print('same')
else:
print('different')
rval, frame_read = vc.read()
I have also tested if this is simply the indexing mismatch between the video writer and the video reader. It is not. This really looks like the difference caused by the codec used to write the frame to a file. Is there no codec which writes the same exact frame that is emitted by VideoCapture.read()?
Hi i am trying to break a long video down into smaller videos. I got some code of the internet but when I run it it does not write the video what is wrong with my code?
I am not getting any errors.
import cv2
count = 0
if __name__ == '__main__':
vidPath = 'VideoNietBewerkt.mp4'
shotsPath = '/videos/%d.avi' % count
segRange = [(0,1000),(1000,2000),(2000,3000)] # a list of starting/ending frame indices pairs
cap = cv2.VideoCapture(vidPath)
fps = int(cap.get(cv2.CAP_PROP_FPS))
size = (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)),int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
fourcc = int(cv2.VideoWriter_fourcc('X','V','I','D')) # XVID codecs
for idx,(begFidx,endFidx) in enumerate(segRange):
writer = cv2.VideoWriter(shotsPath,fourcc,fps,size)
cap.set(cv2.CAP_PROP_POS_FRAMES,begFidx)
ret = True # has frame returned
while(cap.isOpened() and ret and writer.isOpened()):
ret, frame = cap.read()
frame_number = cap.get(cv2.CAP_PROP_POS_FRAMES) - 1
if frame_number < endFidx:
writer.write(frame)
else:
break
writer.release()
count += 1
The problem was that I did not closed my cap variable I fixed this by putting everything in the for loop
import cv2
vidPath = 'VideoNietBewerkt.mp4'
segRange = [(0,5000),(5000,50000),(50000,100400)] # <-- to fit my sample movie
for idx,(begFidx,endFidx) in enumerate(segRange):
cap = cv2.VideoCapture(vidPath) # <---- Open Cap
fps = int(cap.get(cv2.CAP_PROP_FPS))
size = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)),int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
fourcc = int(cv2.VideoWriter_fourcc(*'jpeg'))
shotsPath = f'movie_{str(idx)}.avi' # <-- use idx for naming the output file
print(f'saving file: {shotsPath}')
writer = cv2.VideoWriter() # <-- instantiate the writer this way
writer.open(shotsPath, fourcc, fps, size) # <-- open the writer
cap.set(cv2.CAP_PROP_POS_FRAMES, begFidx)
while(cap.isOpened() and writer.isOpened()): # removed and ret
ret, frame = cap.read()
frame_number = cap.get(cv2.CAP_PROP_POS_FRAMES) - 1
if frame_number < endFidx:
writer.write(frame)
else:
break
writer.release()
cap.release() #<--- Closed Cap
It seems like there is a problem with the codec (at least for me) and with the output filename, which is not updated outside the loop.
I made some changes for working on my machine, try this out with a short movie, there are few comments in the code itself.
This worked for me:
import cv2
vidPath = 'movie.mp4'
segRange = [(0,30),(30,60),(60,90)] # <-- to fit my sample movie
cap = cv2.VideoCapture(vidPath)
fps = int(cap.get(cv2.CAP_PROP_FPS))
size = (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)),int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
fourcc = int(cv2.VideoWriter_fourcc(*'jpeg')) # <-- I had to change the codec
for idx,(begFidx,endFidx) in enumerate(segRange):
shotsPath = f'movie_{str(idx)}.avi' # <-- update filename here, use idx for naming the output file
print(f'saving file: {shotsPath}')
writer = cv2.VideoWriter() # <-- instantiate the writer this way
writer.open(shotsPath, fourcc, fps, size) # <-- open the writer
cap.set(cv2.CAP_PROP_POS_FRAMES, begFidx)
while(cap.isOpened() and writer.isOpened()): # removed and ret
ret, frame = cap.read()
frame_number = cap.get(cv2.CAP_PROP_POS_FRAMES) - 1
if frame_number < endFidx:
writer.write(frame)
else:
break
writer.release()
cap.release()
I'm trying to write a video to a media file using OpenCV. The video plays well and the mp4 file writes to the media file. However, when I open the written video I get this message,
This file isn't playable. That might be because the file type is unsupported, the file extension is incorrect, or the file is corrupt
I've changed VideoWriter_fourcc() to *"X264", *"H264", *"MP4V", *"mp4v", and *"MPEG". None of these resolved the issue.
import cv2
path = "C:/Users/gri_o/Desktop/opencvProjects/ProjectOne/testVideos/myvideo.mp4"
video_selected = cv2.VideoCapture(path)
vid_cod = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter('media/testOne.mp4', vid_cod, 20.0, (640,480))
while(True):
ret,frame = video_selected.read()
if ret == True:
out.write(frame)
cv2.imshow('frame', frame)
# Press Q on keyboard to exit
if cv2.waitKey(10) & 0xFF == ord('q'):
break
else:
break
video_selected.release()
out.release()
The error may be due to the width and height mentioned in,
out = cv2.VideoWriter('media/testOne.mp4', vid_cod, 20.0, (640,480))
get the frame's width and height as
w, h = frame.shape[:2]
out = cv2.VideoWriter('media/testOne.mp4', vid_cod, 20.0, (w,h))
I am trying to save one frame in every thousand frames of a video. Below is the code I am currently using:
import cv2
import numpy as np
import os
# Playing video from file:
cap = cv2.VideoCapture('D:/01 Projects/AMAZON CATALYST PROJECT/Surgery1.mpg')
try:
if not os.path.exists('D:/01 Projects/AMAZON CATALYST PROJECT/data_surg1'):
os.makedirs('D:/01 Projects/AMAZON CATALYST PROJECT/data_surg1')
except OSError:
print ('Error: Creating directory of data_surg1')
currentFrame = 0
while(True):
# Capture frame-by-frame
if currentFrame > 0:
cap.set(cv2.CAP_PROP_POS_MSEC,currentFrame)
ret, frame = cap.read()
# Saves image of the current frame in jpg file
name = 'D:/01 Projects/AMAZON CATALYST PROJECT/data_surg1/frame' + str(currentFrame/1000) + '.jpg'
print ('Creating...' + name)
cv2.imwrite(name, frame)
# To stop duplicate images
currentFrame += 1000
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
However, I am not sure if this is saving it correctly. When I look at the frames in the file explorer, the numbers are initially very high and then reduce to form a sequential frame number compared to the previous image. I am using Python 2.7 and OpenCV3.3.
For storing from certain frames instead of a time-based save, the following script works:
import cv2
import numpy as np
import os
# Playing video from file:
cap = cv2.VideoCapture('D:/01 Projects/AMAZON CATALYST PROJECT/Surgery1.mpg')
try:
if not os.path.exists('D:/01 Projects/AMAZON CATALYST PROJECT/data_surg1'):
os.makedirs('D:/01 Projects/AMAZON CATALYST PROJECT/data_surg1')
except OSError:
print ('Error: Creating directory of data_surg1')
currentFrame = 0
while(True):
# Capture frame-by-frame
if currentFrame > 0:
cap.set(cv2.CAP_PROP_POS_FRAMES,currentFrame)
ret, frame = cap.read()
# Saves image of the current frame in jpg file
name = 'D:/01 Projects/AMAZON CATALYST PROJECT/data_surg1/frame' + str(currentFrame/1000) + '.jpg'
print ('Creating...' + name)
cv2.imwrite(name, frame)
# To stop duplicate images
currentFrame += 1
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()