/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ // Original file Copyright Crytek GMBH or its affiliates, used under license. // Description : A collection of window functions with Finite Impulse Response FIR // and some helper window functions with Infinite Impulse Response IIR #pragma once #include #include /* #################################################################################################################### */ #ifndef M_PI #define M_PI 3.14159265358979323846 /* pi */ #endif //the original file was from cry's RC.exe with all the filters. We decided we would only use few of them for users namespace ImageProcessing { template F cube(const F& op) { return op * op * op; } template F square(F fOp) { return(fOp * fOp); } enum EWindowFunction { eWindowFunction_Combiner = 0, /*--------------- unit-area filters for unit-spaced samples ----------------*/ eWindowFunction_Point = 1, eWindowFunction_Box = 2, // box, pulse, Fourier window, 1st order (constant) b-spline eWindowFunction_Triangle = 3, // triangle, Bartlett window, 2nd order (linear) b-spline eWindowFunction_Linear = eWindowFunction_Triangle, eWindowFunction_Bartlett = eWindowFunction_Triangle, eWindowFunction_Quadric = 4, // 3rd order (quadratic) b-spline eWindowFunction_Bilinear = eWindowFunction_Quadric, eWindowFunction_Welch = eWindowFunction_Quadric, eWindowFunction_Cubic = 5, // 4th order (cubic) b-spline eWindowFunction_Hermite = 6, // 4th order (cubic hermite) b-spline eWindowFunction_Catrom = 7, // Catmull-Rom spline, Overhauser spline eWindowFunction_Sine = 8, // IIR eWindowFunction_Sinc = 9, // Sinc, perfect lowpass filter (infinite) eWindowFunction_Bessel = 10, // Bessel (for circularly symm. 2-d filt, inf) eWindowFunction_Lanczos = 11, // Lanczos filtering, windowed Sinc /*------------------ filters for non-unit spaced samples -------------------*/ eWindowFunction_Gaussian = 12, // Gaussian (infinite) eWindowFunction_Normal = 13, // Normal distribution (infinite) /*------------------------- parameterized filters --------------------------*/ eWindowFunction_Mitchell = 14, // Mitchell & Netravali's two-param cubic /*--------------------------- window functions -----------------------------*/ eWindowFunction_Hann = 15, // Hanning window eWindowFunction_BartlettHann = 16, eWindowFunction_Hamming = 17, // Hamming window eWindowFunction_Blackman = 18, // Blackman window eWindowFunction_BlackmanHarris = 19, eWindowFunction_BlackmanNuttall = 20, eWindowFunction_Flattop = 21, /*------------------------- parameterized windows --------------------------*/ eWindowFunction_Kaiser = 22, // parameterized Kaiser window /*---------------------------- custom windows ------------------------------*/ eWindowFunction_SigmaSix = 23, // two Normal distributions eWindowFunction_KaiserSinc = 24, // Kaiser and Sinc eWindowFunction_Num = eWindowFunction_KaiserSinc + 1, }; enum EWindowEvaluation { eWindowEvaluation_Sum, eWindowEvaluation_Max, eWindowEvaluation_Min, }; /* #################################################################################################################### */ template class IWindowFunction { public: virtual ~IWindowFunction() {} virtual const char* getName() const = 0; virtual T getLength() const = 0; virtual bool isCardinal() const = 0; virtual bool isInfinite() const = 0; virtual bool isUnitSpaced() const = 0; virtual bool isCentered() const = 0; public: virtual T operator () (T pos) const = 0; }; /* #################################################################################################################### * box, pulse, Fourier window, * box function also know as rectangle function * 1st order (constant) b-spline */ template class BoxWindowFunction : public IWindowFunction { public: virtual const char* getName() const { return "Box-window"; } virtual T getLength() const { return 0.5; } virtual bool isCardinal() const { return true; } virtual bool isInfinite() const { return false; } virtual bool isUnitSpaced() const { return true; } virtual bool isCentered() const { return true; } public: virtual T operator () (T pos) const { if (pos < 0.0) { pos = -pos; } if (pos <= 0.5) { return 1.0; } return 0.0; } }; /* -------------------------------------------------------------------------------------------------------------------- * triangle, Bartlett window, * triangle function also known as lambda function * 2nd order (linear) b-spline */ template class TriangleWindowFunction : public IWindowFunction { public: virtual const char* getName() const { return "Triangle-window"; } virtual T getLength() const { return 1.0; } virtual bool isCardinal() const { return true; } virtual bool isInfinite() const { return false; } virtual bool isUnitSpaced() const { return true; } virtual bool isCentered() const { return true; } public: virtual T operator () (T pos) const { if (pos < 0.0) { pos = -pos; } if (pos < 1.0) { return 1.0 - pos; } return 0.0; } }; /* #################################################################################################################### * 3rd order (quadratic) b-spline */ template class QuadricWindowFunction : public IWindowFunction { public: virtual const char* getName() const { return "Quadric-window"; } virtual T getLength() const { return 1.5; } virtual bool isCardinal() const { return false; } virtual bool isInfinite() const { return false; } virtual bool isUnitSpaced() const { return true; } virtual bool isCentered() const { return true; } public: virtual T operator () (T pos) const { if (pos < 0.0) { pos = -pos; } if (pos < 0.5) { return 0.75 - square(pos); } if (pos < 1.5) { return 0.50 * square(pos - 1.5); } return 0.0; } }; /* -------------------------------------------------------------------------------------------------------------------- * 4th order (cubic) b-spline */ template class CubicWindowFunction : public IWindowFunction { public: virtual const char* getName() const { return "Cubic-window"; } virtual T getLength() const { return 2.0; } virtual bool isCardinal() const { return false; } virtual bool isInfinite() const { return false; } virtual bool isUnitSpaced() const { return true; } virtual bool isCentered() const { return true; } public: virtual T operator () (T pos) const { if (pos < 0.0) { pos = -pos; } if (pos < 1.0) { return 0.5 * cube(pos) - square(pos) + 2.0 / 3.0; } if (pos < 2.0) { return cube(2.0 - pos) / 6.0; } return 0.0; } }; /* -------------------------------------------------------------------------------------------------------------------- * Hermite filter * f(x) = 2|x|^3 - 3|x|^2 + 1, -1 <= x <= 1 */ template class HermiteWindowFunction : public IWindowFunction { public: virtual const char* getName() const { return "Hermite-window"; } virtual T getLength() const { return 1.0; } virtual bool isCardinal() const { return false; } virtual bool isInfinite() const { return false; } virtual bool isUnitSpaced() const { return true; } virtual bool isCentered() const { return true; } public: virtual T operator () (T pos) const { if (pos < 0.0) { pos = -pos; } if (pos < 1.0) { return 2.0 * cube(pos) - 3.0 * square(pos) + 1.0; } return 0.0; } }; /* -------------------------------------------------------------------------------------------------------------------- * Catmull-Rom spline, Overhauser spline */ template class CatromWindowFunction : public IWindowFunction { public: CatromWindowFunction() { } public: virtual const char* getName() const { return "Catrom-window"; } virtual T getLength() const { return 2.0; } virtual bool isCardinal() const { return true; } virtual bool isInfinite() const { return false; } virtual bool isUnitSpaced() const { return false; } virtual bool isCentered() const { return true; } public: virtual T operator () (T pos) const { if (pos < 0.0) { pos = -pos; } if (pos < 1.0) { return 1.5 * cube(pos) - 2.5 * square(pos) + 1.0; } if (pos < 2.0) { return -0.5 * cube(pos) + 2.5 * square(pos) - 4.0 * pos + 2.0; } return 0.0; } }; /* #################################################################################################################### */ template class SineWindowFunction : public IWindowFunction { public: virtual const char* getName() const { return "Sine-window"; } virtual T getLength() const { return 0.0; } virtual bool isCardinal() const { return true; } virtual bool isInfinite() const { return true; } virtual bool isUnitSpaced() const { return true; } virtual bool isCentered() const { return true; } public: virtual T operator () (T pos) const { return sin(pos); } }; /* -------------------------------------------------------------------------------------------------------------------- * sinc, perfect lowpass filter (infinite) * * Note: Some people say sinc(x) is sin(x)/x. Others say it's * sin(PI*x)/(PI*x), a horizontal compression of the former which is * zero at integer values. We use the latter, whose Fourier transform * is a canonical rectangle function (edges at -1/2, +1/2, height 1). */ template class SincWindowFunction : public IWindowFunction { public: virtual const char* getName() const { return "Sinc-window"; } virtual T getLength() const { return 4.0; } virtual bool isCardinal() const { return true; } virtual bool isInfinite() const { return true; } virtual bool isUnitSpaced() const { return false; } virtual bool isCentered() const { return true; } public: virtual T operator () (T pos) const { if (pos == 0.0) { return 1.0; } return sin(M_PI * pos) / (M_PI * pos); } }; /* -------------------------------------------------------------------------------------------------------------------- * Bessel (for circularly symm. 2-d filt, infinite) * See Pratt "Digital Image Processing" p. 97 for Bessel functions */ template class BesselWindowFunction : public IWindowFunction { public: virtual const char* getName() const { return "Bessel-window"; } virtual T getLength() const { return 3.2383; } virtual bool isCardinal() const { return false; } virtual bool isInfinite() const { return true; } virtual bool isUnitSpaced() const { return false; } virtual bool isCentered() const { return true; } public: virtual T operator () (T pos) const { if (pos == 0.0) { return M_PI / 4.0; } return AZ_TRAIT_IMAGEPROCESSING_BESSEL_FUNCTION_FIRST_ORDER(M_PI * pos) / (2.0 * pos); } }; /* -------------------------------------------------------------------------------------------------------------------- * Lanczos filter */ template class LanczosWindowFunction : public SincWindowFunction { public: LanczosWindowFunction(T tap = 3.0) { this->tap = AZ::GetMax(3.0, tap); } protected: T tap; public: virtual const char* getName() const { return "Lanczos-window"; } virtual T getLength() const { return tap; } virtual bool isCardinal() const { return false; } virtual bool isInfinite() const { return false; } virtual bool isUnitSpaced() const { return false; } virtual bool isCentered() const { return true; } public: virtual T operator () (T pos) const { if (pos < 0.0) { pos = -pos; } if (pos < tap) { return ((SincWindowFunction) * this)(pos) * ((SincWindowFunction) * this)(pos / tap); } return 0.0; } }; /* -------------------------------------------------------------------------------------------------------------------- * Gaussian filter (infinite) */ template class GaussianWindowFunction : public IWindowFunction { public: virtual const char* getName() const { return "Gaussian-window"; } virtual T getLength() const { return 1.25; } virtual bool isCardinal() const { return false; } virtual bool isInfinite() const { return true; } virtual bool isUnitSpaced() const { return true; } virtual bool isCentered() const { return true; } public: virtual T operator () (T pos) const { return exp(-2.0 * square(pos)) * sqrt(2.0 / M_PI); } }; /* -------------------------------------------------------------------------------------------------------------------- * normal distribution (infinite) * Normal(x) = Gaussian(x/2)/2 */ template class NormalWindowFunction : public IWindowFunction { public: virtual const char* getName() const { return "Normal-window"; } virtual T getLength() const { return 2.5; } virtual bool isCardinal() const { return false; } virtual bool isInfinite() const { return true; } virtual bool isUnitSpaced() const { return false; } virtual bool isCentered() const { return true; } public: virtual T operator () (T pos) const { return exp(-square(pos) / 2.0) / sqrt(2.0 * M_PI); } }; /* -------------------------------------------------------------------------------------------------------------------- */ template class SigmaSixWindowFunction : public IWindowFunction { public: SigmaSixWindowFunction(T diameter = 1.0, T negative = 0.0) { // we aim for 6 * sigma = 99,99996% of all values const T sigma = 1.0 / 3.0; s2 = sigma * sigma * 2.0; d2 = s2 / (diameter * diameter); d = diameter; n = negative; } protected: T s2, d2, d, n; public: virtual const char* getName() const { return "SigmaSix-window"; } virtual T getLength() const { return 1.44; } virtual bool isCardinal() const { return false; } virtual bool isInfinite() const { return true; } virtual bool isUnitSpaced() const { return false; } virtual bool isCentered() const { return true; } public: virtual T operator () (T pos) const { if (pos < 0.0) { pos = -pos; } T o = exp(-square(pos) / s2) - (1.0 - 0.9999996); T i = exp(-square(pos) / d2) - (1.0 - 0.9999996); return (pos >= d ? 0.0 : i) - o * n; } }; /* -------------------------------------------------------------------------------------------------------------------- * Mitchell & Netravali's two-param cubic * see Mitchell & Netravali, * "Reconstruction Filters in Computer Graphics", SIGGRAPH 88 */ template class MitchellWindowFunction : public IWindowFunction { public: MitchellWindowFunction(T b = 1.0 / 3.0, T c = 1.0 / 3.0) { p0 = (6. - 2. * b) / 6.; p2 = (-18. + 12. * b + 6. * c) / 6.; p3 = (12. - 9. * b - 6. * c) / 6.; q0 = (8. * b + 24. * c) / 6.; q1 = (-12. * b - 48. * c) / 6.; q2 = (6. * b + 30. * c) / 6.; q3 = (-b - 6. * c) / 6.; } protected: T p0, p2, p3, q0, q1, q2, q3; public: virtual const char* getName() const { return "Mitchell-window"; } virtual T getLength() const { return 2.0; } virtual bool isCardinal() const { return false; } virtual bool isInfinite() const { return false; } virtual bool isUnitSpaced() const { return false; } virtual bool isCentered() const { return true; } public: virtual T operator () (T pos) const { if (pos < 0.0) { pos = -pos; } if (pos < 1.0) { return p3 * cube(pos) + p2 * square(pos) + p0; } if (pos < 2.0) { return q3 * cube(pos) + q2 * square(pos) + q1 * pos + q0; } return 0.0; } }; /* #################################################################################################################### * Hanning window (infinite) */ template class HannWindowFunction : public IWindowFunction { public: virtual const char* getName() const { return "Hann-window"; } virtual T getLength() const { return 1.0; } virtual bool isCardinal() const { return true; } virtual bool isInfinite() const { return true; } virtual bool isUnitSpaced() const { return true; } virtual bool isCentered() const { return true; } public: virtual T operator () (T pos) const { return 0.5 + 0.5 * cos(M_PI * pos); } }; /* -------------------------------------------------------------------------------------------------------------------- * BartlettHanning window (infinite) */ template class BartlettHannWindowFunction : public IWindowFunction { public: virtual const char* getName() const { return "Bartlett-Hann-window"; } virtual T getLength() const { return 1.0; } virtual bool isCardinal() const { return true; } virtual bool isInfinite() const { return true; } virtual bool isUnitSpaced() const { return true; } virtual bool isCentered() const { return true; } public: virtual T operator () (T pos) const { return 0.62 + 0.48 * (1.0 - pos) + 0.38 * cos(M_PI * pos); } }; /* -------------------------------------------------------------------------------------------------------------------- * Hamming window (infinite) */ template class HammingWindowFunction : public IWindowFunction { public: virtual const char* getName() const { return "Hamming-window"; } virtual T getLength() const { return 1.0; } virtual bool isCardinal() const { return true; } virtual bool isInfinite() const { return true; } virtual bool isUnitSpaced() const { return true; } virtual bool isCentered() const { return true; } public: virtual T operator () (T pos) const { return 0.53836 + 0.46164 * cos(M_PI * pos); } }; /* -------------------------------------------------------------------------------------------------------------------- * Blackman window (infinite) */ template class BlackmanWindowFunction : public IWindowFunction { public: virtual const char* getName() const { return "Blackman-window"; } virtual T getLength() const { return 1.0; } virtual bool isCardinal() const { return true; } virtual bool isInfinite() const { return true; } virtual bool isUnitSpaced() const { return true; } virtual bool isCentered() const { return true; } public: virtual T operator () (T pos) const { return 0.42659 + 0.49656 * cos(M_PI * pos) + 0.07685 * cos(2.0 * M_PI * pos); } }; /* -------------------------------------------------------------------------------------------------------------------- * BlackmanHarris window (infinite) */ template class BlackmanHarrisWindowFunction : public IWindowFunction { public: virtual const char* getName() const { return "Blackman-Harris-window"; } virtual T getLength() const { return 1.0; } virtual bool isCardinal() const { return true; } virtual bool isInfinite() const { return true; } virtual bool isUnitSpaced() const { return true; } virtual bool isCentered() const { return true; } public: virtual T operator () (T pos) const { return 0.35875 + 0.48829 * cos(M_PI * pos) + 0.14128 * cos(2.0 * M_PI * pos) + 0.01168 * cos(3.0 * M_PI * pos); } }; /* -------------------------------------------------------------------------------------------------------------------- * BlackmanNuttall window (infinite) */ template class BlackmanNuttallWindowFunction : public IWindowFunction { public: virtual const char* getName() const { return "Blackman-Nuttall-window"; } virtual T getLength() const { return 1.0; } virtual bool isCardinal() const { return true; } virtual bool isInfinite() const { return true; } virtual bool isUnitSpaced() const { return true; } virtual bool isCentered() const { return true; } public: virtual T operator () (T pos) const { return 0.3635819 + 0.4891775 * cos(M_PI * pos) + 0.1365995 * cos(2.0 * M_PI * pos) + 0.0106411 * cos(3.0 * M_PI * pos); } }; /* -------------------------------------------------------------------------------------------------------------------- * FlatTop window (infinite) */ template class FlatTopWindowFunction : public IWindowFunction { public: virtual const char* getName() const { return "Flat-Top-window"; } virtual T getLength() const { return 1.0; } virtual bool isCardinal() const { return true; } virtual bool isInfinite() const { return true; } virtual bool isUnitSpaced() const { return true; } virtual bool isCentered() const { return true; } public: virtual T operator () (T pos) const { return 0.215578948 + 0.416631580 * cos(M_PI * pos) + 0.277263158 * cos(2.0 * M_PI * pos) + 0.083578947 * cos(3.0 * M_PI * pos) + 0.006947368 * cos(4.0 * M_PI * pos); } }; /* -------------------------------------------------------------------------------------------------------------------- * parameterized Kaiser window (infinite) * from Oppenheim & Schafer, Hamming */ template class KaiserWindowFunction : public IWindowFunction { public: KaiserWindowFunction(T a = 6.5) { /* typically 4a = a; this->i0a = 1. / bessel_i0(a); } protected: T a, i0a; /* modified zeroth order Bessel function of the first kind. */ static T bessel_i0(T x) { #define EPSILON 1e-7 const T y = square(x) / 4.0; T sum = 1.0; T t = y; for (int i = 2; t > EPSILON; i++) { sum += t; t *= y / square(i); } return sum; #undef EPSILON } public: virtual const char* getName() const { return "Kaiser-window"; } virtual T getLength() const { return 1.0; } virtual bool isCardinal() const { return true; } virtual bool isInfinite() const { return true; } virtual bool isUnitSpaced() const { return true; } virtual bool isCentered() const { return true; } public: virtual T operator () (T pos) const { return i0a * bessel_i0(a * sqrt(1.0 - square(pos))); } }; /* #################################################################################################################### */ template class CombinerWindowFunction : public IWindowFunction { public: CombinerWindowFunction(IWindowFunction* fu, IWindowFunction* wi) { shaper = fu; restrictor = wi; } protected: IWindowFunction* shaper; IWindowFunction* restrictor; public: virtual const char* getName() const { return "Combiner of two window-generators"; } virtual T getLength() const { return shaper->getLength(); } virtual bool isCardinal() const { return shaper->isCardinal() && restrictor->isCardinal(); } virtual bool isInfinite() const { return shaper->isInfinite() && restrictor->isInfinite(); } virtual bool isUnitSpaced() const { return shaper->isUnitSpaced() && restrictor->isUnitSpaced(); } virtual bool isCentered() const { return shaper->isCentered() && restrictor->isCentered(); } public: virtual T operator () (T pos) const { return (*shaper)(pos) * (*restrictor)(pos / shaper->getLength()); } }; /* -------------------------------------------------------------------------------------------------------------------- */ template class PointWindowFunction : public BoxWindowFunction { public: PointWindowFunction() : BoxWindowFunction() { } public: virtual const char* getName() const { return "Point-window"; } virtual T getLength() const { return 0.0; } }; } //end namespace ImageProcessing