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?
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
I don’t think it’s a transmitting or decoding problem because at the point of
with open(Path.home() / 'test.jpg', 'wb') as f:
f.write(data.tobytes())
The image that is being written to disk, for debugging purposes, is in black and white, and the code above that part is the same as what’s in the streaming application. The original python snippet is just extracted and the transmit part is replaced with the f.write() part just to sanity check what is being sent over the network–so I know that before I send the data that the data I have in the numpy array is in black and white.
I’ve found it, the issue was on my side and not OpenCV related. I’m guessing that the low saturation value was persisted from the original version of the script? I think that the gain was set to a really high value because sometimes I would accidentally run the program while the webcam cap was still on.
I have noticed that too. either the camera or the driver in the operating system persists those things. they are not reset to any defaults when you “open” it. they might reset with a system reboot, or they might require the device to be unplugged, or maybe neither would do that and it’s stored on the device (unlikely) or by the system.