raspberrypi / picamera2

New libcamera based python library
BSD 2-Clause "Simplified" License
889 stars 188 forks source link

[HOW-TO] Allow AnalogueGain to go above 6 during image capture #840

Open Eric-Nava-Git opened 1 year ago

Eric-Nava-Git commented 1 year ago

My Question

When capturing images with default settings, the analogue gain will not go above 6, even when there is no light entering the camera lens. How can I allow the gain to go above 6 for low light situations?

Setup

Hardware is a Raspberry Pi Zero W and a Pi Camera Module 3. Running Raspberry Pi OS Lite - Bookworm

Test Method:

Completely cover the camera lens with a towel so no light is getting to the sensor. Then I run this test code:

from picamera2 import Picamera2

picam2 = Picamera2()
config = picam2.create_still_configuration()
picam2.configure(config)
print(f"AnalogueGain control limits: {picam2.camera_controls['AnalogueGain']}")
picam2.start()

request = picam2.capture_request()
request.save("main", "test.jpg")
metadata = request.get_metadata()

print(f"ExposureTime: {metadata['ExposureTime']}  AnalogueGain: {metadata['AnalogueGain']} DigitalGain: {metadata['DigitalGain']}")

request.release()

The output

[23:16:24.700512335] [2833]  INFO Camera camera_manager.cpp:284 libcamera v0.1.0+52-a858d20b
[23:16:24.994538329] [2836]  WARN RPiSdn sdn.cpp:39 Using legacy SDN tuning - please consider moving SDN inside rpi.denoise
[23:16:25.018209087] [2836]  INFO RPI vc4.cpp:387 Registered camera /base/soc/i2c0mux/i2c@1/imx708@1a to Unicam device /dev/media3 and ISP device /dev/media0
{'format': 'SRGGB10_CSI2P', 'size': (1536, 864)} 9600.0
{'format': 'SRGGB10_CSI2P', 'size': (2304, 1296)} 7200.0
{'format': 'SRGGB10_CSI2P', 'size': (4608, 2592)} 0.0
[23:16:25.101684233] [2833]  INFO Camera camera.cpp:1213 configuring streams: (0) 4608x2592-BGR888 (1) 4608x2592-SBGGR10_CSI2P
[23:16:25.104624203] [2836]  INFO RPI vc4.cpp:549 Sensor: /base/soc/i2c0mux/i2c@1/imx708@1a - Selected sensor format: 4608x2592-SBGGR10_1X10 - Selected unicam format: 4608x2592-pBAA
AnalogueGain control limits: (1.1228070259094238, 16.0, None)
ExposureTime: 119305  AnalogueGain: 5.988304138183594 DigitalGain: 1.0077857971191406

The saved test.jpg image is completely black. You can see from the output that the Analogue Gain is stuck at 6 even though the limit should be 16. I'm not sure what I am doing wrong, any advice would be appreciated.

Manuel-Angel-Es commented 1 year ago

Hi @Eric-Nava-Git,

I have carried out tests with my camera and specifically the analog gain adjustment works correctly with values between 1 and 16. Note that it does not adjust automatically, unless you activate auto exposure.

In my case I adjust the analog gain with the following instruction:

# AnalogueGain: value between 1.0 and 16.0.
picam2.controls.AnalogueGain = 1.0

No need to stop the camera, analog gain can be adjusted dynamically with the camera active.

To activate autoexposure you must first set the exposure time to 0:

#ExposureTime:
picam2.controls.ExposureTime = 0

Next we activate autoexposure:

#AeEnable:
# AEC: Automatic Exposure Control.
# AGC: Automatic Gain Control.
# False: AEC/AGC algorithm disabled.
# True: AEC/AGC algorithm enabled.
picam2.controls.AeEnable = True

With auto exposure, the exposure time and analog gain are automatically adjusted.

It is possible to act on the exposure value adjusted by the AEC/AGC algorithm with the ExposureValue variable:

# ExposureValue: value between -8.0 and 8.0. Default 0.0.
picam2.controls.ExposureValue = 0

Values less than 0 darken the image. Higher values give brighter images.

Good luck

sandyol55 commented 1 year ago

Also worth looking at the different AeExposureMode settings that are available.

The .json tuning file for the camera contains three different exposure profiles and the 'normal' one is applied by default, and I think the 6.0 max analogue gain will be defined in that profile. If you switch to the 'long' profile that should allow a gain of 12 for the V3 camera (I think, don't have one to check!)

from picamera2 import Picamera2

picam2 = Picamera2()
config = picam2.create_still_configuration(controls={"AeExposureMode":2})
picam2.configure(config)
print(f"AnalogueGain control limits: {picam2.camera_controls['AnalogueGain']}")
picam2.start()

request = picam2.capture_request()
request.save("main", "test.jpg")
metadata = request.get_metadata()

print(f"ExposureTime: {metadata['ExposureTime']}  AnalogueGain: {metadata['AnalogueGain']} DigitalGain: {metadata['DigitalGain']}")

request.release()

Editing the tuning file to define a max gain of 16 for the 'long' profile or perhaps defining a suitable custom one would perhaps allow the full analogue gain to be applied even during an 'auto exposure' mode. Look for this section in the imx708.json tuning file

                {
                    "normal":
                    {
                        "shutter": [ 100, 15000, 30000, 60000, 120000 ],
                        "gain": [ 1.0, 1.0, 2.0, 4.0, 6.0 ]
                    },
                    "short":
                    {
                        "shutter": [ 100, 5000, 10000, 20000, 120000 ],
                        "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
                    },
                    "long":
                    {
                        "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
                        "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
                    }
                },
Manuel-Angel-Es commented 1 year ago

@sandyol55,

You are right, I have never stopped in checking these details. In my case I use Picamera2 as a user. As I really use it meets my needs. For my part I use a configuration file created by a competent technician in digital image. Specifically I use the following instructions:

tuningfile = Picamera2.load_tuning_file("imx477_scientific.json")
picam2 = Picamera2(tuning=tuningfile)

Personally in my case it works very well

Regards