Home | History | Annotate | Download | only in src
      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 
     50 void cv::cuda::calcOpticalFlowBM(const GpuMat&, const GpuMat&, Size, Size, Size, bool, GpuMat&, GpuMat&, GpuMat&, Stream&) { throw_no_cuda(); }
     51 
     52 #else // HAVE_CUDA
     53 
     54 namespace optflowbm
     55 {
     56     void calc(PtrStepSzb prev, PtrStepSzb curr, PtrStepSzf velx, PtrStepSzf vely, int2 blockSize, int2 shiftSize, bool usePrevious,
     57               int maxX, int maxY, int acceptLevel, int escapeLevel, const short2* ss, int ssCount, cudaStream_t stream);
     58 }
     59 
     60 void cv::cuda::calcOpticalFlowBM(const GpuMat& prev, const GpuMat& curr, Size blockSize, Size shiftSize, Size maxRange, bool usePrevious, GpuMat& velx, GpuMat& vely, GpuMat& buf, Stream& st)
     61 {
     62     CV_Assert( prev.type() == CV_8UC1 );
     63     CV_Assert( curr.size() == prev.size() && curr.type() == prev.type() );
     64 
     65     const Size velSize((prev.cols - blockSize.width + shiftSize.width) / shiftSize.width,
     66                        (prev.rows - blockSize.height + shiftSize.height) / shiftSize.height);
     67 
     68     velx.create(velSize, CV_32FC1);
     69     vely.create(velSize, CV_32FC1);
     70 
     71     // scanning scheme coordinates
     72     std::vector<short2> ss((2 * maxRange.width + 1) * (2 * maxRange.height + 1));
     73     int ssCount = 0;
     74 
     75     // Calculate scanning scheme
     76     const int minCount = std::min(maxRange.width, maxRange.height);
     77 
     78     // use spiral search pattern
     79     //
     80     //     9 10 11 12
     81     //     8  1  2 13
     82     //     7  *  3 14
     83     //     6  5  4 15
     84     //... 20 19 18 17
     85     //
     86 
     87     for (int i = 0; i < minCount; ++i)
     88     {
     89         // four cycles along sides
     90         int x = -i - 1, y = x;
     91 
     92         // upper side
     93         for (int j = -i; j <= i + 1; ++j, ++ssCount)
     94         {
     95             ss[ssCount].x = (short) ++x;
     96             ss[ssCount].y = (short) y;
     97         }
     98 
     99         // right side
    100         for (int j = -i; j <= i + 1; ++j, ++ssCount)
    101         {
    102             ss[ssCount].x = (short) x;
    103             ss[ssCount].y = (short) ++y;
    104         }
    105 
    106         // bottom side
    107         for (int j = -i; j <= i + 1; ++j, ++ssCount)
    108         {
    109             ss[ssCount].x = (short) --x;
    110             ss[ssCount].y = (short) y;
    111         }
    112 
    113         // left side
    114         for (int j = -i; j <= i + 1; ++j, ++ssCount)
    115         {
    116             ss[ssCount].x = (short) x;
    117             ss[ssCount].y = (short) --y;
    118         }
    119     }
    120 
    121     // the rest part
    122     if (maxRange.width < maxRange.height)
    123     {
    124         const int xleft = -minCount;
    125 
    126         // cycle by neighbor rings
    127         for (int i = minCount; i < maxRange.height; ++i)
    128         {
    129             // two cycles by x
    130             int y = -(i + 1);
    131             int x = xleft;
    132 
    133             // upper side
    134             for (int j = -maxRange.width; j <= maxRange.width; ++j, ++ssCount, ++x)
    135             {
    136                 ss[ssCount].x = (short) x;
    137                 ss[ssCount].y = (short) y;
    138             }
    139 
    140             x = xleft;
    141             y = -y;
    142 
    143             // bottom side
    144             for (int j = -maxRange.width; j <= maxRange.width; ++j, ++ssCount, ++x)
    145             {
    146                 ss[ssCount].x = (short) x;
    147                 ss[ssCount].y = (short) y;
    148             }
    149         }
    150     }
    151     else if (maxRange.width > maxRange.height)
    152     {
    153         const int yupper = -minCount;
    154 
    155         // cycle by neighbor rings
    156         for (int i = minCount; i < maxRange.width; ++i)
    157         {
    158             // two cycles by y
    159             int x = -(i + 1);
    160             int y = yupper;
    161 
    162             // left side
    163             for (int j = -maxRange.height; j <= maxRange.height; ++j, ++ssCount, ++y)
    164             {
    165                 ss[ssCount].x = (short) x;
    166                 ss[ssCount].y = (short) y;
    167             }
    168 
    169             y = yupper;
    170             x = -x;
    171 
    172             // right side
    173             for (int j = -maxRange.height; j <= maxRange.height; ++j, ++ssCount, ++y)
    174             {
    175                 ss[ssCount].x = (short) x;
    176                 ss[ssCount].y = (short) y;
    177             }
    178         }
    179     }
    180 
    181     const cudaStream_t stream = StreamAccessor::getStream(st);
    182 
    183     ensureSizeIsEnough(1, ssCount, CV_16SC2, buf);
    184     if (stream == 0)
    185         cudaSafeCall( cudaMemcpy(buf.data, &ss[0], ssCount * sizeof(short2), cudaMemcpyHostToDevice) );
    186     else
    187         cudaSafeCall( cudaMemcpyAsync(buf.data, &ss[0], ssCount * sizeof(short2), cudaMemcpyHostToDevice, stream) );
    188 
    189     const int maxX = prev.cols - blockSize.width;
    190     const int maxY = prev.rows - blockSize.height;
    191 
    192     const int SMALL_DIFF = 2;
    193     const int BIG_DIFF = 128;
    194 
    195     const int blSize = blockSize.area();
    196     const int acceptLevel = blSize * SMALL_DIFF;
    197     const int escapeLevel = blSize * BIG_DIFF;
    198 
    199     optflowbm::calc(prev, curr, velx, vely,
    200                     make_int2(blockSize.width, blockSize.height), make_int2(shiftSize.width, shiftSize.height), usePrevious,
    201                     maxX, maxY, acceptLevel, escapeLevel, buf.ptr<short2>(), ssCount, stream);
    202 }
    203 
    204 #endif // HAVE_CUDA
    205