[libcamera-devel] [PATCH] py: cam: Fix demosaic overflow issue

Laurent Pinchart laurent.pinchart at ideasonboard.com
Mon Mar 13 09:13:02 CET 2023


Hi Tomi,

Thank you for the patch.

On Mon, Mar 13, 2023 at 09:28:13AM +0200, Tomi Valkeinen via libcamera-devel wrote:
> The demosaic code first expands the buffer datatype to uint16, and then
> shifts the data left so that the 8, 10 and 12 bitspp formats all become
> 16 bitspp.
> 
> It then, eventually, uses np.einsum to calculate averages, but this
> averaging sums multiple uint16 values together, and stores them in
> uint16 storage. As in the first step we shifted the values left,
> possibly getting values close to the maximum of uint16 range, we, of
> course, overflow when summing them together. This leads to rather bad
> looking images.
> 
> Fix this by dropping the original shift. It serves no purpose, and is
> probably a remnant of some early testing code. This way the largest
> numbers we are summing together are 12 bit values, and as we use a 3x3
> window from which we fetch values, for a single rgb plane, the max
> number of 12 bit values is 5 (for green). Sum of 5 12 bit values is well
> below the 16 bit maximum.
> 
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen at ideasonboard.com>

Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>

> ---
>  src/py/cam/helpers.py | 6 ++----
>  1 file changed, 2 insertions(+), 4 deletions(-)
> 
> diff --git a/src/py/cam/helpers.py b/src/py/cam/helpers.py
> index 6b32a134..2d906667 100644
> --- a/src/py/cam/helpers.py
> +++ b/src/py/cam/helpers.py
> @@ -117,14 +117,12 @@ def to_rgb(fmt, size, data):
>          bayer_pattern = fmt[1:5]
>          bitspp = int(fmt[5:])
>  
> -        # \todo shifting leaves the lowest bits 0
>          if bitspp == 8:
>              data = data.reshape((h, w))
> -            data = data.astype(np.uint16) << 8
> +            data = data.astype(np.uint16)
>          elif bitspp in [10, 12]:
>              data = data.view(np.uint16)
>              data = data.reshape((h, w))
> -            data = data << (16 - bitspp)
>          else:
>              raise Exception('Bad bitspp:' + str(bitspp))
>  
> @@ -145,7 +143,7 @@ def to_rgb(fmt, size, data):
>          b0 = (idx % 2, idx // 2)
>  
>          rgb = demosaic(data, r0, g0, g1, b0)
> -        rgb = (rgb >> 8).astype(np.uint8)
> +        rgb = (rgb >> (bitspp - 8)).astype(np.uint8)
>  
>      else:
>          rgb = None

-- 
Regards,

Laurent Pinchart


More information about the libcamera-devel mailing list