I'm trying to send various 8x8 pixel values to an LED matrix and take a picture at each cycle. This is on a Raspberry Pi 3 using the Sense Hat and a Logitech C920 webam (for now; could use the rpi camera).
Here's a raw image example:
Somewhere in googling around I found this post about long exposures, so I implemented that strategy. Namely, I can grab n frames and average them. It's not the best, but I get things more like this:
I've done this with my DSLR, but I'm trying to automate. With the DSLR, I just manually tweak the exposure and aperture to get a good shot. I tried that with various cam.set(cv2.CAP_FOO)
settings and had a tough time. I opted to just set them directly with subprocess
and v4l2-ctl
, but I can't seem to get a good setting for exposure_absolute
, brightness
, and others to get a good picture.
Any suggestions on how to get something cleaner and with good color representation? The below seem overexposed to me. Here's an example of a 16x16 LED matrix shot with my DSLR (what I'd like to see):
Here's how I'm setting up the camera:
def setup_cam():
cam_props = {'brightness': 108, 'contrast': 128, 'saturation': 158,
'gain': 10, 'sharpness': 128, 'exposure_auto': 1,
'exposure_absolute': 100, 'exposure_auto_priority': 0,
'focus_auto': 0, 'focus_absolute': 50, 'zoom_absolute': 150,
'white_balance_temperature_auto': 0, 'white_balance_temperature': 3000}
for key in cam_props:
subprocess.call(['v4l2-ctl -d /dev/video0 -c {}={}'.format(key, str(cam_props[key]))],
shell=True)
subprocess.call(['v4l2-ctl -d /dev/video0 -p 30'], shell=True)
subprocess.call(['v4l2-ctl -d /dev/video0 -l'], shell=True)
cam = cv2.VideoCapture(0)
return cam
Here's the function to take an averaged picture based on that post above:
def take_pic():
r_ave, g_ave, b_ave, total = (0, 0, 0, 0)
for i in range(10):
(ret, frame) = cam.read()
(b, g, r) = cv2.split(frame.astype('float'))
r_ave = ((total * r_ave) + (1 * r)) / (total + 1.0)
g_ave = ((total * g_ave) + (1 * g)) / (total + 1.0)
b_ave = ((total * b_ave) + (1 * b)) / (total + 1.0)
# increment the total number of frames read thus far
total += 1
return cv2.merge([b_ave, g_ave, r_ave]).astype("uint8")