Search code examples
pythonopencvvideo-processing

Can't open saved video using OpenCV in Python (Windows 10)


Code reads the train1.mov file, shows cv2.imshow('res', res) also saves a file named output.avi. Problem is, output.avi is around 40 kb and empty. But cv2.imshow('res', res) shows the whole video. Then show the following error.

Python Code:

import numpy as np
import cv2

cap = cv2.VideoCapture('C:\\Users\\khan1\\Desktop\\python project\\color_threshold\\train1.mov')

fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('C:\\Users\\khan1\\Desktop\\python project\\color_threshold\\output.avi',fourcc, 20.0, (640,480))

while(cap.isOpened()):
    _, frame = cap.read()

    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    lower_green = np.array([40, 60, 60]) 
    upper_green = np.array([80, 255, 255])

    mask = cv2.inRange(hsv, lower_green, upper_green)
    mask = cv2.GaussianBlur(mask, (7, 7), 0)
    res = cv2.bitwise_and(frame, frame, mask=mask)

    out.write(res)

    cv2.namedWindow("res", cv2.WINDOW_NORMAL)
    cv2.imshow('res', res)
    if (cv2.waitKey(1) & 0xFF) == ord('q'): # Hit `q` to exit
         break

# Release everything if job is finished
out.release()
cap.release()
cv2.destroyAllWindows()

Error:

OpenCV Error: Assertion failed ((scn == 3 || scn == 4) && (depth == CV_8U || depth == CV_32F)) in cv::cvtColor, file C:\build\master_winpack-bindings-win32-vc14-static\opencv\modules\imgproc\src\color.cpp, line 9815
Traceback (most recent call last):
  File "C:/Users/khan1/Desktop/python project/color_threshold/savevid.py", line 19, in <module>
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
cv2.error: C:\build\master_winpack-bindings-win32-vc14-static\opencv\modules\imgproc\src\color.cpp:9815: error: (-215) (scn == 3 || scn == 4) && (depth == CV_8U || depth == CV_32F) in function cv::cvtColor


Process finished with exit code 1

How can I fix it?


Solution

  • It's clear your error is happening on the last frame; that's why your imshow is still working the whole time but it errors out and doesn't complete writing the video which happens after the while loop.

    The first value returned by cap.read() is a boolean on whether or not the frame exists/was read. So you can simply insert an if-else block in your code to perform your processing if the frame was read, and quit the while loop if not, so that you can finish writing the frame.

    This should patch up your code:

    import numpy as np
    import cv2
    
    cap = cv2.VideoCapture('C:\\Users\\khan1\\Desktop\\python project\\color_threshold\\train1.mov')
    
    fourcc = cv2.VideoWriter_fourcc(*'XVID')
    out = cv2.VideoWriter('C:\\Users\\khan1\\Desktop\\python project\\color_threshold\\output.avi',fourcc, 20.0, (640,480))
    
    while(cap.isOpened()):
        ret, frame = cap.read()
        if ret:
    
            hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
            lower_green = np.array([40, 60, 60]) 
            upper_green = np.array([80, 255, 255])
    
            mask = cv2.inRange(hsv, lower_green, upper_green)
            mask = cv2.GaussianBlur(mask, (7, 7), 0)
            res = cv2.bitwise_and(frame, frame, mask=mask)
    
            out.write(res)
    
            cv2.namedWindow("res", cv2.WINDOW_NORMAL)
            cv2.imshow('res', res)
            if (cv2.waitKey(1) & 0xFF) == ord('q'): # Hit `q` to exit
                break
        else:
            break
    
    # Release everything if job is finished
    out.release()
    cap.release()
    cv2.destroyAllWindows()
    

    See an example of this same process here.