Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to set custom exposure area to the same as auto focus area #1095

Open
cornato55 opened this issue Aug 15, 2024 · 1 comment
Open

How to set custom exposure area to the same as auto focus area #1095

cornato55 opened this issue Aug 15, 2024 · 1 comment

Comments

@cornato55
Copy link

cornato55 commented Aug 15, 2024

I made a program that uses a camera to take a photo, that photo is then processed with an April Tag script to find April tags in it, it is used for inventory tracking. The issue is that the camera is outside and some parts of the day there are massive shadows because of the building. During these parts of the day a lot of the image is washed out and the program can't find the April tags in it.

image

There is a grid pattern we use to locate the April Tags, and I have a custom script setup that sets separate Auto-Focus areas for each grid pattern to be sure that grid is in focus since they are so far apart. I want to set the custom Auto-Exposure setting to use the same coordinates so that the Exposure and Focus are perfect allowing us to see all the tags in that area.

I'm using a Raspberry Pi 5 and an Arducam OwlSight OV64A40 64Mp camera sensor. It is being processed using pupil-labs April Tag detector script. Here are the camera's settings that produced the picture above.

def set_camera():
    
    try:        
        time.sleep(1)
        picam2 = Picamera2()
        capture_config = picam2.create_still_configuration(main={'size': (9248, 6944)})
        mode = picam2.sensor_modes[1]
        preview_config = picam2.create_preview_configuration(sensor={'output_size': mode['size'], 'bit_depth': mode['bit_depth']})
        picam2.configure(preview_config)

        control_settings = {
            "AeMeteringMode": controls.AeMeteringModeEnum.Matrix,
            "AeConstraintMode": controls.AeConstraintModeEnum.Highlight,
            "AwbMode": controls.AwbModeEnum.Auto,
            "AfMetering": controls.AfMeteringEnum.Windows,
            "AfMode": controls.AfModeEnum.Auto,
            "Brightness": -0.1
        }
        
        picam2.controls.set_controls(control_settings)            
        time.sleep(1)    # Pause inserted to allow the camera get the white balance, and other auto settings       
        return picam2, capture_config
    
    except Exception as e:
        print(f"Error in set_camera: {str(e)}")
        return None, None

# Function to set the focus based on the sectors outlined in the AOI, and capture a photo
def set_focus_and_capture(picam2, rect, capture_config, file_path):
    try:        
        picam2.set_controls({"AfWindows": [rect]})
        success = picam2.autofocus_cycle()
        print("Focusing Camera...")
        time.sleep(0.1)
        print("Taking Photo...")
        picam2.switch_mode_and_capture_file(capture_config, file_path)
        print("Photo taken")
        return file_path
    
    except Exception as e:
        print(f"Error is set_focus_and_capture: {str(e)}")

The camera iterates over the AOI outlined in another script to set the autofocus. So, if there are 5 AOIs, it will take 5 pictures adjusting the focus for each AOI. To set up the AOIs when you start the program it takes an initial photo and prompts the user the make sectors using Inkscape and edit geometrical shapes. The shape's xml data is imported and converted to a text file that is read as coordinates.

There is a lot of code and different scripts, I don't want to make a wall of text here. I just need to find a way to compensate for fluctuating lighting conditions to allow my program to detect April Tags as best as possible.

@davidplowman
Copy link
Collaborator

Hi, there is unfortunately no way to adjust the weight of the differing metering zones at runtime.

However, you could add some simple AEC/AGC type processing of your own to adjust the exposure target so that you get a better result. I'd try something like this.

  1. Define a low resolution stream as part of your preview configuration which you can use to monitor the brightness of different parts of the image. Maybe set it to something like 256x192 to start with. A YUV420 image would do - you could just look at the greyscale part of the image (the first 192 rows, in this case, of the array you get back).

  2. Use numpy to find the average brightness of the area of interest. It it's too bright, set the EV to -0.5 (picam2.set_controls('ExposureValue': -0.5}). Wait a few frames for it to take effect.

  3. Now repeat. If it's still too bright, subtract another 0.5. If it's too dark, add 0.5. You'll have to experiment a bit, but I'm sure you get the idea.

Might that work for you?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants