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 //M*/
42 
43 #include "precomp.hpp"
44 
45 using namespace cv;
46 using namespace cv::cuda;
47 
48 #if !defined (HAVE_CUDA) || defined (CUDA_DISABLER)
49 
create(Size,int,int,bool)50 Ptr<SparsePyrLKOpticalFlow> cv::cuda::SparsePyrLKOpticalFlow::create(Size, int, int, bool) { throw_no_cuda(); return Ptr<SparsePyrLKOpticalFlow>(); }
51 
create(Size,int,int,bool)52 Ptr<DensePyrLKOpticalFlow> cv::cuda::DensePyrLKOpticalFlow::create(Size, int, int, bool) { throw_no_cuda(); return Ptr<SparsePyrLKOpticalFlow>(); }
53 
54 #else /* !defined (HAVE_CUDA) */
55 
56 namespace pyrlk
57 {
58     void loadConstants(int2 winSize, int iters, cudaStream_t stream);
59 
60     void sparse1(PtrStepSzf I, PtrStepSzf J, const float2* prevPts, float2* nextPts, uchar* status, float* err, int ptcount,
61                  int level, dim3 block, dim3 patch, cudaStream_t stream);
62     void sparse4(PtrStepSz<float4> I, PtrStepSz<float4> J, const float2* prevPts, float2* nextPts, uchar* status, float* err, int ptcount,
63                  int level, dim3 block, dim3 patch, cudaStream_t stream);
64 
65     void dense(PtrStepSzb I, PtrStepSzf J, PtrStepSzf u, PtrStepSzf v, PtrStepSzf prevU, PtrStepSzf prevV,
66                PtrStepSzf err, int2 winSize, cudaStream_t stream);
67 }
68 
69 namespace
70 {
71     class PyrLKOpticalFlowBase
72     {
73     public:
74         PyrLKOpticalFlowBase(Size winSize, int maxLevel, int iters, bool useInitialFlow);
75 
76         void sparse(const GpuMat& prevImg, const GpuMat& nextImg, const GpuMat& prevPts, GpuMat& nextPts,
77             GpuMat& status, GpuMat* err, Stream& stream);
78 
79         void dense(const GpuMat& prevImg, const GpuMat& nextImg, GpuMat& u, GpuMat& v, Stream& stream);
80 
81     protected:
82         Size winSize_;
83         int maxLevel_;
84         int iters_;
85         bool useInitialFlow_;
86 
87     private:
88         std::vector<GpuMat> prevPyr_;
89         std::vector<GpuMat> nextPyr_;
90     };
91 
PyrLKOpticalFlowBase(Size winSize,int maxLevel,int iters,bool useInitialFlow)92     PyrLKOpticalFlowBase::PyrLKOpticalFlowBase(Size winSize, int maxLevel, int iters, bool useInitialFlow) :
93         winSize_(winSize), maxLevel_(maxLevel), iters_(iters), useInitialFlow_(useInitialFlow)
94     {
95     }
96 
calcPatchSize(Size winSize,dim3 & block,dim3 & patch)97     void calcPatchSize(Size winSize, dim3& block, dim3& patch)
98     {
99         if (winSize.width > 32 && winSize.width > 2 * winSize.height)
100         {
101             block.x = deviceSupports(FEATURE_SET_COMPUTE_12) ? 32 : 16;
102             block.y = 8;
103         }
104         else
105         {
106             block.x = 16;
107             block.y = deviceSupports(FEATURE_SET_COMPUTE_12) ? 16 : 8;
108         }
109 
110         patch.x = (winSize.width  + block.x - 1) / block.x;
111         patch.y = (winSize.height + block.y - 1) / block.y;
112 
113         block.z = patch.z = 1;
114     }
115 
sparse(const GpuMat & prevImg,const GpuMat & nextImg,const GpuMat & prevPts,GpuMat & nextPts,GpuMat & status,GpuMat * err,Stream & stream)116     void PyrLKOpticalFlowBase::sparse(const GpuMat& prevImg, const GpuMat& nextImg, const GpuMat& prevPts, GpuMat& nextPts, GpuMat& status, GpuMat* err, Stream& stream)
117     {
118         if (prevPts.empty())
119         {
120             nextPts.release();
121             status.release();
122             if (err) err->release();
123             return;
124         }
125 
126         dim3 block, patch;
127         calcPatchSize(winSize_, block, patch);
128 
129         CV_Assert( prevImg.channels() == 1 || prevImg.channels() == 3 || prevImg.channels() == 4 );
130         CV_Assert( prevImg.size() == nextImg.size() && prevImg.type() == nextImg.type() );
131         CV_Assert( maxLevel_ >= 0 );
132         CV_Assert( winSize_.width > 2 && winSize_.height > 2 );
133         CV_Assert( patch.x > 0 && patch.x < 6 && patch.y > 0 && patch.y < 6 );
134         CV_Assert( prevPts.rows == 1 && prevPts.type() == CV_32FC2 );
135 
136         if (useInitialFlow_)
137             CV_Assert( nextPts.size() == prevPts.size() && nextPts.type() == prevPts.type() );
138         else
139             ensureSizeIsEnough(1, prevPts.cols, prevPts.type(), nextPts);
140 
141         GpuMat temp1 = (useInitialFlow_ ? nextPts : prevPts).reshape(1);
142         GpuMat temp2 = nextPts.reshape(1);
143         cuda::multiply(temp1, Scalar::all(1.0 / (1 << maxLevel_) / 2.0), temp2, 1, -1, stream);
144 
145         ensureSizeIsEnough(1, prevPts.cols, CV_8UC1, status);
146         status.setTo(Scalar::all(1), stream);
147 
148         if (err)
149             ensureSizeIsEnough(1, prevPts.cols, CV_32FC1, *err);
150 
151         // build the image pyramids.
152 
153         BufferPool pool(stream);
154 
155         prevPyr_.resize(maxLevel_ + 1);
156         nextPyr_.resize(maxLevel_ + 1);
157 
158         int cn = prevImg.channels();
159 
160         if (cn == 1 || cn == 4)
161         {
162             prevImg.convertTo(prevPyr_[0], CV_32F, stream);
163             nextImg.convertTo(nextPyr_[0], CV_32F, stream);
164         }
165         else
166         {
167             GpuMat buf = pool.getBuffer(prevImg.size(), CV_MAKE_TYPE(prevImg.depth(), 4));
168 
169             cuda::cvtColor(prevImg, buf, COLOR_BGR2BGRA, 0, stream);
170             buf.convertTo(prevPyr_[0], CV_32F, stream);
171 
172             cuda::cvtColor(nextImg, buf, COLOR_BGR2BGRA, 0, stream);
173             buf.convertTo(nextPyr_[0], CV_32F, stream);
174         }
175 
176         for (int level = 1; level <= maxLevel_; ++level)
177         {
178             cuda::pyrDown(prevPyr_[level - 1], prevPyr_[level], stream);
179             cuda::pyrDown(nextPyr_[level - 1], nextPyr_[level], stream);
180         }
181 
182         pyrlk::loadConstants(make_int2(winSize_.width, winSize_.height), iters_, StreamAccessor::getStream(stream));
183 
184         for (int level = maxLevel_; level >= 0; level--)
185         {
186             if (cn == 1)
187             {
188                 pyrlk::sparse1(prevPyr_[level], nextPyr_[level],
189                                prevPts.ptr<float2>(), nextPts.ptr<float2>(),
190                                status.ptr(),
191                                level == 0 && err ? err->ptr<float>() : 0, prevPts.cols,
192                                level, block, patch,
193                                StreamAccessor::getStream(stream));
194             }
195             else
196             {
197                 pyrlk::sparse4(prevPyr_[level], nextPyr_[level],
198                                prevPts.ptr<float2>(), nextPts.ptr<float2>(),
199                                status.ptr(),
200                                level == 0 && err ? err->ptr<float>() : 0, prevPts.cols,
201                                level, block, patch,
202                                StreamAccessor::getStream(stream));
203             }
204         }
205     }
206 
dense(const GpuMat & prevImg,const GpuMat & nextImg,GpuMat & u,GpuMat & v,Stream & stream)207     void PyrLKOpticalFlowBase::dense(const GpuMat& prevImg, const GpuMat& nextImg, GpuMat& u, GpuMat& v, Stream& stream)
208     {
209         CV_Assert( prevImg.type() == CV_8UC1 );
210         CV_Assert( prevImg.size() == nextImg.size() && prevImg.type() == nextImg.type() );
211         CV_Assert( maxLevel_ >= 0 );
212         CV_Assert( winSize_.width > 2 && winSize_.height > 2 );
213 
214         // build the image pyramids.
215 
216         prevPyr_.resize(maxLevel_ + 1);
217         nextPyr_.resize(maxLevel_ + 1);
218 
219         prevPyr_[0] = prevImg;
220         nextImg.convertTo(nextPyr_[0], CV_32F, stream);
221 
222         for (int level = 1; level <= maxLevel_; ++level)
223         {
224             cuda::pyrDown(prevPyr_[level - 1], prevPyr_[level], stream);
225             cuda::pyrDown(nextPyr_[level - 1], nextPyr_[level], stream);
226         }
227 
228         BufferPool pool(stream);
229 
230         GpuMat uPyr[] = {
231             pool.getBuffer(prevImg.size(), CV_32FC1),
232             pool.getBuffer(prevImg.size(), CV_32FC1),
233         };
234         GpuMat vPyr[] = {
235             pool.getBuffer(prevImg.size(), CV_32FC1),
236             pool.getBuffer(prevImg.size(), CV_32FC1),
237         };
238 
239         uPyr[0].setTo(Scalar::all(0), stream);
240         vPyr[0].setTo(Scalar::all(0), stream);
241         uPyr[1].setTo(Scalar::all(0), stream);
242         vPyr[1].setTo(Scalar::all(0), stream);
243 
244         int2 winSize2i = make_int2(winSize_.width, winSize_.height);
245         pyrlk::loadConstants(winSize2i, iters_, StreamAccessor::getStream(stream));
246 
247         int idx = 0;
248 
249         for (int level = maxLevel_; level >= 0; level--)
250         {
251             int idx2 = (idx + 1) & 1;
252 
253             pyrlk::dense(prevPyr_[level], nextPyr_[level],
254                          uPyr[idx], vPyr[idx], uPyr[idx2], vPyr[idx2],
255                          PtrStepSzf(), winSize2i,
256                          StreamAccessor::getStream(stream));
257 
258             if (level > 0)
259                 idx = idx2;
260         }
261 
262         uPyr[idx].copyTo(u, stream);
263         vPyr[idx].copyTo(v, stream);
264     }
265 
266     class SparsePyrLKOpticalFlowImpl : public SparsePyrLKOpticalFlow, private PyrLKOpticalFlowBase
267     {
268     public:
SparsePyrLKOpticalFlowImpl(Size winSize,int maxLevel,int iters,bool useInitialFlow)269         SparsePyrLKOpticalFlowImpl(Size winSize, int maxLevel, int iters, bool useInitialFlow) :
270             PyrLKOpticalFlowBase(winSize, maxLevel, iters, useInitialFlow)
271         {
272         }
273 
getWinSize() const274         virtual Size getWinSize() const { return winSize_; }
setWinSize(Size winSize)275         virtual void setWinSize(Size winSize) { winSize_ = winSize; }
276 
getMaxLevel() const277         virtual int getMaxLevel() const { return maxLevel_; }
setMaxLevel(int maxLevel)278         virtual void setMaxLevel(int maxLevel) { maxLevel_ = maxLevel; }
279 
getNumIters() const280         virtual int getNumIters() const { return iters_; }
setNumIters(int iters)281         virtual void setNumIters(int iters) { iters_ = iters; }
282 
getUseInitialFlow() const283         virtual bool getUseInitialFlow() const { return useInitialFlow_; }
setUseInitialFlow(bool useInitialFlow)284         virtual void setUseInitialFlow(bool useInitialFlow) { useInitialFlow_ = useInitialFlow; }
285 
calc(InputArray _prevImg,InputArray _nextImg,InputArray _prevPts,InputOutputArray _nextPts,OutputArray _status,OutputArray _err,Stream & stream)286         virtual void calc(InputArray _prevImg, InputArray _nextImg,
287                           InputArray _prevPts, InputOutputArray _nextPts,
288                           OutputArray _status,
289                           OutputArray _err,
290                           Stream& stream)
291         {
292             const GpuMat prevImg = _prevImg.getGpuMat();
293             const GpuMat nextImg = _nextImg.getGpuMat();
294             const GpuMat prevPts = _prevPts.getGpuMat();
295             GpuMat& nextPts = _nextPts.getGpuMatRef();
296             GpuMat& status = _status.getGpuMatRef();
297             GpuMat* err = _err.needed() ? &(_err.getGpuMatRef()) : NULL;
298 
299             sparse(prevImg, nextImg, prevPts, nextPts, status, err, stream);
300         }
301     };
302 
303     class DensePyrLKOpticalFlowImpl : public DensePyrLKOpticalFlow, private PyrLKOpticalFlowBase
304     {
305     public:
DensePyrLKOpticalFlowImpl(Size winSize,int maxLevel,int iters,bool useInitialFlow)306         DensePyrLKOpticalFlowImpl(Size winSize, int maxLevel, int iters, bool useInitialFlow) :
307             PyrLKOpticalFlowBase(winSize, maxLevel, iters, useInitialFlow)
308         {
309         }
310 
getWinSize() const311         virtual Size getWinSize() const { return winSize_; }
setWinSize(Size winSize)312         virtual void setWinSize(Size winSize) { winSize_ = winSize; }
313 
getMaxLevel() const314         virtual int getMaxLevel() const { return maxLevel_; }
setMaxLevel(int maxLevel)315         virtual void setMaxLevel(int maxLevel) { maxLevel_ = maxLevel; }
316 
getNumIters() const317         virtual int getNumIters() const { return iters_; }
setNumIters(int iters)318         virtual void setNumIters(int iters) { iters_ = iters; }
319 
getUseInitialFlow() const320         virtual bool getUseInitialFlow() const { return useInitialFlow_; }
setUseInitialFlow(bool useInitialFlow)321         virtual void setUseInitialFlow(bool useInitialFlow) { useInitialFlow_ = useInitialFlow; }
322 
calc(InputArray _prevImg,InputArray _nextImg,InputOutputArray _flow,Stream & stream)323         virtual void calc(InputArray _prevImg, InputArray _nextImg, InputOutputArray _flow, Stream& stream)
324         {
325             const GpuMat prevImg = _prevImg.getGpuMat();
326             const GpuMat nextImg = _nextImg.getGpuMat();
327 
328             BufferPool pool(stream);
329             GpuMat u = pool.getBuffer(prevImg.size(), CV_32FC1);
330             GpuMat v = pool.getBuffer(prevImg.size(), CV_32FC1);
331 
332             dense(prevImg, nextImg, u, v, stream);
333 
334             GpuMat flows[] = {u, v};
335             cuda::merge(flows, 2, _flow, stream);
336         }
337     };
338 }
339 
create(Size winSize,int maxLevel,int iters,bool useInitialFlow)340 Ptr<SparsePyrLKOpticalFlow> cv::cuda::SparsePyrLKOpticalFlow::create(Size winSize, int maxLevel, int iters, bool useInitialFlow)
341 {
342     return makePtr<SparsePyrLKOpticalFlowImpl>(winSize, maxLevel, iters, useInitialFlow);
343 }
344 
create(Size winSize,int maxLevel,int iters,bool useInitialFlow)345 Ptr<DensePyrLKOpticalFlow> cv::cuda::DensePyrLKOpticalFlow::create(Size winSize, int maxLevel, int iters, bool useInitialFlow)
346 {
347     return makePtr<DensePyrLKOpticalFlowImpl>(winSize, maxLevel, iters, useInitialFlow);
348 }
349 
350 #endif /* !defined (HAVE_CUDA) */
351