Skip to content

[HOW-TO] Set exposure measurement area with Raspberry Pi Camera #1338

@Quibbledoot

Description

@Quibbledoot

Hi there :)

I am trying to take images with a raspberry pi 2018 HQ Camera V1.0 / raspberry Pi 5 combination and I want to manually set the auto exposure metering so that it only meters the right hand side of the camera. As far as I know the tuning file for this camera is the imx477.json.

My question is how can I ensure that my custom metering array is used?

So far I have tried two approaches:

Approach 1:

I did try to directly edit the tuning file like this

"rpi.agc":
{
    "channels": [
        {
            "comment": "Channel 0 is normal AGC",
            "metering_modes":
            {
                "centre-weighted":
                {
                    "weights":
                    [
                        *Array*
                    ]
                },
                "spot":
                {
                    "weights":
                    [
                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                        0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
                        0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
                        0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
                        0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
                        0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0

                    ]
                },
                "matrix":
                {
                    "weights":
                    [
                        *Array*
                    ]
                }
                "custom":
                {
                    "weights":
                    [
                        0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 4, 3, 2,
                        0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 5, 6, 5, 4, 3,
                        0, 0, 0, 0, 0, 0, 0, 3, 4, 5, 6, 7, 6, 5, 4,
                        0, 0, 0, 0, 0, 0, 0, 4, 5, 6, 7, 8, 7, 6, 5,
                        0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 8, 9, 8, 7, 6,
                        0, 0, 0, 0, 0, 0, 0, 6, 7, 8, 9, 9, 9, 8, 7,
                        0, 0, 0, 0, 0, 0, 0, 7, 8, 9, 9, 9, 9, 9, 8,
                        0, 0, 0, 0, 0, 0, 0, 8, 9, 9, 9, 9, 9, 9, 8,
                        0, 0, 0, 0, 0, 0, 0, 7, 8, 9, 9, 9, 9, 9, 8,
                        0, 0, 0, 0, 0, 0, 0, 6, 7, 8, 9, 9, 9, 8, 7,
                        0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 8, 9, 8, 7, 6,
                        0, 0, 0, 0, 0, 0, 0, 4, 5, 6, 7, 8, 7, 6, 5,
                        0, 0, 0, 0, 0, 0, 0, 3, 4, 5, 6, 7, 6, 5, 4,
                        0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 5, 6, 5, 4, 3,
                        0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 4, 3, 2
                    ]
                }
            },

And then take an image like this, where I select the AeMeteringMode to Custom

from picamera2 import Picamera2
from libcamera import controls
from PIL import Image
from datetime import datetime

tuning = Picamera2.load_tuning_file("imx477_edited.json")
picam2 = Picamera2(tuning=tuning)

picam2.configure(picam2.create_still_configuration())
picam2.start()

picam2.set_controls({"AeMeteringMode": controls.AeMeteringModeEnum.Custom})
img = picam2.capture_array()
Image.fromarray(img).save(f"capture_{datetime.now().strftime('%Y%m%d_%H%M%S')}.jpg")
picam2.stop()

and while this resulted in images being taken, the images did not suggest, that it was only metering the right hand side of the image.

Approach 2:

I then tried to set the array in code similar to the solution that I saw in issue #967

[...]
tuning = Picamera2.load_tuning_file("imx477.json")
algo = Picamera2.find_tuning_algo(tuning, "rpi.agc")
algo["channels"][0]["metering_modes"]["custom"] = {
    "weights": [0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 4, 3, 2, 0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 5, 6, 5, 4, 3, 0, 0, 0, 0, 0, 0, 0, 3, 4, 5, 6, 7, 6, 5, 4, 0, 0, 0, 0, 0, 0, 0, 4, 5, 6, 7, 8, 7, 6, 5, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 8, 9, 8, 7, 6, 0, 0, 0, 0, 0, 0, 0, 6, 7, 8, 9, 9, 9, 8, 7, 0, 0, 0, 0, 0, 0, 0, 7, 8, 9, 9, 9, 9, 9, 8, 0, 0, 0, 0, 0, 0, 0, 8, 9, 9, 9, 9, 9, 9, 8, 0, 0, 0, 0, 0, 0, 0, 7, 8, 9, 9, 9, 9, 9, 8, 0, 0, 0, 0, 0, 0, 0, 6, 7, 8, 9, 9, 9, 8, 7, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 8, 9, 8, 7, 6, 0, 0, 0, 0, 0, 0, 0, 4, 5, 6, 7, 8, 7, 6, 5, 0, 0, 0, 0, 0, 0, 0, 3, 4, 5, 6, 7, 6, 5, 4, 0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 5, 6, 5, 4, 3, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 4, 3, 2]
}
picam2 = Picamera2(tuning=tuning)
[...

While here I again got no errors and images where taken these are not what I expect given my custom metering array.

Images

These are examples of the images that I took with these approaches.
For this one the left side was covered and here I expect a relatively normal exposure since the right hand side should anyway only be metered.
Image
For this image, however, where the right hand side is covered I would expect a lot of overexposure on the left side, since the metering should only be done for the right hand side.
Image

To me it seems like it then just defaults to a centre-weighted metering mode. How can I ensure that my custom metering array is used?

Any help is greatly appreciated!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions