Drubbels
Drubbels

Reputation: 357

OpenCV2: grayscaled video displays fine, but does not save

I'm trying to get familiar with OpenCV2 for basic image and video processing. Right now I'm having trouble saving grayscaled video frames. The following code (adapted from here) is meant to save three versions of a six-second video I took of the Arc de Triomphe (arc.avi) - one unmodified, one entirely grayscaled, and one grayscaled only during certain frames and full colour in others.

import cv2

capture = cv2.VideoCapture('arc.avi')

fourcc = cv2.VideoWriter_fourcc(*'DIVX')
outgray = cv2.VideoWriter('vidgray.avi',fourcc, 30.0, (1280,720))
outorig = cv2.VideoWriter('vidorig.avi',fourcc, 30.0, (1280,720))
outhalf = cv2.VideoWriter('vidhalf.avi',fourcc, 30.0, (1280,720))

framecounter = 0
while(True):

    ret, frame = capture.read()

    grayFrame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    outorig.write(frame)
    outgray.write(grayFrame)

    #cv2.imshow('video gray', grayFrame)
    #cv2.imshow('video original', frame)

    if framecounter//40%2 == 1:
        outhalf.write(frame)
        cv2.imshow('video half', frame)
    else:
        outhalf.write(grayFrame)
        cv2.imshow('video half', grayFrame)

    if cv2.waitKey(1) == 27:
        break

    framecounter += 1

capture.release()
outgray.release()
outorig.release()
outhalf.release()
cv2.destroyAllWindows()

(I can't figure out how to enclose my video files, but if you want to reproduce the problem, you should be able to use the code yourself on any .avi file of your choosing).

vidorig.avi saves fine, and looks exactly like the original when played back (as it is meant to). vidgray.avi is an empty video file with zero frames (confusing the hell out of my VLC player when I try to play it back). vidhalf.avi consists only of the full-colour frames, and simply skips all the grayscaled frames it is meant to have. This leads to the video being shorter and having weird jittery jumps between frames.

Note that the problem is only with the saved video files, not (as far as I can tell) with the grayscaling process itself. While I do get an error message:

OpenCV Error: Assertion failed (scn == 3 || scn == 4) in cv::ipp_cvtColor, file ..\..\..\modules\imgproc\src\color.cpp, line 7456
Traceback (most recent call last):
  File "grayvid.py", line 15, in <module>
    grayFrame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.error: ..\..\..\modules\imgproc\src\color.cpp:7456: error: (-215) scn == 3 || scn == 4 in function cv::ipp_cvtColor

all three display just fine at runtime with cv2.imshow. It's only the saved files which are problematic.

I am on Windows 8, using OpenCV2 in Python 3.5.4.

Note that this is not a duplicate of Save grayscale video in OpenCV? - I don't get the error Nithin does, nor do the proposed answers work (my code implemented them to begin with).

Upvotes: 0

Views: 80

Answers (1)

Tobias Senst
Tobias Senst

Reputation: 2840

The writer function of the VideoWriter class expects (in general) images with the RGB format (see OpenCV Docu). Most probably the encoder misinterpret the image data if it contains only 1 channel. To store gray valued images you can extend the 1 channel gray image into a 3 channel image by copying the gray channel to R,G and B. This will be done by cv2.COLOR_GRAY2BGR.

In that case your code would look like:

ret, frame = capture.read()

grayFrame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
// expand dimension on gray valued image
grayFrame = cv2.cvtColor(grayFrame, cv2.COLOR_GRAY2BGR)
outorig.write(frame)
outgray.write(grayFrame)

Upvotes: 1

Related Questions