Closed mmoollllee closed 8 months ago
Hi, thanks for attaching the helpful test script. Looking at it, I would recommend adding something like time.sleep(0.5)
after calling set_controls
, as the auto exposure will take a few moments settle.
In your question, you say the the exposure varies too much. To some extent this is unavoidable when changing between cloudy or sunny conditions. Can you say how you would like this to change?
For example, you could restrict the available range of exposure times, but you may simply find that some of your images are over or under exposed. Or you could change the metering mode (for example, from "spot" to "matrix"), but this may or may not make much difference. You can get quite precise control of these behaviours in the camera tuning file, but it would be helpful to know what you would like to achieve. Thanks!
Thank you for you fast answer and the tipp with time.sleep(0.5)
. I will implement this right away and see if it helps!
To clarify the case see the following two pictures taken in 5 minutes.
I thought to solve this behaviour it would help to define a area on the sensor that should be used for exposure calculation (see red rectangle area).
Is that possible?
From documentation I know there is a "AeMeteringMode": controls.AeMeteringModeEnum.Custom
, but I have no idea how to set this up... Sorry for my missing knowledge :(
Yes, you can customise the metering area. You will need to edit the camera tuning file to do this.
Normally, you should find this in the folder /usr/share/libcamera/ipa/rpi/vc4
for Pi 4 or earlier devices. Look for a file named <your-camera>.json
. For example, the camera module 3 would be imx708.json
(though note that there is a wide angle version). Anyway, the easiest way to check you've found the right file is to insert a few characters of garbage at the top and check that the camera doesn't start!
Once you have this file, save a backup (just in case!), then open it and search for "metering_modes". There you will find a list of 15 weights for each mode that are applied to different parts of the image. You can set to zero any regions that you don't care about. The map of where the regions lie can be found in section 5.9.2 of the camera tuning guide (page 31).
For Pi 5 the arrangements are similar, but slightly different. Let me know if you are using a Pi 5.
Awesome!! I understand.
So for my case I came up with something like [5,4,4,1,4,3,3,1,1,0,2,0,0,1,1]
.
I'll try out and see what the results look like tomorrow!
From checking examples/tuning_file.py I came up with the following to set custom weights in python before starting the camera.
dir = 'some/path'
timestamp = '2024-02-28_15-57'
# load tuning file
tuning = Picamera2.load_tuning_file("imx477.json")
algo = Picamera2.find_tuning_algo(tuning, "rpi.agc")
algo["metering_modes"]["custom"] = {"weights": [5,4,4,1,4,3,3,1,1,0,2,0,0,1,1]}
with Picamera2(tuning=tuning) as picam2:
picam2.start(show_preview=False)
picam2.set_controls({
"AeMeteringMode": controls.AeMeteringModeEnum.Custom,
"AeExposureMode": controls.AeExposureModeEnum.Long,
"Brightness": 0,
"ExposureValue": 0,
"FrameDurationLimits": (100, 10000000)
})
# auto exposure might take a few moments settle
time.sleep(0.5)
ctrl={}
capture_config = picam2.create_still_configuration(ctrl)
picam2.switch_mode_and_capture_file(capture_config, os.path.join(dir, timestamp+".jpg"))
picam2.stop()
From what I understand I can't set the metering areas without restarting the camera, e.g. by clicking on a preview window as it's done on Smartphone devices?
Thanks for your help!!
Yes, you will have to completely shut down and restart the camera system to force it to re-read the camera tuning file. libcamera does not expose an API to change this at runtime - though I suppose it might do one day if enough people ask for it!
Yes, you will have to completely shut down and restart the camera system to force it to re-read the camera tuning file.
That's actually already happening in my code, right?
libcamera does not expose an API to change this at runtime - though I suppose it might do one day if enough people ask for it!
Where should I ask for it? In the raspberrypi/libcamera repo?
Still monitoring the change, but so far I think it already works better here
Thank you again!
Yes, looks to me like your code should be doing that!. I said there's no API for updating this at runtime, but you can switch between metering modes at runtime, for example with
picam2.set_controls({'AeMeteringMode': controls.AeMeteringModeEnum.Custom})
I suppose you could switch between modes interactively just to test that you're getting difference you expect.
Yes, you will have to completely shut down and restart the camera system to force it to re-read the camera tuning file. libcamera does not expose an API to change this at runtime - though I suppose it might do one day if enough people ask for it!
Hello, @davidplowman when you say that you have to restart the camera system, can this be done without rebooting the Raspberry Pi? Thanks!
You should be able to close the Picamera2 object (picam2.close()
) and re-open it, and I think that's enough.
@davidplowman
In the tuning file, we can see that there are 3 different channels
:
"rpi.agc":
{
"channels": [
{},
{},
{}
]
}
What do these 3 different channels correspond to? How can we select which channel to use? Why are there 3 different channels? The first one is selected by default, correct?
I noticed that they are mostly identical with the second one having "base_ev": 0.125
and the third one having "base_ev": 1.5
. I'm guessing that it's to have higher or lower overall image brightness.
In the documentation we can choose the following settings:
If I want select controls.AeMeteringModeEnum.Custom
, all I have to do is:
"rpi.agc":
{
"channels": [
{
"metering_modes":
{
"centre-weighted":
{
"weights":
[
3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
]
},
"spot":
{
"weights":
[
2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
]
},
"matrix":
{
"weights":
[
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
]
},
"custom":
{
"weights":
[
// My custom weights! (top secret)
]
}
},
Thanks again :smile:
Use channel 0, which is selected by default. libcamera has no API actually to choose different channels, but they may be used internally if you were to engage a particular HDR mode. But I don't think this is relevant to you, so as I said, channel 0.
As regards setting custom weights, yes that's correct!
I'm captureing images every couple minutes to produce timelapse videos. My current configuration is not yet achieving the optimal results, as exposure varies much (e.g. if cloudy or not). I'd like to define a specifiy area to measure Exposure. Is that possible, or is there other way to get more even exposure?
My current setup looks like this:
Thank you for your work!!!