2

From this and this I know that there is no way of setting camera.analog_gain and camera.digital_gain between subsequent runs of a script. However, I'm still faced with the problem that I need consistent videos between different runs of the same script.

Here's a solution I came up with that I see works if you play around with the light intensity your camera gets and wait. Eventually I get an analog_gain and a digital_gain value that I choose. Except...

Ghetto Solution:

#The Value you want for analog_gain = AG
#The Value you want for digital_gain = DG
AG = Fraction(17, 16)
DG = 1

camera=picamera.PiCamera()
time.sleep(2)
while camera.analog_gain != AG or camera.digital_gain != DG:
        time.sleep(0.1)
        print ("analog gain = "+str(camera.analog_gain))
        print ("digital gain = "+str(camera.digital_gain))
#time.sleep(2) <=== Don't let the values settle
camera.shutter_speed=camera.exposure_speed
camera.exposure_mode='off'
print (camera.analog_gain)
print (camera.digital_gain)
g = camera.awb_gains
camera.awb_mode = 'off'
camera.awb_gains = g
camera.shutter_speed = 30000
camera.awb_gains = (1,1)
camera.iso = 0

Except, what is the relationship - mathematically - between analog_gain and digital_gain? Is there one? If I have the value for anaolog_gain, what values are possible for digital_gain? What choices for analog_gain and digital_gain are possible or reasonable if I have an experiment where daily I need to wait for the camera gains to settle to the value they were at the previous day?

So far I've just been looking at what values I've seen appear already. e.g. In a previous run I saw

analog gain = 1
digital gain = 17/16

print out and therefore I set

AG = Fraction(17, 16)
DG = 1

since I thus knew it was a possible combination. After a while the gains did settle at these values.

2

For a definitive answer to this I'd recommend posting to the RPi camera forum and hoping for 6by9 or JamesH (the firmware devs) to answer as they'll know for certain what's going on under the covers.

My (limited) understanding is that analog gain is the gain applied to the sensor itself and that the firmware "prefers" modifying this as opposed to digital gain (which is gain applied by the firmware to the captured data). In other words, analog gain is applied first and presumably adjusts the sensitivity of the camera, while digital gain is presumably multiplication (or some other form of scaling?) of the resulting pixel values (whether this is done to the raw 10-bit bayer data, or later on in the pipeline I don't know).

The maximum value of each gain is 8.0 (and obviously the minimum is 0.0). From experience (but without any deeper insight into the underlying logic) I can say that when the firmware wants more gain (because the scene is too dark) it usually pushes analog gain up while leaving digital gain at 1.0. Only once analog gain hits the limit (8.0) have I seen it start to push digital gain up far above 1.0. That said there are circumstances where digital gain hovers around 1.1 or 1.2 while analog gain is below 8.0. Why this occurs I don't know (perhaps digital gain was above 1.0 in a dark scene which brightened and the firmware adjusted analog gain down first?)

Anyway, my guess is that when digital gain is ~1.0, analog gain must be in the range 1.0 <= gain < 8.0, and when digital gain is >~1.3, analog gain must be 8.0.

One interesting question which I don't know the answer to is what happens in extremely bright scenes? Does the firmware dip analog gain below 1.0, or does it leave analog gain at 1.0 and reduce the digital gain first? This isn't something I've had the opportunity to test, but I'd be interested to hear any results. If you want to have a play with this further, this little curses based script may prove useful:

#!/usr/bin/env python

import picamera
import curses

def main(window):
    window.nodelay(True)
    with picamera.PiCamera() as camera:
        camera.resolution = (1280, 720)
        camera.framerate = 24
        while True:
            window.addstr(0, 0, 'Press Q to quit')
            window.addstr(2, 0, 'Analog gain: %.1f' % camera.analog_gain)
            window.addstr(3, 0, 'Digital gain: %.1f' % camera.digital_gain)
            window.refresh()
            c = window.getch()
            if c == ord('q'):
                break

curses.initscr()
curses.wrapper(main)

Fire it up and then give the camera differently lit scenes (turn lights on and off, point it at a light source, hold your hand over the lens, etc.)

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.