How to write video then download using cv2 in Google colab? - opencv

I am trying to do some image processing on a video, then save the resulting video using opencv on colab. However, I am not able to access the resulting video file that I am writing to.
import cv2
from google.colab.patches import cv2_imshow
import numpy as np
fourcc = cv2.VideoWriter_fourcc(*'H264')
cap = cv2.VideoCapture(vid_file)
out = cv2.VideoWriter('output.mp4',fourcc,30.0,(1124,1080))
cnt = 0
ret = True
while(ret):
ret,frame = cap.read()
print(cnt,end=' ')
# check if prey was tracked on this frame
match = np.where(prey_frames==cnt)[0]
if match:
prey_frame = match[0]
# print(prey_frame)
image = cv2.circle(frame,(int(prey_px[prey_frame].x),95+int(prey_px[prey_frame].y)),
radius=5,color=(255,0,255),thickness=2)
else:
image = frame
out.write(image)
cnt += 1
out.release()
cap.release()
cv2.destroyAllWindows()
From what I understand, this should write to a file called 'output.mp4'. This code runs without error, but there is no file in the current directory, and no file of that name available to download (using files.download('output.mp4') returns 'cannot find file' error).
Any help would be appreciated!

I've hit this problem a few times and I believe that it has to do with the fact that Colab's operating environment only supports a few video encodings.
I was able to get the video writer working with the following:
fourcc = cv2.VideoWriter_fourcc('F','M','P','4')

Related

I am getting an error while trying to vonvert a bgr image to gray scale [duplicate]

