Extracting grayscale images from a video using opencv

I am trying to extract images (frames) from a video and save them at a specific location. I have written the following code where it works well for extracting color images.

extractFrames(srcPath,dstPathColor)

However, When I want to extract grayscale image ( extractFrames(srcPath,dstPathColor,gray=True ), only one image is written to destination folder and code stops

import numpy as np
import cv2
print('OpenCV version: '+cv2.__version__)
import matplotlib as plt

def extractFrames(srcPath,dstPath,gray=False):
    # gray = true writes only grayscale images of the video
    
    cap = cv2.VideoCapture(srcPath)

    # check if camera opened successfully
    if (cap.isOpened() == False):
        print("Error reading video file")

    try:
        frameCount = 1
        while(cap.isOpened()):
            
            ret, frame = cap.read()

            if ret == True:

                if gray==True:
                    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
                    cv2.imwrite(dstPath+'grayframe'+str(frameCount)+'.jpg',gray)
                    
                else:
                    cv2.imwrite(dstPath+'colorframe'+str(frameCount)+'.jpg',frame)
                                
                frameCount += 1

                if cv2.waitKey(1) & 0xFF == ord('q'):
                    break

            # if frame is read correctly, ret is True
            else:
                print("Can't retrieve frame - stream may have ended. Exiting..")
                break

    except:
        print("Video has ended.")

    cap.release()
    cv2.destroyAllWindows()
    

vidName = 'scale_calib2.avi'
srcPath = vidName;
dstPathColor = 'Extracted Images\\Color\\'
dstPathGray = 'Extracted Images\\Gray\\'

#extractFrames(srcPath,dstPathColor)
#print('Finished extracting color images from video')

extractFrames(srcPath,dstPathGray,gray=True)
print('Finished extracting gray images from video')

Ouput:

Video has ended.
Finished extracting gray images from video

When I call the function to extract gray scale images ( extractFrames(srcPath,dstPathColor,gray=True ), only one image is written to destination folder and code stops executing. Why is this happening?

The imwrite function works well in extracting all color images (frames) from the video.

How do I fix this?

Naming bug: You are using variable gray both as a boolean parameter for the function and as a Mat for the converted frame

1 Like

Ha! Thank you for pointing out. I fixed the naming bug but still getting the same error:

def extractFrames(srcPath,dstPath,grayImg=False):
    # grayImg = true writes only grayscale images of the video
    
    cap = cv2.VideoCapture(srcPath)

    # check if camera opened successfully
    if (cap.isOpened() == False):
        print("Error reading video file")

    try:
        frameCount = 1
        while(cap.isOpened()):
            
            ret, frame = cap.read()
            print('frame count: {0}'.format(frameCount))
            #print('ret: {0}'.format(ret))

            if ret == True:

                if grayImg==True:
                    gray = cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR)
                    cv2.imwrite(dstPath+'grayframe'+str(frameCount)+'.jpg',gray)
                    
                elif grayImg==False:
                    cv2.imwrite(dstPath+'colorframe'+str(frameCount)+'.jpg',frame)
                
                else:
                    print('something went wrong')
                    break
                    
                frameCount += 1

                if cv2.waitKey(1) & 0xFF == ord('q'):
                    break

            # if frame is read correctly, ret is True
            else:
                print("Can't retrieve frame - stream may have ended. Exiting..")
                break

    except:
        print("Video has ended.")

    cap.release()
    cv2.destroyAllWindows()
    

vidName = 'scale_calib2.avi'
srcPath = vidName;
dstPathColor = 'Extracted Images\\Color\\'
dstPathGray = 'Extracted Images\\Gray\\'

#extractFrames(srcPath,dstPathColor)
#print('Finished extracting color images from video')

extractFrames(srcPath,dstPathGray,grayImg=True)
print('Finished extracting gray images from video')

Looks like only first frame is processed for gray scale image conversion

Nevermind. I was testing few different color spaces and had the wrong argument for gray = cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR)

It is now corrected to gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) and everything is working as expected.