0

When testing the video playback example from the OpenCV introductory video tutorial, my videos (.m4v and .mov) always freeze for a little bit after they are done and then throws this error message:

---------------------------------------------------------------------------
error                                     Traceback (most recent call last)
<ipython-input-33-6ff11ed068b5> in <module>()
     15 
     16     # Our operations on the frame come here
---> 17     gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
     18 
     19     # Display the resulting frame

error: /home/user/opencv-2.4.9/modules/imgproc/src/color.cpp:3737: error: (-215) scn == 3 || scn == 4 in function cvtColor

My interpretation is that this is because the last frame will be empty and lack the channels that cvtColor() expects and the image can therefore not be displayed. If I modify the example code slightly and replace the while(True) with a for loop that ends after the last frame in the video, I get no such message and the video window closes instead of freezing.

However, I assume there is a reason to why this is not the default behaviour in OpenCV and I'm afraid my modification will screw something up further down the road (completely new to OpenCV). So now I would like input on a few things:

  1. Why is the while(True) the default for showing the video, since it is freezing and throwing an error message (if this is not unique to my setup)?
  2. Is it safe to have the for loop or should I stick to while(True) and wait for the error message every time I play a video?
  3. Is there a preferred way to have OpenCV exit video playback gracefully?

I have tried the suggestions here and they did help with not freezing up the kernel completely, but the video still freezes and the error message still shows. The for loop alternative seems smoother.

I'm using the Ipython Notebook with Python 2.7.9 and OpenCV 2.4.9 on Ubuntu 14.04. Below is the code I'm executing.

import cv2

video_name = '/path/to/video'
cap = cv2.VideoCapture(video_name)

# while(True): #causes freeze and throws error
for num in range(0,int(cap.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT))):
    # Capture frame-by-frame
    ret, frame = cap.read()

    # Our operations on the frame come here
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # Display the resulting frame
    cv2.imshow('frame',gray)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
Community
  • 1
  • 1
joelostblom
  • 43,590
  • 17
  • 150
  • 159
  • yeah, tried ogv, mp4 and avi since I posted. All give the same error message. I'm using the Ipython Notebook in case that matters, I'll add that to the question. – joelostblom Jan 10 '15 at 23:33
  • After the error message is thrown, I have to force close the video as well. I can also rerun the script and the frozen video will come alive and start playing again. I installed python through anaconda and opencv from source after [these instructions](http://www.samontab.com/web/2014/06/installing-opencv-2-4-9-in-ubuntu-14-04-lts/). I guess this is not a huge issue, but I am curious to why it happens and would like to get rid of it if possible. – joelostblom Jan 11 '15 at 00:34
  • Yeah, I tried running from the ipython console in spyder and encountered the same error. Could it be due to my camera driver even though I'm not capturing from the camera? – joelostblom Jan 11 '15 at 00:41

1 Answers1

0

Since I ended up wanting to loop the video at some occasions, the following proved to be the best solution for me.

import numpy as np
import cv2

cap = cv2.VideoCapture('/path/to/vid.mp4') 
frame_counter = 0
loop = True
while(True):
    # Capture frame-by-frame
    ret, frame = cap.read()
    # Our operations on the frame come here
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    # Display the resulting frame
    cv2.imshow('frame',gray)
    frame_counter += 1
    if frame_counter == cap.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT):
        if loop == True:
            frame_counter = 0
            cap = cv2.VideoCapture(video_name)
        else:
            break
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()

If you don't need to loop you videos just use

if frame_counter == cap.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT):
    break

or Padraic's solution (slightly modified)

try:
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
except cv2.error:
    break

The try/except statement does give a short delay where the video freezes before closing. The if statement closes it immediately when playback is finished.

I am still interested if someone can explain while the error message is encountered in the first place since padraic said this is not the case on his machine.

EDIT: So I noticed I misread the tutorial and should use while(cap.isOpened()) instead of while(True), but I still get the same error with while(cap.isOpened()).

joelostblom
  • 43,590
  • 17
  • 150
  • 159