added dual tvl1 optical flow gpu implementation
[profile/ivi/opencv.git] / modules / gpu / src / cuda / gftt.cu
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                           License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
15 // Third party copyrights are property of their respective owners.
16 //
17 // Redistribution and use in source and binary forms, with or without modification,
18 // are permitted provided that the following conditions are met:
19 //
20 //   * Redistribution's of source code must retain the above copyright notice,
21 //     this list of conditions and the following disclaimer.
22 //
23 //   * Redistribution's in binary form must reproduce the above copyright notice,
24 //     this list of conditions and the following disclaimer in the documentation
25 //     and/or other materials provided with the distribution.
26 //
27 //   * The name of the copyright holders may not be used to endorse or promote products
28 //     derived from this software without specific prior written permission.
29 //
30 // This software is provided by the copyright holders and contributors "as is" and
31 // any express or implied warranties, including, but not limited to, the implied
32 // warranties of merchantability and fitness for a particular purpose are disclaimed.
33 // In no event shall the Intel Corporation or contributors be liable for any direct,
34 // indirect, incidental, special, exemplary, or consequential damages
35 // (including, but not limited to, procurement of substitute goods or services;
36 // loss of use, data, or profits; or business interruption) however caused
37 // and on any theory of liability, whether in contract, strict liability,
38 // or tort (including negligence or otherwise) arising in any way out of
39 // the use of this software, even if advised of the possibility of such damage.
40 //
41 // Copyright (c) 2010, Paul Furgale, Chi Hay Tong
42 //
43 // The original code was written by Paul Furgale and Chi Hay Tong
44 // and later optimized and prepared for integration into OpenCV by Itseez.
45 //
46 //M*/
47
48 #if !defined CUDA_DISABLER
49
50 #include <thrust/device_ptr.h>
51 #include <thrust/sort.h>
52
53 #include "opencv2/gpu/device/common.hpp"
54 #include "opencv2/gpu/device/utility.hpp"
55
56 namespace cv { namespace gpu { namespace device
57 {
58     namespace gfft
59     {
60         texture<float, cudaTextureType2D, cudaReadModeElementType> eigTex(0, cudaFilterModePoint, cudaAddressModeClamp);
61
62         __device__ uint g_counter = 0;
63
64         template <class Mask> __global__ void findCorners(float threshold, const Mask mask, float2* corners, uint max_count, int rows, int cols)
65         {
66             #if __CUDA_ARCH__ >= 110
67
68             const int j = blockIdx.x * blockDim.x + threadIdx.x;
69             const int i = blockIdx.y * blockDim.y + threadIdx.y;
70
71             if (i > 0 && i < rows - 1 && j > 0 && j < cols - 1 && mask(i, j))
72             {
73                 float val = tex2D(eigTex, j, i);
74
75                 if (val > threshold)
76                 {
77                     float maxVal = val;
78
79                     maxVal = ::fmax(tex2D(eigTex, j - 1, i - 1), maxVal);
80                     maxVal = ::fmax(tex2D(eigTex, j    , i - 1), maxVal);
81                     maxVal = ::fmax(tex2D(eigTex, j + 1, i - 1), maxVal);
82
83                     maxVal = ::fmax(tex2D(eigTex, j - 1, i), maxVal);
84                     maxVal = ::fmax(tex2D(eigTex, j + 1, i), maxVal);
85
86                     maxVal = ::fmax(tex2D(eigTex, j - 1, i + 1), maxVal);
87                     maxVal = ::fmax(tex2D(eigTex, j    , i + 1), maxVal);
88                     maxVal = ::fmax(tex2D(eigTex, j + 1, i + 1), maxVal);
89
90                     if (val == maxVal)
91                     {
92                         const uint ind = atomicInc(&g_counter, (uint)(-1));
93
94                         if (ind < max_count)
95                             corners[ind] = make_float2(j, i);
96                     }
97                 }
98             }
99
100             #endif // __CUDA_ARCH__ >= 110
101         }
102
103         int findCorners_gpu(PtrStepSzf eig, float threshold, PtrStepSzb mask, float2* corners, int max_count)
104         {
105             void* counter_ptr;
106             cudaSafeCall( cudaGetSymbolAddress(&counter_ptr, g_counter) );
107
108             cudaSafeCall( cudaMemset(counter_ptr, 0, sizeof(uint)) );
109
110             bindTexture(&eigTex, eig);
111
112             dim3 block(16, 16);
113             dim3 grid(divUp(eig.cols, block.x), divUp(eig.rows, block.y));
114
115             if (mask.data)
116                 findCorners<<<grid, block>>>(threshold, SingleMask(mask), corners, max_count, eig.rows, eig.cols);
117             else
118                 findCorners<<<grid, block>>>(threshold, WithOutMask(), corners, max_count, eig.rows, eig.cols);
119
120             cudaSafeCall( cudaGetLastError() );
121
122             cudaSafeCall( cudaDeviceSynchronize() );
123
124             uint count;
125             cudaSafeCall( cudaMemcpy(&count, counter_ptr, sizeof(uint), cudaMemcpyDeviceToHost) );
126
127             return min(count, max_count);
128         }
129
130         class EigGreater
131         {
132         public:
133             __device__ __forceinline__ bool operator()(float2 a, float2 b) const
134             {
135                 return tex2D(eigTex, a.x, a.y) > tex2D(eigTex, b.x, b.y);
136             }
137         };
138
139
140         void sortCorners_gpu(PtrStepSzf eig, float2* corners, int count)
141         {
142             bindTexture(&eigTex, eig);
143
144             thrust::device_ptr<float2> ptr(corners);
145
146             thrust::sort(ptr, ptr + count, EigGreater());
147         }
148     } // namespace optical_flow
149 }}}
150
151
152 #endif /* CUDA_DISABLER */