Cannot read the output video after using CV2 Video Writer - python

I didn't managed to open the .avi file after i have performed videowrite.cv2.
Is there any way to solve the issues?
Able to write but not able to read as it said corrupted data.
Below is the sample code
:
day_video = cv2.VideoCapture('/content/gdrive/Shareddrives/Computer Vision/Assignment 2/Q1_day_video.avi')
check, frame = day_video.read()
height, width, _ = frame.shape
fourcc = cv2.VideoWriter_fourcc(*'MJPG')
out = cv2.VideoWriter('output_day.avi', fourcc, 20, (height, width))
while day_video.isOpened():
check, frame = day_video.read()
if not check:
out.release()
break
new_output = lines_highlighted_day(frame)
out.write(new_output)
out.release()

Change the height & video in this line
out = cv2.VideoWriter('output_day.avi', fourcc, 20, (height, width))
to
out = cv2.VideoWriter('output_day.avi', fourcc, 20, (width, height ))

Related

Error in Writing Video with OpenCV for Video Classification

I am building a video classification model same as in this video: https://www.youtube.com/watch?v=l8XQsxlGxiY&list=PLxefhmF0pcPl_v-lLsqF3drP6NOoSYJR0&index=9
The model predicts which sport is being shown in the video: Tennis, swimming or Boxing.
I already built my model and has a 96% accuracy.
Now, I have a sample video to test my model.
from keras.models import load_model
from collections import deque
import numpy as np
import pickle
import cv2
model = load_model(r"C:\Users\yudishteer.c\Desktop\VideoClassification\video_classification_model\videoclassificationModel")
lb = pickle.loads(open(r"C:\Users\yudishteer.c\Desktop\VideoClassification\video_classification_model\videoclassificationBinarizer.pickle", "rb").read())
outputvideo = r"C:\Users\yudishteer.c\Desktop\VideoClassification\video_classification_model\outputvideo\demo_output.avi"
mean = np.array([123.68, 116.779, 103.939], dtype = "float32")
Queue = deque(maxlen=128)
capture_video=cv2.VideoCapture(r"C:\Users\yudishteer.c\Desktop\VideoClassification\video_classification_model\demo_video.mp4")
writer = None
(Width, Height) = (None, None)
while True:
(taken, frame) = capture_video.read()
if not taken:
break
if Width is None or Height is None:
(Width, Height) = frame.shape[:2]
output = frame.copy()
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
frame = cv2.resize(frame, (224,224)).astype("float32")
frame -= mean
preds = model.predict(np.expand_dims(frame, axis=0))[0]
Queue.append(preds)
results = np.array(Queue).mean(axis = 0)
i = np.argmax(results)
label = lb.classes_[i]
text = "The game is {}".format(label)
cv2.putText(output, text, (45,60), cv2.FONT_HERSHEY_SIMPLEX, 1.25, (255,0,0),5)
if writer is None:
fourcc = cv2.VideoWriter_fourcc(*'MJPG')
writer = cv2.VideoWriter('demo_output.mp4', fourcc, 10, (Width, Height), True)
writer.write(output)
cv2.imshow("In progress", output)
key = cv2.waitKey(1) & 0xFF
if key == ord("q"):
break
print("Finalizing.......")
writer.release()
capture_video.release()
# Closes all the frames
cv2.destroyAllWindows()
When I run the above code, I can see it being classified correctly. 
That is, the demo video(demo_video.mp4) is opened and I can see either swimming, tennis, or boxing being displayed at the top of the video depending on the sport being shown.
However, since I have a:
writer = cv2.VideoWriter(‘demo_output.mp4’, fourcc, 10, (Width, Height), True)
When I open my demo_output.mp4 (or even avi), I get:
Can someone help what is wrong?
thanks!
You have mixed Width and Height...
Instead of (Width, Height) = frame.shape[:2], it should be:
(Height, Width) = frame.shape[:2]
In my system, I am getting the following warning:
OpenCV: FFMPEG: tag 0x47504a4d/'MJPG' is not supported with codec id 7 and format 'mp4 / MP4 (MPEG-4 Part 14)'
OpenCV: FFMPEG: fallback to use tag 0x7634706d/'mp4v'
The result is a black video.
One of the following combinations of codec/container works:
'MJPG' FOURCC and AVI container:
fourcc = cv2.VideoWriter_fourcc(*'MJPG')
writer = cv2.VideoWriter('demo_output.avi', fourcc, 10, (Width, Height), True)
'mp4v' FOURCC and MP4 container:
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
writer = cv2.VideoWriter('demo_output.mp4', fourcc, 10, (Width, Height), True)

Why are my video files getting bigger after converting to np.array?

I have video files around 700x200, and I'm using cv2 to perform preprocessing. The actual videos are .mp4 format and range from a couple mb depending on the length, but after scaling down the resolution, making the color videos grey, somehow my filesize almost 10x when I try to either save via Pickle or np.save.
Preprocessing code is:
def save_video(link):
frames = []
# Creating a VideoCapture object to read the video
# cap = cv2.VideoCapture('video.mp4')
cap = cv2.VideoCapture(link)
frameCount = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
frameWidth = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frameHeight = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
buf_c = np.empty((frameCount, frameHeight, frameWidth, 3), np.dtype('uint8'))
buf = np.empty((frameCount, frameHeight, frameWidth), np.dtype('uint8'))
fc = 0
ret = True
# Resolution reduction
scale_percent = 30 # percent of original size
width = int(buf.shape[2] * scale_percent / 100)
height = int(buf.shape[1] * scale_percent / 100)
dim = (width, height)
while (fc < frameCount and ret):
ret, buf_c[fc] = cap.read()
buf[fc] = cv2.cvtColor(buf_c[fc], cv2.COLOR_BGR2GRAY)
resized = cv2.resize(buf[fc], dim, interpolation = cv2.INTER_AREA)
frames.append(resized)
fc += 1
cap.release()
cv2.destroyAllWindows()
return frames // or np.asarray(frames)
dimensions for video files as examples (after processing):
(844, 216, 121) (so 844 frames of 216x121 after scaling down)
(788, 216, 121)
Actual video files are 1-2MB before any preprocessing and the resulting pkl or npy are 10x+ in size. Is this what is supposed to happen?
A compressed video stream is decompressed by OpenCV and is saved as raw data. To reduce the size you need to encode the video stream. For example:
def opencv_replay(video_file: str, video_file_out: str):
import cv2
video_in = cv2.VideoCapture(video_file)
video_out = cv2.VideoWriter()
assert (video_out.open(
video_file_out,
cv2.VideoWriter_fourcc('a', 'v', 'c', '1'),
video_in.get(cv2.CAP_PROP_FPS),
(int(video_in.get(cv2.CAP_PROP_FRAME_WIDTH)), int(video_in.get(cv2.CAP_PROP_FRAME_HEIGHT)))
))
while True:
res, frame = video_in.read()
if not res:
break
video_out.write(frame)
avc1 is used for h264 encoding in Linux.

Saving video from frames in with fourcc codec h264 and h265 with opencv

I am saving frames from live stream to a video with h264 codec. I tried this with openCV (versions 3.4 and 4.4) in python but I am not able to save it. I can save video in XVID and many other codecs but I am not successful in h264 and h265.
I am using windows opencv 4.4 in Python.
My sample code is as follow
cap = cv2.VideoCapture(0)
while(cap.isOpened()):
ret,frame = cap.read()
if ret == True:
width = int(cap.get(3)) # float
height = int(cap.get(4)) # float
# fourcc = int(cap.get(cv2.CAP_PROP_FOURCC))
fourcc = cv2.VideoWriter_fourcc(*'H264')
out = cv2.VideoWriter(filename, fourcc, 30, (width,height))
out.write(frame)
out.release()
Can anyone help me how can I save video in h264 and h265.
You are recreating the VideoWriter at each frame which in the end only stores a single frame. You need to create the writer first, write the frames to it in the loop then terminate it after you're finished with the video. As a precaution you'll also want to break out of the loop if we detect any problems in the video when you read a frame. To make sure you do this right, let's read in the first frame, set up the VideoWriter then only write to it once we've established its creation:
cap = cv2.VideoCapture(0)
out = None
while cap.isOpened():
ret, frame = cap.read()
if ret == True:
if out is None:
width = int(cap.get(3)) # float
height = int(cap.get(4)) # float
fourcc = cv2.VideoWriter_fourcc(*'H264')
out = cv2.VideoWriter(filename, fourcc, 30, (width, height))
else:
out.write(frame)
else:
break
if out is not None:
out.release()

Write 2 images into a video using OpenCV (Python) of 10 seconds duration

