[2/2] utils: raspberrypi: ctt: Fix NaNs in chromatic aberration tables
diff mbox series

Message ID 20250428103604.151551-3-david.plowman@raspberrypi.com
State Accepted
Commit 17e41b2a3a144a80e60f28e15a4c2aaa42c87105
Headers show
Series
  • Raspberry Pi Camera Tuning Tool fixes
Related show

Commit Message

David Plowman April 28, 2025, 10:36 a.m. UTC
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@raspberrypi.com>
---
 utils/raspberrypi/ctt/ctt.py     |  9 ++++++---
 utils/raspberrypi/ctt/ctt_cac.py | 32 +++++++++++++++++++++++++++-----
 2 files changed, 33 insertions(+), 8 deletions(-)

Comments

Naushir Patuck April 28, 2025, 1:20 p.m. UTC | #1
Hi David,

On Mon, 28 Apr 2025 at 11:36, David Plowman
<david.plowman@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@raspberrypi.com>

Reviewed-by: Naushir Patuck <naush@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
>

Patch
diff mbox series

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!'