Color Balance

This tutorial shows how to balance the color of a 2D image by taking images of a white surface (a piece of paper, wall, or similar) in a loop.

Camera facing the wall for color balance

First, we connect to the camera.

Go to source


camera = app.connect_camera()

Then we automatically configure 2D acquisition settings by taking images in a loop while tuning gain, exposure time, and aperture. The goal is for the maximum of mean RGB values to reach the value within defined limits.

Go to source


settings_2d = _auto_settings_configuration(camera)

We then capture an image and display it.

Go to source


rgba = camera.capture(settings_2d).image_rgba().copy_data()
display_rgb(rgba[:, :, 0:3], title="RGB image before color balance", block=False)

Then we run the calibration algorithm, which balances the color of RGB image by taking images of a white surface (a piece of paper, wall, or similar) in a loop.

Go to source


[red_balance, green_balance, blue_balance] = _color_balance_calibration(camera, settings_2d)

The complete implementation of the algorithm is given below.

Go to source


def _color_balance_calibration(camera: zivid.Camera, settings_2d: zivid.Settings2D) -> Tuple[float, float, float]:
    """Balance color for RGB image by taking images of white surface (piece of paper, wall, etc.) in a loop.

        camera: Zivid camera
        settings_2d: 2D capture settings

        corrected_red_balance: Corrected red balance
        corrected_green_balance: Corrected green balance
        corrected_blue_balance: Corrected blue balance

    print("Starting color balance calibration")

    corrected_red_balance = 1.0
    corrected_green_balance = 1.0
    corrected_blue_balance = 1.0

    saturated = False

    while True: = corrected_red_balance = corrected_green_balance = corrected_blue_balance
        rgba = camera.capture(settings_2d).image_rgba().copy_data()
        mean_color = _compute_mean_rgb(rgba[:, :, 0:3], 100)
        print(" Mean color values:")
        print(f"  R: {int(}")
        print(f"  G: {int(}")
        print(f"  B: {int(}")
        if int( == int( and int( == int(
            print("Color balance successful")
        if saturated is True:
            print("Color balance incomplete - the range limits of color balance parameters have been reached")
        max_color = max(float(, float(, float(
        corrected_red_balance = float(
            np.clip( * max_color /, 1, 8)
        corrected_green_balance = float(
            np.clip( * max_color /, 1, 8)
        corrected_blue_balance = float(
            np.clip( * max_color /, 1, 8)

        corrected_values = [corrected_red_balance, corrected_green_balance, corrected_blue_balance]

        if 1.0 in corrected_values or 8.0 in corrected_values:
            saturated = True
    print("Color balance:")
    print(f" Red: {corrected_red_balance}")
    print(f" Green: {corrected_green_balance}")
    print(f" Blue: {corrected_blue_balance}")

    return (corrected_red_balance, corrected_green_balance, corrected_blue_balance)

Lastly, we apply the color balance settings, capture a new image and display it.

Go to source

source = red_balance = green_balance = blue_balance
rgba_balanced = camera.capture(settings_2d).image_rgba().copy_data()
display_rgb(rgba_balanced[:, :, 0:3], title="RGB image after color balance", block=True)

The figure below shows the color image before and after applying color balance.

Color Balance: before on left, after on right