I am trying to take 2 images present in a local folder and use OpenCV's Videowriter function to create a video from these images.
I am using FrameRate of 1. So this creates a video of 2 seconds duration. Below is the code (I got it from here):
import cv2
import os
image_folder = 'images'
video_name = 'video.avi'
images = [img for img in os.listdir(image_folder) if img.endswith(".png")]
frame = cv2.imread(os.path.join(image_folder, images[0]))
height, width, layers = frame.shape
video = cv2.VideoWriter(video_name, 0, 1, (width,height))
for image in images:
video.write(cv2.imread(os.path.join(image_folder, image)))
cv2.destroyAllWindows()
video.release()
Goal: I want to create a video of 10 seconds which will have these 2 images each being displayed for 5 seconds.
I think there might be a similar question like this in the forum but I am not able to find it. If someone can point me to the solution, it would be great.
Thank you.
The below code snippet should solve your problem. Notice that you will have to specify each_image_duration. I used this variable to write the each image in the video for a specific duration. For this use case, you have to keep the fps as 1.0, so each video frame will be displayed for 1.0 sec. This makes the 3rd argument in cv2.Videowriter.
import cv2
import os
image_folder = 'images'
video_name = 'video.avi'
each_image_duration = 5 # in secs
fourcc = cv2.VideoWriter_fourcc(*'XVID') # define the video codec
images = [img for img in os.listdir(image_folder) if img.endswith(".png")]
frame = cv2.imread(os.path.join(image_folder, images[0]))
height, width, layers = frame.shape
video = cv2.VideoWriter(video_name, fourcc, 1.0, (width, height))
for image in images:
for _ in range(each_image_duration):
video.write(cv2.imread(os.path.join(image_folder, image)))
cv2.destroyAllWindows()
video.release()
Here you can calculate fps dynamically based on how many frames you have and how many seconds of video you want to make.
See code below:
import cv2
import os
image_folder = 'images'
video_name = 'video.avi'
fourcc = cv2.VideoWriter_fourcc(*'XVID') # define the video codec
images = [img for img in os.listdir(image_folder) if img.endswith(".png")]
img_count = len(images)
video_secs = 10
frame = cv2.imread(os.path.join(image_folder, images[0]))
height, width, layers = frame.shape
video = cv2.VideoWriter(video_name, fourcc, float(img_count/video_secs), (width, height))
for image in images:
video.write(image)
cv2.destroyAllWindows()
video.release()

OpenCV MP4 Creation

I've been trying to trying to write MP4 video files using OpenCV, in python.
AVI creation works fine, both on linux and windows, when I use both:
out = cv2.VideoWriter('x.avi', 0, 30, (640, 480))
and
fourcc = cv2.VideoWriter_fourcc(*"XVID")
out = cv2.VideoWriter('x.avi', fourcc, 30, (640, 480))
and even
fourcc = cv2.VideoWriter_fourcc(*"XVID")
out = cv2.VideoWriter('x', fourcc, 30, (640, 480))
.
When I try to save an MP4 however nothing ever saves - using:
fourcc = cv2.VideoWriter_fourcc(*"H264")
out = cv2.VideoWriter('x.mp4', fourcc, 30, (640, 480))
and
fourcc = cv2.VideoWriter_fourcc(*"AVC1")
out = cv2.VideoWriter('x.mp4', fourcc, 30, (640, 480))
No errors occur, just nothing saves.
I've tried everything over the past few days, doing everything to avoid creating the AVI and then converting it to MP4 using ffmpeg as I find that to be horrible practice.
cap = cv2.VideoCapture(0)
cap.set(3,640)
cap.set(4,480)
fourcc = cv2.VideoWriter_fourcc(*'MP4V')
out = cv2.VideoWriter('output.mp4', fourcc, 20.0, (640,480))
while(True):
ret, frame = cap.read()
out.write(frame)
cv2.imshow('frame', frame)
c = cv2.waitKey(1)
if c & 0xFF == ord('q'):
break
cap.release()
out.release()
cv2.destroyAllWindows()
Give right values of the high and width of the frames:
import cv2
print ('Press [ESC] to quit demo')
# Read from the input video file
# input_file = 'Your path to input video file'
# camera = cv2.VideoCapture(input_file)
# Or read from your computer camera
camera = cv2.VideoCapture(0)
# Output video file may be with another extension, but I didn't try
# output_file = 'Your path to output video file' + '.avi'
output_file = "out.avi"
# 4-byte code of the video codec may be another, but I did not try
fourcc = cv2.VideoWriter_fourcc(*'DIVX')
is_begin = True
while camera.isOpened():
_, frame = camera.read()
if frame is None:
break
# Your code
processed = frame
if is_begin:
# Right values of high and width
h, w, _ = processed.shape
out = cv2.VideoWriter(output_file, fourcc, 30, (w, h), True)
print(out.isOpened()) # To check that you opened VideoWriter
is_begin = False
out.write(processed)
cv2.imshow('', processed)
choice = cv2.waitKey(1)
if choice == 27:
break
camera.release()
out.release()
cv2.destroyAllWindows()
This code works for me.

Categories