• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2016 The TensorFlow Authors. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7     http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 
16 #ifndef TENSORFLOW_CORE_KERNELS_SAMPLING_KERNELS_H_
17 #define TENSORFLOW_CORE_KERNELS_SAMPLING_KERNELS_H_
18 
19 #include <cmath>
20 
21 #include "tensorflow/core/lib/core/stringpiece.h"
22 
23 namespace tensorflow {
24 namespace functor {
25 // Defines functions for different types of sampling kernels.
26 enum SamplingKernelType {
27   // Lanczos kernel with radius 1.  Aliases but does not ring.
28   Lanczos1Kernel,
29 
30   // Lanczos kernel with radius 3.  High-quality practical filter but may have
31   // some ringing especially on synthetic images.
32   Lanczos3Kernel,
33 
34   // Lanczos kernel with radius 5.  Very-high-quality filter but may have
35   // stronger ringing.
36   Lanczos5Kernel,
37 
38   // Gaussian kernel with radius 3, sigma = 1.5 / 3.  Less commonly used.
39   GaussianKernel,
40 
41   // Rectangle function.  Equivalent to "nearest" sampling when upscaling.
42   // Has value 1 in interval (-0.5, 0.5), value 0.5 on edge, and 0 elsewhere.
43   BoxKernel,
44 
45   // Hat/tent function with radius 1.  Equivalent to "bilinear" reconstruction
46   // when upsampling.
47   // Has value zero at -1.0 and 1.0.
48   TriangleKernel,
49 
50   // Cubic interpolant of Keys.  Equivalent to Catmull-Rom kernel.  Reasonably
51   // good quality and faster than Lanczos3Kernel.
52   KeysCubicKernel,
53 
54   // Cubic non-interpolating scheme.  For synthetic images (especially those
55   // lacking proper prefiltering), less ringing than Keys cubic kernel but less
56   // sharp.
57   MitchellCubicKernel,
58 
59   // Always insert new kernel types before this.
60   SamplingKernelTypeEnd
61 };
62 
63 // Converts a string into the corresponding kernel type.
64 // Returns SamplingKernelTypeEnd if the string couldn't be converted.
65 SamplingKernelType SamplingKernelTypeFromString(const StringPiece str);
66 
67 // A function object for a Lanczos kernel.
68 struct LanczosKernelFunc {
69   // Pass 1 for Lanczos1 kernel, 3 for Lanczos3 etc.
LanczosKernelFuncLanczosKernelFunc70   explicit LanczosKernelFunc(float _radius) : radius(_radius) {}
operatorLanczosKernelFunc71   float operator()(float x) const {
72     constexpr float kPI = 3.14159265359;
73     x = std::abs(x);
74     if (x > radius) return 0.0;
75     // Need to special case the limit case of sin(x) / x when x is zero.
76     if (x <= 1e-3) {
77       return 1.0;
78     }
79     return radius * std::sin(kPI * x) * std::sin(kPI * x / radius) /
80            (kPI * kPI * x * x);
81   }
RadiusLanczosKernelFunc82   float Radius() const { return radius; }
83   const float radius;
84 };
85 
86 struct GaussianKernelFunc {
87   static constexpr float kRadiusMultiplier = 3.0f;
88   // https://en.wikipedia.org/wiki/Gaussian_function
89   // We use sigma = 0.5, as suggested on p. 4 of Ken Turkowski's "Filters
90   // for Common Resampling Tasks" for kernels with a support of 3 pixels:
91   // www.realitypixels.com/turk/computergraphics/ResamplingFilters.pdf
92   // This implies a radius of 1.5,
93   explicit GaussianKernelFunc(float _radius = 1.5f)
radiusGaussianKernelFunc94       : radius(_radius), sigma(_radius / kRadiusMultiplier) {}
operatorGaussianKernelFunc95   float operator()(float x) const {
96     x = std::abs(x);
97     if (x >= radius) return 0.0;
98     return std::exp(-x * x / (2.0 * sigma * sigma));
99   }
RadiusGaussianKernelFunc100   float Radius() const { return radius; }
101   const float radius;
102   const float sigma;  // Gaussian standard deviation
103 };
104 
105 struct BoxKernelFunc {
operatorBoxKernelFunc106   float operator()(float x) const {
107     x = std::abs(x);
108     return x < 0.5f ? 1. : x == 0.5f ? 0.5f : 0.0f;
109   }
RadiusBoxKernelFunc110   float Radius() const { return 1.f; }
111 };
112 
113 struct TriangleKernelFunc {
114   // https://en.wikipedia.org/wiki/Triangle_function
operatorTriangleKernelFunc115   float operator()(float x) const {
116     x = std::abs(x);
117     return x < 1.0f ? 1.0f - x : 0.0f;
118   }
RadiusTriangleKernelFunc119   float Radius() const { return 1.f; }
120 };
121 
122 struct KeysCubicKernelFunc {
123   // http://ieeexplore.ieee.org/document/1163711/
124   // R. G. Keys. Cubic convolution interpolation for digital image
125   // processing. IEEE Transactions on Acoustics, Speech, and Signal
126   // Processing, 29(6):1153–1160, 1981.
operatorKeysCubicKernelFunc127   float operator()(float x) const {
128     x = std::abs(x);
129     if (x >= 2.0f) {
130       return 0.0f;
131     } else if (x >= 1.0f) {
132       return ((-0.5f * x + 2.5f) * x - 4.0f) * x + 2.0f;
133     } else {
134       return ((1.5f * x - 2.5f) * x) * x + 1.0f;
135     }
136   }
RadiusKeysCubicKernelFunc137   float Radius() const { return 2.f; }
138 };
139 
140 struct MitchellCubicKernelFunc {
141   // https://doi.org/10.1145/378456.378514
142   // D. P. Mitchell and A. N. Netravali. Reconstruction filters in computer
143   // graphics.  Computer Graphics (Proceedings of ACM SIGGRAPH 1988),
144   // 22(4):221–228, 1988.
operatorMitchellCubicKernelFunc145   float operator()(float x) const {
146     x = std::abs(x);
147     if (x >= 2.0f) {
148       return 0.0f;
149     } else if (x >= 1.0f) {
150       return (((-7.0f / 18.0f) * x + 2.0f) * x - 10.0f / 3.0f) * x +
151              16.0f / 9.0f;
152     } else {
153       return (((7.0f / 6.0f) * x - 2.0f) * x) * x + 8.0f / 9.0f;
154     }
155   }
RadiusMitchellCubicKernelFunc156   float Radius() const { return 2.f; }
157 };
158 
CreateLanczos1Kernel()159 inline LanczosKernelFunc CreateLanczos1Kernel() {
160   return LanczosKernelFunc(1.0);
161 }
162 
CreateLanczos3Kernel()163 inline LanczosKernelFunc CreateLanczos3Kernel() {
164   return LanczosKernelFunc(3.0);
165 }
166 
CreateLanczos5Kernel()167 inline LanczosKernelFunc CreateLanczos5Kernel() {
168   return LanczosKernelFunc(5.0);
169 }
170 
CreateGaussianKernel()171 inline GaussianKernelFunc CreateGaussianKernel() {
172   return GaussianKernelFunc(1.5);
173 }
174 
CreateBoxKernel()175 inline BoxKernelFunc CreateBoxKernel() { return BoxKernelFunc(); }
176 
CreateTriangleKernel()177 inline TriangleKernelFunc CreateTriangleKernel() {
178   return TriangleKernelFunc();
179 }
180 
CreateKeysCubicKernel()181 inline KeysCubicKernelFunc CreateKeysCubicKernel() {
182   return KeysCubicKernelFunc();
183 }
184 
CreateMitchellCubicKernel()185 inline MitchellCubicKernelFunc CreateMitchellCubicKernel() {
186   return MitchellCubicKernelFunc();
187 }
188 
189 }  // namespace functor
190 }  // namespace tensorflow
191 
192 #endif  // TENSORFLOW_CORE_KERNELS_SAMPLING_KERNELS_H_
193