forked from raspberrypi/libcamera
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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>
- Loading branch information
Showing
3 changed files
with
120 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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') |