Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python opencv cv2.VideoCapture.read() getting stuck indefinitely after running the first time

I am using opencv on python and I'm facing an issue where the cv2.VideoCapture.read() function gets stuck. Here's some prototype code:

requirements.txt

opencv-contrib-python==4.1.1.26

application.py

import cv2

def run_analysis(path_to_video):
    vs = cv2.VideoCapture(path_to_video)

    while True:
         frame = vs.read()
         if frame is None:
             break
         do_stuff_with_frame(frame)

    vs.release()

This code works all the time on my mac. It works only the first time around when I deploy it as a Flask app to Elastic Beanstalk (runs on Red Hat Linux). I've seen some stuff in github issues that might suggest that vs.release() fails to release the file pointer, or that there's a memory leak, but I'm not too well versed in these concepts.

Even if I can't get an answer for why, I'd be happy with a brute force way of making it work.

like image 684
Alexander Soare Avatar asked Nov 29 '19 10:11

Alexander Soare


People also ask

What is VideoCapture in cv2?

Capture Video from Camera OpenCV allows a straightforward interface to capture live stream with the camera (webcam). It converts video into grayscale and display it. We need to create a VideoCapture object to capture a video. It accepts either the device index or the name of a video file.

What does cv2 VideoCapture return?

The VideoCapture class returns a video capture object which we can use to display the video. The class has several methods, for example, there is the get() method which takes a property identifier from cv2.

What does VideoCapture read do?

VideoCapture – Creates a video capture object, which would help stream or display the video. cv2. VideoWriter – Saves the output video to a directory.


2 Answers

You can add guards to ensure that the cv2.VideoCapture() handler object is valid with isOpened(). In addition, you can check the status return value from read() to ensure that the frame is valid. Also ensure that the path given to the handler is valid.

import cv2

def run_analysis(path_to_video):
    cap = cv2.VideoCapture(path_to_video)

    if not cap.isOpened():
        print("Error opening video")

    while(cap.isOpened()):
        status, frame = cap.read()
        if status:
            cv2.imshow('frame', frame)
            # do_stuff_with_frame(frame)
        key = cv2.waitKey(25)
        if key == ord('q'):
            break

if __name__ == "__main__":
    run_analysis('video.mp4')
like image 82
nathancy Avatar answered Oct 07 '22 18:10

nathancy


According to openCV web site

If no frames has been grabbed (camera has been disconnected, or there are no more frames in video file), the methods return false and the functions return NULL pointer.

you could test to see if 'frame' is false after you test it for 'None'. If in doubt, 'print(frame)'

Edit:
I just realized your skipping the most important step with opening a file. Need to check if it opened with isOpened()

    vs = cv2.VideoCapture(path_to_video)
    if not vs.isOpened():
        print("Error: Could not open file: %s" % (path_to_video))
        return
    ........

Edit: Try this code. By expanded the vs.read() it becomes a little more clear as to what it is returning.

import cv2
def do_stuff_with_frame(image):
    pass

def run_analysis(path_to_video):
    vs = cv2.VideoCapture(path_to_video)
    if not vs.isOpened():
        print("Error: Could not open file: %s" % (path_to_video))
        return

    while True:
        retval, image = vs.read()
        if not retval:
            print("Video file finished. Total Frames: %d" % (vs.get(cv2.CAP_PROP_FRAME_COUNT)))
            break
        do_stuff_with_frame(image)

    vs.release()

# START OF PROGRAM
if __name__ == "__main__":
    run_analysis("test.mov")
like image 2
ron Avatar answered Oct 07 '22 18:10

ron