[libcamera-devel] [PATCH v3 02/12] utils: tuning: libtuning: Implement math helpers
Laurent Pinchart
laurent.pinchart at ideasonboard.com
Wed Nov 23 02:35:46 CET 2022
Hi Paul,
Thank you for the patch.
On Fri, Nov 11, 2022 at 02:31:44AM +0900, Paul Elder via libcamera-devel wrote:
> Implement math helpers for libtuning. This includes:
> - Average, a wrapper class for numpy averaging functions
> - Gradient, a class that represents gradients, for distributing and
> mapping
> - Smoothing, a wrapper class for cv2 smoothing functions
>
> Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>
>
> ---
> Changes in v3:
> - Newly split from the first patch "utils: tuning: libtuning: Implement
> the core of libtuning"
> - See changelog from that patch
> ---
> utils/tuning/libtuning/average.py | 21 ++++++++
> utils/tuning/libtuning/gradient.py | 75 +++++++++++++++++++++++++++++
> utils/tuning/libtuning/smoothing.py | 24 +++++++++
> 3 files changed, 120 insertions(+)
> create mode 100644 utils/tuning/libtuning/average.py
> create mode 100644 utils/tuning/libtuning/gradient.py
> create mode 100644 utils/tuning/libtuning/smoothing.py
>
> diff --git a/utils/tuning/libtuning/average.py b/utils/tuning/libtuning/average.py
> new file mode 100644
> index 00000000..e28770d7
> --- /dev/null
> +++ b/utils/tuning/libtuning/average.py
> @@ -0,0 +1,21 @@
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +#
> +# Copyright (C) 2022, Paul Elder <paul.elder at ideasonboard.com>
> +#
> +# average.py - Wrapper for numpy averaging functions to enable duck-typing
> +
> +import numpy as np
> +
> +
> +# @brief Wrapper for np averaging functions so that they can be duck-typed
> +class Average(object):
> + def __init__(self):
> + pass
> +
> + def average(self, np_array):
> + raise NotImplementedError
> +
> +
> +class Mean(Average):
> + def average(self, np_array):
> + return np.mean(np_array)
> diff --git a/utils/tuning/libtuning/gradient.py b/utils/tuning/libtuning/gradient.py
> new file mode 100644
> index 00000000..64a96369
> --- /dev/null
> +++ b/utils/tuning/libtuning/gradient.py
> @@ -0,0 +1,75 @@
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +#
> +# Copyright (C) 2022, Paul Elder <paul.elder at ideasonboard.com>
> +#
> +# gradient.py - Gradients that can be used to distribute or map numbers
> +
> +import libtuning as lt
> +
> +import math
> +from numbers import Number
> +
> +
> +# @brief Gradient for how to allocate pixels to sectors
> +# @description There are no parameters for the gradients as the domain is the
> +# number of pixels and the range is the number of sectors, and
> +# there is only one curve that has a startpoint and endpoint at
> +# (0, 0) and at (#pixels, #sectors). The exception is for curves
> +# that *do* have multiple solutions for only two points, such as
> +# gaussian, and curves of higher polynomial orders if we had them.
> +#
> +# \todo There will probably be a helper in the Gradient class, as I have a
> +# feeling that all the other curves (besides Linear and Gaussian) can be
> +# implemented in the same way.
> +class Gradient(object):
> + def __init__(self):
> + pass
> +
> + # @brief Distribute pixels into sectors (only in one dimension)
> + # @param domain Number of pixels
> + # @param sectors Number of sectors
> + # @return A list of number of pixels in each sector
> + def distribute(self, domain: list, sectors: list, ) -> list:
Is the training ', ' a Python syntax I don't know about ?
Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> + raise NotImplementedError
> +
> + # @brief Map a number on a curve
> + # @param domain Domain of the curve
> + # @param rang Range of the curve
> + # @param x Input on the domain of the curve
> + # @return y from the range of the curve
> + def map(self, domain: tuple, rang: tuple, x: Number) -> Number:
> + raise NotImplementedError
> +
> +
> +class Linear(Gradient):
> + # @param remainder Mode of handling remainder
> + def __init__(self, remainder: lt.Remainder = lt.Remainder.Float):
> + self.remainder = remainder
> +
> + def distribute(self, domain: list, sectors: list) -> list:
> + size = domain / sectors
> + rem = domain % sectors
> +
> + if rem == 0:
> + return [int(size)] * sectors
> +
> + size = math.ceil(size)
> + rem = domain % size
> + output_sectors = [int(size)] * (sectors - 1)
> +
> + if self.remainder == lt.Remainder.Float:
> + size = domain / sectors
> + output_sectors = [size] * sectors
> + elif self.remainder == lt.Remainder.DistributeFront:
> + output_sectors.append(int(rem))
> + elif self.remainder == lt.Remainder.DistributeBack:
> + output_sectors.insert(0, int(rem))
> + else:
> + raise ValueError
> +
> + return output_sectors
> +
> + def map(self, domain: tuple, rang: tuple, x: Number) -> Number:
> + m = (rang[1] - rang[0]) / (domain[1] - domain[0])
> + b = rang[0] - m * domain[0]
> + return m * x + b
> diff --git a/utils/tuning/libtuning/smoothing.py b/utils/tuning/libtuning/smoothing.py
> new file mode 100644
> index 00000000..b8a5a242
> --- /dev/null
> +++ b/utils/tuning/libtuning/smoothing.py
> @@ -0,0 +1,24 @@
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +#
> +# Copyright (C) 2022, Paul Elder <paul.elder at ideasonboard.com>
> +#
> +# smoothing.py - Wrapper for cv2 smoothing functions to enable duck-typing
> +
> +import cv2
> +
> +
> +# @brief Wrapper for cv2 smoothing functions so that they can be duck-typed
> +class Smoothing(object):
> + def __init__(self):
> + pass
> +
> + def smoothing(self, src):
> + raise NotImplementedError
> +
> +
> +class MedianBlur(Smoothing):
> + def __init__(self, ksize):
> + self.ksize = ksize
> +
> + def smoothing(self, src):
> + return cv2.medianBlur(src.astype('float32'), self.ksize).astype('float64')
--
Regards,
Laurent Pinchart
More information about the libcamera-devel
mailing list