This question already has answers here:
How to load a video in opencv(python)
(5 answers)
Closed 1 year ago.
I am reading a video here:
VideoCap = cv2.VideoCapture("E:\Omar's Stuff\College related\Forth Year\Project\Kalman Filter
code\video_randomball.avi")
ret, frame = VideoCap.read()
and sending the frames to a detect function here:
# Detect object
centers = detect(frame,debugMode)
trying to convert here:
def detect(frame,debugMode):
# Convert frame from BGR to GRAY
#frame = frame.astype('uint8')
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
and getting this error:
OpenCV(3.4.2) c:\projects\opencv-python\opencv\modules\imgproc\src\color.hpp:253: error:
(-215:Assertion failed) VScn::contains(scn) && VDcn::contains(dcn) && VDepth::contains(depth) in
function 'cv::CvtHelper<struct cv::Set<3,4,-1>,struct cv::Set<1,-1,-1>,struct
cv::Set<0,2,5>,2>::CvtHelper'
how to fix it?
Something wrong with the video file path that you have passed in cv2.VideoCapture() method so try to correct the path and if not able to correct then simply drag and drop the video file along with the python script folder then it will work.
Here is sample code to read the video in the same directory where the python script is located
import cv2
import numpy as np
# Create a VideoCapture object and read from input file
cap = cv2.VideoCapture('tree.mp4')
# Check if camera opened successfully
if (cap.isOpened()== False):
print("Error opening video file")
# Read until video is completed
while(cap.isOpened()):
# Capture frame-by-frame
ret, frame = cap.read()
if ret == True:
# Display the resulting frame
cv2.imshow('Frame', frame)
# Press Q on keyboard to exit
if cv2.waitKey(25) & 0xFF == ord('q'):
break
# Break the loop
else:
break
# When everything done, release
# the video capture object
cap.release()
# Closes all the frames
cv2.destroyAllWindows()

OpenCV 4.1.1.26 reports 90000.0 fps for a 25fps RTSP stream

I have an RTP/RTSP stream that's running at 25fps, as verified by ffprobe -i <URI>. Also, VLC plays back the RTSP stream at a real-time rate, but doesn't show me the FPS in the Media Information window.
However, when I use OpenCV 4.1.1.26 to retrieve the input stream's frame rate, it is giving me a response of 90000.0.
Question: How can I use OpenCV to probe for the correct frame rate of the RTSP stream? What would cause it to report 90000.0 instead of 25?
Here's my Python function to retrieve the frame rate:
import cv2
vid : cv2.VideoCapture = cv2.VideoCapture('rtsp://192.168.1.10/cam1/mpeg4')
def get_framerate(video: cv2.VideoCapture):
fps = video.get(cv2.CAP_PROP_FPS)
print('FPS is {0}'.format(fps))
get_framerate(vid)
MacOS Catalina
Python 3.7.4
I hope this helps you somehow. It is a simple calculator that takes cont captures and measure the beginning and the ending time. Then with the rule of three, i converted it to fps.
Related to you second question i read here that it could be due to bad installation. Also, you can check that your camera is working properly by printing ret variable. If it is true then you should be able to see the fps, if it is false then you can have an unpredictable result.
cv2.imshow() and key = cv2.waitKey(1) should be commented as it adds ping/delay resulting in bad measurement.
I post this as a comment because i do not have enough reputation points.
img = cv2.VideoCapture('rtsp://192.168.1.10/cam1/mpeg4')
while True:
if cont == 50:
a = datetime.now() - start
b = (a.seconds * 10e6 + a.microseconds)
print((a.seconds * 10e6 + a.microseconds), "fps = ", (50 * 10e6)/ b)
break
ret, frame = img.read()
# Comment for best test
cv2.imshow('fer', frame)
key = cv2.waitKey(1)
if key == ord('q'):
break
cont+=1
img.release()
cv2.destroyAllWindows()`

How do I configure while loop to use picamera?

So I want to read individual frames of picamera using while loop. Here is what I found for doing it using for loop:
# import the necessary packages
from picamera.array import PiRGBArray
from picamera import PiCamera
import time
import cv2
# initialize the camera and grab a reference to the raw camera capture
camera = PiCamera()
camera.resolution = (640, 480)
camera.framerate = 32
rawCapture = PiRGBArray(camera, size=(640, 480))
# allow the camera to warmup
time.sleep(0.1)
# capture frames from the camera
for frame in camera.capture_continuous(rawCapture, format="bgr", use_video_port=True):
# grab the raw NumPy array representing the image, then initialize the timestamp
# and occupied/unoccupied text
image = frame.array
# show the frame
cv2.imshow("Frame", image)
key = cv2.waitKey(1) & 0xFF
# clear the stream in preparation for the next frame
rawCapture.truncate(0)
# if the `q` key was pressed, break from the loop
if key == ord("q"):
break
cv2.destroyAllWindows()
Now when I use the above code, I get the video feed but I am planning to do the same using a while loop. Going from the same logic I added a while loop something like this:
while True: frame1=camera.capture_continious(rawCapture,format="bgr",use_video_port=True)
image1 = frame1.array
# show the frame
cv2.imshow("Frame1", image1)
# clear the stream in preparation for the next frame
rawCapture.truncate(0)
But still I am getting an error as frame1 is a generator and doesn't contain such attributes while the same code is running well with for loop. What modifications can I make?
The function capture_continuous() returns an infinite iterator of images captured continuously from the camera. It does not return a single image. That's is why it does work with a for loop.
In your while loop you should use the capture() function, which does return an image.
You can (and should ;) ) read more about it in this documentation

tesseract not able to read all digits accurately

I'm using Tesseract to recognize numbers from images of a screen taken with a phone camera. I've done some preprocessing of the image: processed image, and using Tesseract, I'm able to get some mixed results. Using the following code on the above images, I get the following output: "EOE". However, with this image, processed image, I get an exact match: "39:45.8"
import cv2
import pytesseract
from PIL import Image, ImageEnhance
from matplotlib import pyplot as plt
orig_name = "time3.jpg";
image_name = "time3_.jpg";
img = cv2.imread(orig_name, 0)
img = cv2.medianBlur(img, 5)
img_th = cv2.adaptiveThreshold(img, 255,\
cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY, 11, 2)
cv2.imshow('image', img_th)
cv2.waitKey(0)
cv2.imwrite(image_name, img_th)
im = Image.open(image_name)
time = pytesseract.image_to_string(im, config = "-psm 7")
print(time)
Is there anything I can do to get more consistent results?
I did three additional things to get it correct for the first Image.
You can set a whitelist for Tesseract. In your case we know that
there will only charachters from this List 01234567890.:. This
improves the accuracy significantly.
I resized the image to make it easier for tesseract.
I switched from psm mode 7 to 11 (Recoginze as much as possible)
Code:
import cv2
import pytesseract
from PIL import Image, ImageEnhance
orig_name = "./time1.jpg";
img = cv2.imread(orig_name)
height, width, channels = img.shape
imgResized = cv2.resize(img, ( width*3, height*3))
cv2.imshow("img",imgResized)
cv2.waitKey()
im = Image.fromarray(imgResized)
time = pytesseract.image_to_string(im, config ='--tessdata-dir "/home/rvq/github/tesseract/tessdata/" -c tessedit_char_whitelist=01234567890.: -psm 11 -oem 0')
print(time)
Note:
You can use Image.fromarray(imgResized) to convert an opencv image to a PIL Image. You don't have to write to disk and read it again.

opencv and python 3 -- cannot write video frames to disk

Python 3.5.2, anaconda 4.2.0 on Windows 10.
OpenCV installed from conda, version 3.1.0.
I'm trying to process a video file by opening it, transforming each frame, and putting the result into a new video file. The output file is created, but the size is about 800 bytes and its empty. The input file has ~4,000 frames and it's about 150 MB.
Here's my code, which follows the guide on the OpenCV documentation pretty closely.
import cv2
import progressbar
# preprocess video
# args.input is a valid file name
outname = 'foo.mp4'
cap = cv2.VideoCapture(args.input)
codec = int(cap.get(cv2.CAP_PROP_FOURCC))
framerate = app_config.camera.framerate #240
size = (app_config.camera.width, app_config.camera.height) #1080 x 720
vw = cv2.VideoWriter(filename=outname, fourcc=codec, fps=framerate, frameSize=size, isColor=False)
curframe = 0
with progressbar.ProgressBar(min_value=0, max_value=int(cap.get(cv2.CAP_PROP_FRAME_COUNT))) as pb:
while cap.isOpened():
ret, frame = cap.read()
if ret:
#update the progress bar
curframe += 1
pb.update(curframe)
# convert to greyscale
grey = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# invert colors
inverted = cv2.bitwise_not(grey)
vw.write(inverted)
#cv2.imshow('right', right)
#if cv2.waitKey(1) & 0xFF == ord('q'):
# break
else:
break
cap.release()
vw.release()
cv2.destroyAllWindows()
I receive the following error:
OpenCV: FFMPEG: tag 0x7634706d/'mp4v' is not supported with codec id 13 and format 'mp4 / MP4 (MPEG-4 Part 14)'
OpenCV: FFMPEG: fallback to use tag 0x00000020/' ???'
I receive similar errors (as well as a warning that I have an incorrect environment variable for h.264 library path) if i try to set codec = cv2.VideoWriter_fourcc(*'H264').
Ensure that the dimensions of inverted match the dimensions of the size parameter in the videoWriter definition.
Also use 'M','P','4','V' codec with the .mp4 container.

Resources