Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Strategies for removing aliasing / refresh rate effects

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:

image description

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:

image description

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):

image description

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")