\r
__device__ __forceinline__ elem_type operator ()(float y, float x) const\r
{\r
- return src(__float2int_rd(y), __float2int_rd(x));\r
+ return src(__float2int_rn(y), __float2int_rn(x));\r
}\r
\r
const Ptr2D src;\r
\r
work_type out = VecTraits<work_type>::all(0);\r
\r
- x -= 0.5f;\r
- y -= 0.5f;\r
-\r
const int x1 = __float2int_rd(x);\r
const int y1 = __float2int_rd(y);\r
const int x2 = x1 + 1;\r
\r
explicit __host__ __device__ __forceinline__ CubicFilter(const Ptr2D& src_) : src(src_) {}\r
\r
- static __device__ __forceinline__ work_type cubicInterpolate(typename TypeTraits<work_type>::ParameterType p0, typename TypeTraits<work_type>::ParameterType p1, typename TypeTraits<work_type>::ParameterType p2, typename TypeTraits<work_type>::ParameterType p3, float x)\r
+ static __device__ __forceinline__ float bicubicCoeff(float x_)\r
{\r
- return p1 + 0.5f * x * (p2 - p0 + x * (2.0f * p0 - 5.0f * p1 + 4.0f * p2 - p3 + x * (3.0f * (p1 - p2) + p3 - p0)));\r
+ float x = fabsf(x_);\r
+ if (x <= 1.0f)\r
+ {\r
+ return x * x * (1.5f * x - 2.5f) + 1.0f;\r
+ }\r
+ else if (x < 2.0f)\r
+ {\r
+ return x * (x * (-0.5f * x + 2.5f) - 4.0f) + 2.0f;\r
+ }\r
+ else\r
+ {\r
+ return 0.0f;\r
+ }\r
}\r
\r
__device__ elem_type operator ()(float y, float x) const\r
{\r
- const int xi = __float2int_rn(x);\r
- const int yi = __float2int_rn(y);\r
+ const float xmin = ::ceilf(x - 2.0f);\r
+ const float xmax = ::floorf(x + 2.0f);\r
+\r
+ const float ymin = ::ceilf(y - 2.0f);\r
+ const float ymax = ::floorf(y + 2.0f);\r
+\r
+ work_type sum = VecTraits<work_type>::all(0);\r
+ float wsum = 0.0f;\r
\r
- work_type arr[4];\r
+ for (float cy = ymin; cy <= ymax; cy += 1.0f)\r
+ {\r
+ for (float cx = xmin; cx <= xmax; cx += 1.0f)\r
+ {\r
+ const float w = bicubicCoeff(x - cx) * bicubicCoeff(y - cy);\r
+ sum = sum + w * src(__float2int_rd(cy), __float2int_rd(cx));\r
+ wsum += w;\r
+ }\r
+ }\r
\r
- arr[0] = cubicInterpolate(saturate_cast<work_type>(src(yi - 2, xi - 2)), saturate_cast<work_type>(src(yi - 2, xi - 1)), saturate_cast<work_type>(src(yi - 2, xi)), saturate_cast<work_type>(src(yi - 2, xi + 1)), (x - xi + 2.0f) / 4.0f);\r
- arr[1] = cubicInterpolate(saturate_cast<work_type>(src(yi - 1, xi - 2)), saturate_cast<work_type>(src(yi - 1, xi - 1)), saturate_cast<work_type>(src(yi - 1, xi)), saturate_cast<work_type>(src(yi - 1, xi + 1)), (x - xi + 2.0f) / 4.0f);\r
- arr[2] = cubicInterpolate(saturate_cast<work_type>(src(yi , xi - 2)), saturate_cast<work_type>(src(yi , xi - 1)), saturate_cast<work_type>(src(yi , xi)), saturate_cast<work_type>(src(yi , xi + 1)), (x - xi + 2.0f) / 4.0f);\r
- arr[3] = cubicInterpolate(saturate_cast<work_type>(src(yi + 1, xi - 2)), saturate_cast<work_type>(src(yi + 1, xi - 1)), saturate_cast<work_type>(src(yi + 1, xi)), saturate_cast<work_type>(src(yi + 1, xi + 1)), (x - xi + 2.0f) / 4.0f);\r
+ work_type res = (!wsum)? VecTraits<work_type>::all(0) : sum / wsum;\r
\r
- return saturate_cast<elem_type>(cubicInterpolate(arr[0], arr[1], arr[2], arr[3], (y - yi + 2.0f) / 4.0f));\r
+ return saturate_cast<elem_type>(res);\r
}\r
\r
const Ptr2D src;\r
{\r
static T getValue(const cv::Mat& src, float y, float x, int c, int border_type, cv::Scalar borderVal = cv::Scalar())\r
{\r
- return readVal<T>(src, cvFloor(y), cvFloor(x), c, border_type, borderVal);\r
+ return readVal<T>(src, cvRound(y), cvRound(x), c, border_type, borderVal);\r
}\r
};\r
\r
{\r
static T getValue(const cv::Mat& src, float y, float x, int c, int border_type, cv::Scalar borderVal = cv::Scalar())\r
{\r
- x -= 0.5f;\r
- y -= 0.5f;\r
-\r
int x1 = cvFloor(x);\r
int y1 = cvFloor(y);\r
int x2 = x1 + 1;\r
\r
template <typename T> struct CubicInterpolator\r
{\r
- static float getValue(float p[4], float x)\r
+ static float bicubicCoeff(float x_)\r
{\r
- return static_cast<float>(p[1] + 0.5 * x * (p[2] - p[0] + x*(2.0*p[0] - 5.0*p[1] + 4.0*p[2] - p[3] + x*(3.0*(p[1] - p[2]) + p[3] - p[0]))));\r
+ float x = fabsf(x_);\r
+ if (x <= 1.0f)\r
+ {\r
+ return x * x * (1.5f * x - 2.5f) + 1.0f;\r
+ }\r
+ else if (x < 2.0f)\r
+ {\r
+ return x * (x * (-0.5f * x + 2.5f) - 4.0f) + 2.0f;\r
+ }\r
+ else\r
+ {\r
+ return 0.0f;\r
+ }\r
}\r
\r
- static float getValue(float p[4][4], float x, float y)\r
+ static T getValue(const cv::Mat& src, float y, float x, int c, int border_type, cv::Scalar borderVal = cv::Scalar())\r
{\r
- float arr[4];\r
+ const float xmin = ceilf(x - 2.0f);\r
+ const float xmax = floorf(x + 2.0f);\r
\r
- arr[0] = getValue(p[0], x);\r
- arr[1] = getValue(p[1], x);\r
- arr[2] = getValue(p[2], x);\r
- arr[3] = getValue(p[3], x);\r
+ const float ymin = ceilf(y - 2.0f);\r
+ const float ymax = floorf(y + 2.0f);\r
\r
- return getValue(arr, y);\r
- }\r
+ float sum = 0.0f;\r
+ float wsum = 0.0f;\r
\r
- static T getValue(const cv::Mat& src, float y, float x, int c, int border_type, cv::Scalar borderVal = cv::Scalar())\r
- {\r
- int ix = cvRound(x);\r
- int iy = cvRound(y);\r
-\r
- float vals[4][4] =\r
+ for (float cy = ymin; cy <= ymax; cy += 1.0f)\r
{\r
- {(float)readVal<T>(src, iy - 2, ix - 2, c, border_type, borderVal), (float)readVal<T>(src, iy - 2, ix - 1, c, border_type, borderVal), (float)readVal<T>(src, iy - 2, ix, c, border_type, borderVal), (float)readVal<T>(src, iy - 2, ix + 1, c, border_type, borderVal)},\r
- {(float)readVal<T>(src, iy - 1, ix - 2, c, border_type, borderVal), (float)readVal<T>(src, iy - 1, ix - 1, c, border_type, borderVal), (float)readVal<T>(src, iy - 1, ix, c, border_type, borderVal), (float)readVal<T>(src, iy - 1, ix + 1, c, border_type, borderVal)},\r
- {(float)readVal<T>(src, iy , ix - 2, c, border_type, borderVal), (float)readVal<T>(src, iy , ix - 1, c, border_type, borderVal), (float)readVal<T>(src, iy , ix, c, border_type, borderVal), (float)readVal<T>(src, iy , ix + 1, c, border_type, borderVal)},\r
- {(float)readVal<T>(src, iy + 1, ix - 2, c, border_type, borderVal), (float)readVal<T>(src, iy + 1, ix - 1, c, border_type, borderVal), (float)readVal<T>(src, iy + 1, ix, c, border_type, borderVal), (float)readVal<T>(src, iy + 1, ix + 1, c, border_type, borderVal)},\r
- };\r
+ for (float cx = xmin; cx <= xmax; cx += 1.0f)\r
+ {\r
+ const float w = bicubicCoeff(x - cx) * bicubicCoeff(y - cy);\r
+ sum += w * readVal<T>(src, cvFloor(cy), cvFloor(cx), c, border_type, borderVal);\r
+ wsum += w;\r
+ }\r
+ }\r
\r
- return cv::saturate_cast<T>(getValue(vals, static_cast<float>((x - ix + 2.0) / 4.0), static_cast<float>((y - iy + 2.0) / 4.0)));\r
+ float res = (!wsum)? 0 : sum / wsum;\r
+\r
+ return cv::saturate_cast<T>(res);\r
}\r
};\r
\r