[PATCH 2/2] utils: raspberrypi: ctt: Fix NaNs in chromatic aberration tables

Naushir Patuck naush at raspberrypi.com
Mon Apr 28 15:20:47 CEST 2025


Hi David,

On Mon, 28 Apr 2025 at 11:36, David Plowman
<david.plowman at raspberrypi.com> wrote:
>
> NaNs can appear if no black dots can be found and analysed in a
> particular region of the calibration image. There needs to be at least
> one such dot in every 8x8 cell covering the image.
>
> This is now detected, and an error message issued. No CAC tables are
> generated, so CAC is disabled.
>
> Signed-off-by: David Plowman <david.plowman at raspberrypi.com>

Reviewed-by: Naushir Patuck <naush at raspberrypi.com>

> ---
>  utils/raspberrypi/ctt/ctt.py     |  9 ++++++---
>  utils/raspberrypi/ctt/ctt_cac.py | 32 +++++++++++++++++++++++++++-----
>  2 files changed, 33 insertions(+), 8 deletions(-)
>
> diff --git a/utils/raspberrypi/ctt/ctt.py b/utils/raspberrypi/ctt/ctt.py
> index 96f1b5e6..186afda5 100755
> --- a/utils/raspberrypi/ctt/ctt.py
> +++ b/utils/raspberrypi/ctt/ctt.py
> @@ -198,9 +198,12 @@ class Camera:
>          """
>          Write output to json
>          """
> -        self.json['rpi.cac']['cac'] = cacs
> -        self.log += '\nCAC calibration written to json file'
> -        print('Finished CAC calibration')
> +        if cacs:
> +            self.json['rpi.cac']['cac'] = cacs
> +            self.log += '\nCAC calibration written to json file'
> +            print('Finished CAC calibration')
> +        else:
> +            self.log += "\nCAC calibration failed"
>
>
>      """
> diff --git a/utils/raspberrypi/ctt/ctt_cac.py b/utils/raspberrypi/ctt/ctt_cac.py
> index 5a4c5101..a1183989 100644
> --- a/utils/raspberrypi/ctt/ctt_cac.py
> +++ b/utils/raspberrypi/ctt/ctt_cac.py
> @@ -108,12 +108,29 @@ def shifts_to_yaml(red_shift, blue_shift, image_dimensions, output_grid_size=9):
>          ybsgrid[xgridloc][ygridloc].append(blue_shift[3])
>
>      # Now calculate the average pixel shift for each square in the grid
> +    grid_incomplete = False
>      for x in range(output_grid_size - 1):
>          for y in range(output_grid_size - 1):
> -            xrgrid[x, y] = np.mean(xrsgrid[x][y])
> -            yrgrid[x, y] = np.mean(yrsgrid[x][y])
> -            xbgrid[x, y] = np.mean(xbsgrid[x][y])
> -            ybgrid[x, y] = np.mean(ybsgrid[x][y])
> +            if xrsgrid[x][y]:
> +                xrgrid[x, y] = np.mean(xrsgrid[x][y])
> +            else:
> +                grid_incomplete = True
> +            if yrsgrid[x][y]:
> +                yrgrid[x, y] = np.mean(yrsgrid[x][y])
> +            else:
> +                grid_incomplete = True
> +            if xbsgrid[x][y]:
> +                xbgrid[x, y] = np.mean(xbsgrid[x][y])
> +            else:
> +                grid_incomplete = True
> +            if ybsgrid[x][y]:
> +                ybgrid[x, y] = np.mean(ybsgrid[x][y])
> +            else:
> +                grid_incomplete = True
> +
> +    if grid_incomplete:
> +        raise RuntimeError("\nERROR: CAC measurements do not span the image!"
> +                           "\nConsider using improved CAC images, or remove them entirely.\n")
>
>      # Next, we start to interpolate the central points of the grid that gets passed to the tuning file
>      input_grids = np.array([xrgrid, yrgrid, xbgrid, ybgrid])
> @@ -219,7 +236,12 @@ def cac(Cam):
>      # tuning file
>      print("\nCreating output grid")
>      Cam.log += '\nCreating output grid'
> -    rx, ry, bx, by = shifts_to_yaml(red_shift, blue_shift, image_size)
> +    try:
> +        rx, ry, bx, by = shifts_to_yaml(red_shift, blue_shift, image_size)
> +    except RuntimeError as e:
> +        print(str(e))
> +        Cam.log += "\nCAC correction failed! CAC will not be enabled."
> +        return {}
>
>      print("CAC correction complete!")
>      Cam.log += '\nCAC correction complete!'
> --
> 2.34.1
>


More information about the libcamera-devel mailing list