VideoCapture from webcam stuck in black and white instead of color

OpenCV version 4.11.0, python library opencv-python-headless = "^4.11.0.86"

I am using the following code to capture a single still from a USB webcam and to write it to a file. I am expecting that the .jpg be in color as the webcam captures in color, however the image is always black and white:

#!/usr/bin/env python

import time
from pathlib import Path

import cv2

capture = cv2.VideoCapture(0, cv2.CAP_V4L2)
capture.set(cv2.CAP_PROP_FRAME_WIDTH, 320)
capture.set(cv2.CAP_PROP_FRAME_WIDTH, 240)
capture.set(cv2.CAP_PROP_SATURATION, 0.9)

while not capture.isOpened():
    print('webcam not ready yet')
    time.sleep(0.5)

success, frame = capture.read()
if not success:
    raise RuntimeError('no frame')

frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
success, data = cv2.imencode('.jpg', frame_rgb)
if not success:
    raise RuntimeError('could not convert to jpg')

with open(Path.home() / 'test.jpg', 'wb') as f:
    f.write(data.tobytes())


capture.release()

If I dump out frame.shape I get (480, 640, 3) so it seems like it is capturing in BGR color space but it’s only getting black and white data.

Does anyone know what is wrong with this code or my setup?

maybe it’s that. have you looked into that?

and why would you do that? if not for the ruined saturation above crushing all the colors, you’d see flipped colors now.

just imwrite(), passing str(some_pathlib_path) and you’re good.

just assert that and fail if it’s not right. unless this case actually happens, and unless the sleep actually fixes the situation, then there’s no reason to sleep and no reason to continue. usually, after the constructor returns, something that isn’t open won’t become open a moment later.

Hello, thank you for the suggestions. On the suggestion of how to save the file with imwrite: I should have been more clear that this source code is extracted from a larger context that needs to generate a bytearray of jpg data w/o any file io. In this example I have it write to a file so I can visually inspect it, but the actual application will stream it over the network which is harder to inspect when there are problems at this stage. Should have phrased this better to avoid an X Y question.

If I use the imwrite approach that works and I get a color image. Is there a way to do imwrite to a Python BytesIO so I can avoid file ops? Looks like from a google search that most people use imencode which would bring me back to my current situation.

Using the imencode approach without the saturation property set still results in a black and white image for both frame and frame_rgb