Error in Writing Video with OpenCV for Video Classification - python

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)

Related

How to read grayscale img from a video with OpenCV?

I read all pictures from my pic directory and then convert them each to gray-scale with canny edge detections before writing it all to a video.
But, when I use my video software to play it, it shows a green background, and I can't read video frames from it. Could someone show me how to solve it?
Sample code
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
fourcc = cv.VideoWriter_fourcc(*"I420")
out = cv.VideoWriter("t2.avi", fourcc, 1, (640, 480), 0)
for pic in glob.glob1("./pic/", "A*"):
img = cv.imread(f"./pic/{pic}", -1)
edge = cv.Canny(img, 100, 200)
edge = cv.resize(edge, (640, 480))
out.write(edge)
out.release()
# Cant read video frame here:
cap = cv.VideoCapture("t2.avi")
ret, frame = cap.read()
if ret:
plt.imshow(frame)
else:
print("end")
cap.release()
Video plays with green background
It looks like a compatibility issue between I420 FOURCC and Grayscale format.
Replace fourcc = cv.VideoWriter_fourcc(*"I420") with:
fourcc = cv.VideoWriter_fourcc(*"GREY")
Note:
I am using OpenCV 4.5.5 in Windows 10, and it's working with "GREY".
I am not sure it's going to work in all platforms and versions.
I420 applies colored video.
You may use I420 with colored video:
Replace out = cv.VideoWriter("t2.avi", fourcc, 1, (640, 480), 0) with:
out = cv.VideoWriter("t2.avi", fourcc, 1, (640, 480), 1)
Convert edge to BGR before writing:
edge = cv.cvtColor(edge, cv.COLOR_GRAY2BGR)
out.write(edge)
Code sample using "GREY" FOURCC:
import numpy as np
import cv2 as cv
#import matplotlib.pyplot as plt
import glob
#fourcc = cv.VideoWriter_fourcc(*"I420")
fourcc = cv.VideoWriter_fourcc(*"GREY")
out = cv.VideoWriter("t2.avi", fourcc, 1, (640, 480), 0)
for pic in glob.glob1("./pic/", "A*"):
img = cv.imread(f"./pic/{pic}", -1)
edge = cv.Canny(img, 100, 200)
edge = cv.resize(edge, (640, 480))
out.write(edge)
out.release()
# Cant read video frame here:
cap = cv.VideoCapture("t2.avi")
while True:
ret, frame = cap.read()
if ret:
#plt.imshow(frame)
cv.imshow('frame', frame)
cv.waitKey(1000)
else:
print("end")
cap.release()
break
cv.destroyAllWindows()

Cannot read the output video after using CV2 Video Writer

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 ))

How to make OpenCv on Python play video that is already played from web cam?

Essentially I need a loop inside of a loop, so the live-video could be played using another live-video as a reference. Is it, for example, possible to save video on hardware and then play it from there in real time? If yes, then how? I have a code with an attempt to meake something similar below. ORB detector shouldn`t affect the process.
import cv2
width = 640
height = 480
cap = cv2.VideoCapture(0)
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('output.avi', fourcc, 20.0, (640, 480))
while True:
frame_read = cap
(ret, myFrame) = cap.read()
img = cv2.resize(myFrame, (width, height))
orb = cv2.ORB_create()
kp = orb.detect(img, None)
(kp, des) = orb.compute(img, kp)
img2 = cv2.drawKeypoints(img, kp, img, color=(0xFF, 0, 0xFF))
img2 = cv2.flip(img2, 0)
out.write(img2)
cv2.imshow('test', img2)
while True:
test = cap.open('output.avi')
frame_read = test
(ret, kpFrame) = test.read()
img3 = cv2.resize(kpFrame, (width, height))
cv2.imshow('test2', img3)
if cv2.waitKey(1) & 0xFF == ord('q'):
break

How to solve Opencv VideoWriter issues with global variables

I'mm writing this piece of python to display a stream of video from my webcam while at the same time record the video - which I've got working, however I've grayscaled the video streaming to my screen and time stamped it - but my recorded video is in colour! I've included the code below - I've tried using some global variables but nothing worked - any help, greatly appreciated
import cv2
import numpy as np
import time, datetime
import os
genericfilename = "recording"
filetime = str(time.time())
extension = '.avi'
filename = genericfilename + filetime +extension
frames_per_second = 100
res = '720p'
print("NEW FILE NAME: " + filename)
# Set resolution for the video capture
def change_res(cap, width, height):
cap.set(3, width)
cap.set(4, height)
# Standard Video Dimensions Sizes
STD_DIMENSIONS = {
"480p": (640, 480),
"720p": (1280, 720),
"1080p": (1920, 1080),
"4k": (3840, 2160),
}
# grab resolution dimensions and set video capture to it.
def get_dims(cap, res='1080p'):
width, height = STD_DIMENSIONS["480p"]
if res in STD_DIMENSIONS:
width,height = STD_DIMENSIONS[res]
## change the current caputre device
## to the resulting resolution
change_res(cap, width, height)
return width, height
# Video Encoding, might require additional installs
VIDEO_TYPE = {
'avi': cv2.VideoWriter_fourcc(*'XVID'),
#'mp4': cv2.VideoWriter_fourcc(*'H264'),
'mp4': cv2.VideoWriter_fourcc(*'XVID'),
}
def get_video_type(filename):
filename, ext = os.path.splitext(filename)
if ext in VIDEO_TYPE:
return VIDEO_TYPE[ext]
return VIDEO_TYPE['avi']
capture = cv2.VideoCapture(0)
out = cv2.VideoWriter(filename, get_video_type(filename), 60,
get_dims(capture, res))
while(True):
ret, frame = capture.read()
out.write(frame)
grayFrame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
font = cv2.FONT_ITALIC = 1
cv2.putText(grayFrame, str(datetime.datetime.now()), (-330, 460), font, 3,
(200, 200, 200), 2, cv2.LINE_AA)
cv2.imshow('combilift output', grayFrame)
# Press Q on keyboard to exit
if cv2.waitKey(1) & 0xFF == ord('q'):
break
if cv2.waitKey(1) & 0xFF == ord('r'):
print(datetime.datetime.now())
capture.release()
out.release()
cv2.destroyAllWindows()
You save the frame to video, then convert frame to gray.
out.write(frame)
grayFrame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
If you want your recorded video to be gray, maybe reverse the order of operations and save grayFrame?
grayFrame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
out.write(grayFrame)
If you want to also save the texts, put the text before writing frame to output.
Lets take a look at ur code
out = cv2.VideoWriter(filename, get_video_type(filename), 60,
.....
while(True):
ret, frame = capture.read()
out.write(frame)
grayFrame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
You first save out then convert color
The correct sequence should be
out = cv2.VideoWriter(filename, get_video_type(filename), 60,
.....
while(True):
ret, frame = capture.read()
grayFrame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
out.write(grayFrame)
I don't have data to test. Just in case you experience some issue with channels. You can use opencv merge(grayFrame,grayFrame,grayFrame) to create a normal 3 channel grey scale image and save to video

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