summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Elder <paul.elder@ideasonboard.com>2022-11-11 02:05:53 +0900
committerPaul Elder <paul.elder@ideasonboard.com>2022-11-25 15:37:26 +0900
commitdb99d966633c5d7a5b33d03d653f1839d9feaaea (patch)
tree392733c7b0bfc3fb06a865a1f990db65a0af8bf6
parent19dc8c28f63c2dc8842b88c1fd45c999c7171398 (diff)
utils: tuning: libtuning: Implement math helpers
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@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-rw-r--r--utils/tuning/libtuning/average.py21
-rw-r--r--utils/tuning/libtuning/gradient.py75
-rw-r--r--utils/tuning/libtuning/smoothing.py24
3 files changed, 120 insertions, 0 deletions
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@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..5106f821
--- /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@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:
+ 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@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')