Merged revision(s) 8495 from trunk:
authorVladislav Vinogradov <no@email>
Tue, 29 May 2012 11:35:30 +0000 (11:35 +0000)
committerVladislav Vinogradov <no@email>
Tue, 29 May 2012 11:35:30 +0000 (11:35 +0000)
Bug #1991 : fixed gpu interpolation (remap, resize, warp...)
........

modules/gpu/src/opencv2/gpu/device/filters.hpp
modules/gpu/test/interpolation.hpp
modules/gpu/test/test_remap.cpp

index 9362fde..537d6af 100644 (file)
@@ -59,7 +59,7 @@ namespace cv { namespace gpu { namespace device
 \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
@@ -78,9 +78,6 @@ namespace cv { namespace gpu { namespace device
 \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
@@ -112,24 +109,47 @@ namespace cv { namespace gpu { namespace device
 \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
index 995b91e..e38dc4c 100644 (file)
@@ -54,7 +54,7 @@ template <typename T> struct NearestInterpolator
 {\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
@@ -62,9 +62,6 @@ template <typename T> struct LinearInterpolator
 {\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
@@ -83,37 +80,47 @@ template <typename T> struct LinearInterpolator
 \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
index 84fde5a..c61a899 100644 (file)
@@ -163,7 +163,7 @@ TEST_P(Remap, Accuracy)
     cv::Mat dst_gold;\r
     remapGold(src, xmap, ymap, dst_gold, interpolation, borderType, val);\r
 \r
-    EXPECT_MAT_NEAR(dst_gold, dst, src.depth() == CV_32F ? 1e-4 : 1.0);\r
+    EXPECT_MAT_NEAR(dst_gold, dst, src.depth() == CV_32F ? 1e-3 : 1.0);\r
 }\r
 \r
 INSTANTIATE_TEST_CASE_P(GPU_ImgProc, Remap, testing::Combine(\r