I am working with OpenCV. I have a video file, and I want to read it in grayscale, instead of converting every frame in grayscale. i.e
cap = cv2.VideoCapture(VIDEO_PATH)
results = {}
curr_frame = 0
start = time.time()
while(cap.isOpened()):
# Capture frame-by-frame
ret, frame = cap.read()
if ret == True:
curr_frame =1
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
I do not want to do this, instead I want to read it directly in grayscale as we do in images i.e
im_gray = cv2.imread('grayscale_image.png', cv2.IMREAD_GRAYSCALE)
Now upon inspecting the documentation, I found that the read function "The method/function combines VideoCapture::grab() and VideoCapture::retrieve() in one call." And inside retrieve, we can pass a flag value. Is it possible to combine it with read and read it in gray scale instead of converting it explicitly?
I tried doing
ret, frame = cap.read(flag=0)
But it is not a valid keyword argument.
error: OpenCV(4.5.5) :-1: error: (-5:Bad argument) in function 'read'
> Overload resolution failed:
> - 'flag' is an invalid keyword argument for VideoCapture.read()
> - 'flag' is an invalid keyword argument for VideoCapture.read()
But I can pass in any random number in cap.read()
and it works.
cap.read(-4)
I was looking for source code in Python, but can not found any source code in Python for this function on github.
CodePudding user response:
According to the VideoCaptureModes
documentation, there are four possible modes:
cv2.CAP_MODE_BGR - BGR24 (default)
cv2.CAP_MODE_RGB - RGB24
cv2.CAP_MODE_GRAY - Y8
cv2.CAP_MODE_YUYV - YUYV
Also note:
Currently, these are supported through the libv4l backend only.
So to read video frames directly as grayscale using cv2.VideoCapture()
, you have to set the mode to grayscale with cv2.CAP_MODE_GRAY
like this:
capture = cv2.VideoCapture(0)
possible = capture.set(cv2.CAP_PROP_MODE, cv2.CAP_MODE_GRAY)
print(possible)
# IMPORTANT: Check this value to see if it's supported by your system
You have to check the returned bool
value to see if it's possible since it may or may not be supported by your OS, camera, hardware, or backend. If the returned value is False
or you get an error like this
AttributeError: module 'cv2' has no attribute 'CAP_MODE_GRAY'
then unfortunately it's not possible for your system, the best thing you can do is convert to grayscale with cv2.cvtColor
after retrieving the frame.
Here's a working example to read frames directly as grayscale from a webcam
import multiprocessing as mp
import cv2, time
def capture_frames():
capture = cv2.VideoCapture(0)
possible = capture.set(cv2.CAP_PROP_MODE, cv2.CAP_MODE_GRAY)
print(possible)
# FPS = 1/X, X = desired FPS
FPS = 1/120
FPS_MS = int(FPS * 1000)
while True:
# Ensure camera is connected
if capture.isOpened():
(status, frame) = capture.read()
# Ensure valid frame
if status:
cv2.imshow('frame', frame)
else:
break
if cv2.waitKey(1) & 0xFF == ord('q'):
break
time.sleep(FPS)
capture.release()
cv2.destroyAllWindows()
if __name__ == '__main__':
print('Starting video stream')
capture_process = mp.Process(target=capture_frames, args=())
capture_process.start()