raspberrypi / picamera2

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

AWBmode seems to have no effect[BUG] #977

Closed quitmeyer closed 6 months ago

quitmeyer commented 6 months ago

Describe the bug While using picamera2 and setting the controls, it doesn't seem to matter what value i give for AwbMode, all the images look exactly the same. I also tried setting AwbEnable to True or False, and it doesn't seem to have any bearing

To Reproduce

picam2.set_controls({"AnalogueGain": 1.0,"AeEnable": False,"AwbEnable": False,"AwbMode": controls.AwbModeEnum.Cloudy, "ExposureTime": 8000,"LensPosition": 7.82})

I have also tried changing AwbMode to just values like integers between 1 and 7 and no effect difference

Console Output, Screenshots awbenable = true awbmode = 6 image awbenable = false awbmode = 6 image awbenable = false awbmode = 3 image (and so forth)

Hardware : Rpi4 Arducam 64mp, bookworm 64 (installed march 01)

davidplowman commented 6 months ago

Hi, thanks for the question. Could you try leaving the AWB enabled, and then in your set_controls, change only the AWB mode. Does that make a difference? Thanks.

quitmeyer commented 6 months ago

Cool! So here's an interesting thing, if I specify AwbEnable True then there is no effect in changing the awb mode. (Exact same behavior as if i set AwbEnable to False)

BUT if i just never specify a AwbEnable then i CAN change the AWB mode and it does have an effect! image

how could the default behavior be different than either the True or False states?

davidplowman commented 6 months ago

So when you set a specific AwbMode, you do need the AWB still to be running - because it still needs to do an AWB calculation, just on a limited range of colour temperatures.

Generally I would never set AwbEnable explicitly, except maybe if you want to freeze the AWB wherever it currently is (and don't send any other AWB controls at the same time). I expect this is what was happening. Ditto with AeEnable.

quitmeyer commented 6 months ago

So when you set a specific AwbMode, you do need the AWB still to be running - because it still needs to do an AWB calculation, just on a limited range of colour temperatures. ok that great to know! but im still confused as to why it doesn't work when AwbEnabled = true then?

for right now just setting AwbMode= Cloudy works fine for us to get good photos, but one of the most important things for us, since it is a scientific device is just that it does things consistently. If i leave it as AwbMode = cloudy will it function in the same way as like the settings on my old professional cameras that had "Flourescent, Incandescent, Cloudy, Daylight, etc..." settings? Meaning that it just applies a constant filtering to all images regardless of the incoming light changing? (the "auto" in Awb being enabled makes me worried.

davidplowman commented 6 months ago

No quite. Even in "cloudy" mode it still does an AWB search, just over a limited range. If you want 100% fixed AWB, have a look what AWB gains it is using once it has settled to something you like:

colour_gains = picam2.capture_metadata()['ColourGains']

and then apply these fixed gains:

picam2.set_controls({'ColourGains': colour_gains})

(To "un-fix" the AWB, repeat the above but setting colour gains of (0, 0).)

quitmeyer commented 6 months ago

"If you want 100% fixed AWB," Yeah! that's exactly what i want! thank you so much!

an odd thing im noticing now though is if i run your command

    colour_gains = picam2.capture_metadata()['ColourGains']
    print("colour gains for CLOUDY is ") #(1.5943877696990967, 2.129925489425659)
    print(colour_gains)

it stops the selected WB mode from taking effect! it only gives one result: "(1.5943877696990967, 2.129925489425659)" no matter what setting i put it on, and all the images come out the same!

all these use the exact same code, except the blue ones have the colour_gains = picam2.capture_metadata()['ColourGains'] image

davidplowman commented 6 months ago

Not quite sure what you mean. If you set the colour_gains to explicit fixed (non-zero) values, then you should get those exact same colour gains forever (until you set them both to zero, at which point the AWB algorithm will take over again). Is that what's happening, or not?

quitmeyer commented 6 months ago

Not quite sure what you mean. basically if i just put this code into an existing script, that only READS color gains, it for some reason overrides all other AWB settings, and gives only those specific numbers colour_gains = picam2.capture_metadata()['ColourGains']

I wasn't setting the colour gains at all in that code. Just thought that was odd behavior, and potentially buggy! Also if i just READ the color gains AFTER a photo has been taken, everything freezes!

but in terms of what I actually need for this science project, just setting color gains to (0,0) works splendidly! thanks!

quitmeyer commented 6 months ago

, just setting color gains to (0,0) works splendidly!

So an odd thing i have found is that the white balance set by the colourgains seems to alternate every other picture (like every other photo it just doesn't take effect?) Or it just kinda takes effect randomly?

this is an illustrative image here: image or this one image

you can see how, even though these photos are all taken with the exact same setup, just 1 minute apart, the white balance changes on and off

my code for taking the photos is just:

 if camera_settings:
        picam2.set_controls(camera_settings)
    else:
        print("can't set controls")
    ''''''

    picam2.start()
    #important note, to actually 100% lock down an AWB you need to set ColourGains! (0,0) works well for plain white LEDS
    gains = 0,0
    picam2.set_controls({"ColourGains": gains})

    time.sleep(5)

    start = time.time()

    flashOn()

    request = picam2.capture_request(flush=True)

    if not onlyflash:
        flashOff()
    flashtime=time.time()-start

    print("picture take time: "+str(flashtime))

    array = request.make_array('main')

    now = datetime.now()
    timestamp = now.strftime("%Y_%m_%d__%H_%M_%S")  # Adjust the format as needed

    print(timestamp)
    #save the image
    folderPath= "/home/pi/Desktop/Mothbox/photos/" #can't use relative directories with cron
    filepath = folderPath+"ManFocus_"+computerName+"_"+timestamp+".jpg"

    request.save("main", filepath)
    print("Image saved to "+filepath)

(full code here: https://github.com/Digital-Naturalism-Laboratories/Mothbox/blob/main/Software/TakePhoto.py)

tvoverbeek commented 6 months ago

In TakePhoto.py you start the camera on line 175 and immediately stops it again on line 178. Then it is started again in takePhoto_Manual on line 203, but it is never stopped. If you run this every minute then the camera remains running in between the one minute runs. Doubling camera activation is not a good idea.

quitmeyer commented 6 months ago

" If you run this every minute then the camera remains running in between the one minute runs." -ohhhh! i had just figured that the camera stopped when the script stopped, since that script stops after it. Does that mean my camera has just been running constantly when i do these night long timelapses?

if so, thanks so much for letting me know to manually kill it!

im adding a picam2.stop() right before the quit() at the end! hopefully that helps!

quitmeyer commented 6 months ago

Ok I think i found a way that seems to give consistent results when trying to lock down a white balance/ color gains

AwbEnable needs to be set to 0 AND colourgains has to be set to two FLOATS for instance previously i did this: gains = 0,0 picam2.set_controls({"ColourGains": gains})

and it was giving me erratic behavior but I changed it to gains = 0.0, 0.0

and then it seemed to start working consistently! (or maybe im just losing my mind a bit, hahahah)