--- /dev/null
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+// By downloading, copying, installing or using the software you agree to this license.
+// If you do not agree to this license, do not download, install,
+// copy or use the software.
+//
+//
+// License Agreement
+// For Open Source Computer Vision Library
+//
+// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
+// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
+// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistribution's of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// * Redistribution's in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other oclMaterials provided with the distribution.
+//
+// * The name of the copyright holders may not be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#ifndef __OPENCV_OCL_HPP__
+#define __OPENCV_OCL_HPP__
+
+#include <memory>
+#include <vector>
+
+#include "opencv2/core.hpp"
+#include "opencv2/imgproc.hpp"
+#include "opencv2/objdetect.hpp"
+
+namespace cv
+{
+ namespace ocl
+ {
+ enum
+ {
+ CVCL_DEVICE_TYPE_DEFAULT = (1 << 0),
+ CVCL_DEVICE_TYPE_CPU = (1 << 1),
+ CVCL_DEVICE_TYPE_GPU = (1 << 2),
+ CVCL_DEVICE_TYPE_ACCELERATOR = (1 << 3),
+ //CVCL_DEVICE_TYPE_CUSTOM = (1 << 4)
+ CVCL_DEVICE_TYPE_ALL = 0xFFFFFFFF
+ };
+
+ enum DevMemRW
+ {
+ DEVICE_MEM_R_W = 0,
+ DEVICE_MEM_R_ONLY,
+ DEVICE_MEM_W_ONLY
+ };
+
+ enum DevMemType
+ {
+ DEVICE_MEM_DEFAULT = 0,
+ DEVICE_MEM_AHP, //alloc host pointer
+ DEVICE_MEM_UHP, //use host pointer
+ DEVICE_MEM_CHP, //copy host pointer
+ DEVICE_MEM_PM //persistent memory
+ };
+
+ //Get the global device memory and read/write type
+ //return 1 if unified memory system supported, otherwise return 0
+ CV_EXPORTS int getDevMemType(DevMemRW& rw_type, DevMemType& mem_type);
+
+ //Set the global device memory and read/write type,
+ //the newly generated oclMat will all use this type
+ //return -1 if the target type is unsupported, otherwise return 0
+ CV_EXPORTS int setDevMemType(DevMemRW rw_type = DEVICE_MEM_R_W, DevMemType mem_type = DEVICE_MEM_DEFAULT);
+
+ //this class contains ocl runtime information
+ class CV_EXPORTS Info
+ {
+ public:
+ struct Impl;
+ Impl *impl;
+
+ Info();
+ Info(const Info &m);
+ ~Info();
+ void release();
+ Info &operator = (const Info &m);
+ std::vector<String> DeviceName;
+ String PlatformName;
+ };
+ //////////////////////////////// Initialization & Info ////////////////////////
+ //this function may be obsoleted
+ //CV_EXPORTS cl_device_id getDevice();
+ //the function must be called before any other cv::ocl::functions, it initialize ocl runtime
+ //each Info relates to an OpenCL platform
+ //there is one or more devices in each platform, each one has a separate name
+ CV_EXPORTS int getDevice(std::vector<Info> &oclinfo, int devicetype = CVCL_DEVICE_TYPE_GPU);
+
+ //set device you want to use, optional function after getDevice be called
+ //the devnum is the index of the selected device in DeviceName vector of INfo
+ CV_EXPORTS void setDevice(Info &oclinfo, int devnum = 0);
+
+ //The two functions below enable other opencl program to use ocl module's cl_context and cl_command_queue
+ //returns cl_context *
+ CV_EXPORTS void* getoclContext();
+ //returns cl_command_queue *
+ CV_EXPORTS void* getoclCommandQueue();
+
+ //explicit call clFinish. The global command queue will be used.
+ CV_EXPORTS void finish();
+
+ //this function enable ocl module to use customized cl_context and cl_command_queue
+ //getDevice also need to be called before this function
+ CV_EXPORTS void setDeviceEx(Info &oclinfo, void *ctx, void *qu, int devnum = 0);
+
+ //returns true when global OpenCL context is initialized
+ CV_EXPORTS bool initialized();
+
+ //////////////////////////////// OpenCL context ////////////////////////
+ //This is a global singleton class used to represent a OpenCL context.
+ class CV_EXPORTS Context
+ {
+ protected:
+ Context();
+ friend class std::auto_ptr<Context>;
+ friend bool initialized();
+ private:
+ static std::auto_ptr<Context> clCxt;
+ static int val;
+ public:
+ ~Context();
+ void release();
+ Info::Impl* impl;
+
+ static Context *getContext();
+ static void setContext(Info &oclinfo);
+
+ enum {CL_DOUBLE, CL_UNIFIED_MEM, CL_VER_1_2};
+ bool supportsFeature(int ftype);
+ size_t computeUnits();
+ size_t maxWorkGroupSize();
+ void* oclContext();
+ void* oclCommandQueue();
+ };
+
+ //! Calls a kernel, by string. Pass globalThreads = NULL, and cleanUp = true, to finally clean-up without executing.
+ CV_EXPORTS double openCLExecuteKernelInterop(Context *clCxt ,
+ const char **source, String kernelName,
+ size_t globalThreads[3], size_t localThreads[3],
+ std::vector< std::pair<size_t, const void *> > &args,
+ int channels, int depth, const char *build_options,
+ bool finish = true, bool measureKernelTime = false,
+ bool cleanUp = true);
+
+ //! Calls a kernel, by file. Pass globalThreads = NULL, and cleanUp = true, to finally clean-up without executing.
+ CV_EXPORTS double openCLExecuteKernelInterop(Context *clCxt ,
+ const char **fileName, const int numFiles, String kernelName,
+ size_t globalThreads[3], size_t localThreads[3],
+ std::vector< std::pair<size_t, const void *> > &args,
+ int channels, int depth, const char *build_options,
+ bool finish = true, bool measureKernelTime = false,
+ bool cleanUp = true);
+
+ //! Enable or disable OpenCL program binary caching onto local disk
+ // After a program (*.cl files in opencl/ folder) is built at runtime, we allow the
+ // compiled OpenCL program to be cached to the path automatically as "path/*.clb"
+ // binary file, which will be reused when the OpenCV executable is started again.
+ //
+ // Caching mode is controlled by the following enums
+ // Notes
+ // 1. the feature is by default enabled when OpenCV is built in release mode.
+ // 2. the CACHE_DEBUG / CACHE_RELEASE flags only effectively work with MSVC compiler;
+ // for GNU compilers, the function always treats the build as release mode (enabled by default).
+ enum
+ {
+ CACHE_NONE = 0, // do not cache OpenCL binary
+ CACHE_DEBUG = 0x1 << 0, // cache OpenCL binary when built in debug mode (only work with MSVC)
+ CACHE_RELEASE = 0x1 << 1, // default behavior, only cache when built in release mode (only work with MSVC)
+ CACHE_ALL = CACHE_DEBUG | CACHE_RELEASE, // always cache opencl binary
+ CACHE_UPDATE = 0x1 << 2 // if the binary cache file with the same name is already on the disk, it will be updated.
+ };
+ CV_EXPORTS void setBinaryDiskCache(int mode = CACHE_RELEASE, cv::String path = "./");
+
+ //! set where binary cache to be saved to
+ CV_EXPORTS void setBinpath(const char *path);
+
+ class CV_EXPORTS oclMatExpr;
+ //////////////////////////////// oclMat ////////////////////////////////
+ class CV_EXPORTS oclMat
+ {
+ public:
+ //! default constructor
+ oclMat();
+ //! constructs oclMatrix of the specified size and type (_type is CV_8UC1, CV_64FC3, CV_32SC(12) etc.)
+ oclMat(int rows, int cols, int type);
+ oclMat(Size size, int type);
+ //! constucts oclMatrix and fills it with the specified value _s.
+ oclMat(int rows, int cols, int type, const Scalar &s);
+ oclMat(Size size, int type, const Scalar &s);
+ //! copy constructor
+ oclMat(const oclMat &m);
+
+ //! constructor for oclMatrix headers pointing to user-allocated data
+ oclMat(int rows, int cols, int type, void *data, size_t step = Mat::AUTO_STEP);
+ oclMat(Size size, int type, void *data, size_t step = Mat::AUTO_STEP);
+
+ //! creates a matrix header for a part of the bigger matrix
+ oclMat(const oclMat &m, const Range &rowRange, const Range &colRange);
+ oclMat(const oclMat &m, const Rect &roi);
+
+ //! builds oclMat from Mat. Perfom blocking upload to device.
+ explicit oclMat (const Mat &m);
+
+ //! destructor - calls release()
+ ~oclMat();
+
+ //! assignment operators
+ oclMat &operator = (const oclMat &m);
+ //! assignment operator. Perfom blocking upload to device.
+ oclMat &operator = (const Mat &m);
+ oclMat &operator = (const oclMatExpr& expr);
+
+ //! pefroms blocking upload data to oclMat.
+ void upload(const cv::Mat &m);
+
+
+ //! downloads data from device to host memory. Blocking calls.
+ operator Mat() const;
+ void download(cv::Mat &m) const;
+
+ //! convert to _InputArray
+ operator _InputArray();
+
+ //! convert to _OutputArray
+ operator _OutputArray();
+
+ //! returns a new oclMatrix header for the specified row
+ oclMat row(int y) const;
+ //! returns a new oclMatrix header for the specified column
+ oclMat col(int x) const;
+ //! ... for the specified row span
+ oclMat rowRange(int startrow, int endrow) const;
+ oclMat rowRange(const Range &r) const;
+ //! ... for the specified column span
+ oclMat colRange(int startcol, int endcol) const;
+ oclMat colRange(const Range &r) const;
+
+ //! returns deep copy of the oclMatrix, i.e. the data is copied
+ oclMat clone() const;
+ //! copies the oclMatrix content to "m".
+ // It calls m.create(this->size(), this->type()).
+ // It supports any data type
+ void copyTo( oclMat &m ) const;
+ //! copies those oclMatrix elements to "m" that are marked with non-zero mask elements.
+ //It supports 8UC1 8UC4 32SC1 32SC4 32FC1 32FC4
+ void copyTo( oclMat &m, const oclMat &mask ) const;
+ //! converts oclMatrix to another datatype with optional scalng. See cvConvertScale.
+ //It supports 8UC1 8UC4 32SC1 32SC4 32FC1 32FC4
+ void convertTo( oclMat &m, int rtype, double alpha = 1, double beta = 0 ) const;
+
+ void assignTo( oclMat &m, int type = -1 ) const;
+
+ //! sets every oclMatrix element to s
+ //It supports 8UC1 8UC4 32SC1 32SC4 32FC1 32FC4
+ oclMat& operator = (const Scalar &s);
+ //! sets some of the oclMatrix elements to s, according to the mask
+ //It supports 8UC1 8UC4 32SC1 32SC4 32FC1 32FC4
+ oclMat& setTo(const Scalar &s, const oclMat &mask = oclMat());
+ //! creates alternative oclMatrix header for the same data, with different
+ // number of channels and/or different number of rows. see cvReshape.
+ oclMat reshape(int cn, int rows = 0) const;
+
+ //! allocates new oclMatrix data unless the oclMatrix already has specified size and type.
+ // previous data is unreferenced if needed.
+ void create(int rows, int cols, int type);
+ void create(Size size, int type);
+
+ //! allocates new oclMatrix with specified device memory type.
+ void createEx(int rows, int cols, int type,
+ DevMemRW rw_type, DevMemType mem_type, void* hptr = 0);
+ void createEx(Size size, int type, DevMemRW rw_type,
+ DevMemType mem_type, void* hptr = 0);
+
+ //! decreases reference counter;
+ // deallocate the data when reference counter reaches 0.
+ void release();
+
+ //! swaps with other smart pointer
+ void swap(oclMat &mat);
+
+ //! locates oclMatrix header within a parent oclMatrix. See below
+ void locateROI( Size &wholeSize, Point &ofs ) const;
+ //! moves/resizes the current oclMatrix ROI inside the parent oclMatrix.
+ oclMat& adjustROI( int dtop, int dbottom, int dleft, int dright );
+ //! extracts a rectangular sub-oclMatrix
+ // (this is a generalized form of row, rowRange etc.)
+ oclMat operator()( Range rowRange, Range colRange ) const;
+ oclMat operator()( const Rect &roi ) const;
+
+ oclMat& operator+=( const oclMat& m );
+ oclMat& operator-=( const oclMat& m );
+ oclMat& operator*=( const oclMat& m );
+ oclMat& operator/=( const oclMat& m );
+
+ //! returns true if the oclMatrix data is continuous
+ // (i.e. when there are no gaps between successive rows).
+ // similar to CV_IS_oclMat_CONT(cvoclMat->type)
+ bool isContinuous() const;
+ //! returns element size in bytes,
+ // similar to CV_ELEM_SIZE(cvMat->type)
+ size_t elemSize() const;
+ //! returns the size of element channel in bytes.
+ size_t elemSize1() const;
+ //! returns element type, similar to CV_MAT_TYPE(cvMat->type)
+ int type() const;
+ //! returns element type, i.e. 8UC3 returns 8UC4 because in ocl
+ //! 3 channels element actually use 4 channel space
+ int ocltype() const;
+ //! returns element type, similar to CV_MAT_DEPTH(cvMat->type)
+ int depth() const;
+ //! returns element type, similar to CV_MAT_CN(cvMat->type)
+ int channels() const;
+ //! returns element type, return 4 for 3 channels element,
+ //!becuase 3 channels element actually use 4 channel space
+ int oclchannels() const;
+ //! returns step/elemSize1()
+ size_t step1() const;
+ //! returns oclMatrix size:
+ // width == number of columns, height == number of rows
+ Size size() const;
+ //! returns true if oclMatrix data is NULL
+ bool empty() const;
+
+ //! returns pointer to y-th row
+ uchar* ptr(int y = 0);
+ const uchar *ptr(int y = 0) const;
+
+ //! template version of the above method
+ template<typename _Tp> _Tp *ptr(int y = 0);
+ template<typename _Tp> const _Tp *ptr(int y = 0) const;
+
+ //! matrix transposition
+ oclMat t() const;
+
+ /*! includes several bit-fields:
+ - the magic signature
+ - continuity flag
+ - depth
+ - number of channels
+ */
+ int flags;
+ //! the number of rows and columns
+ int rows, cols;
+ //! a distance between successive rows in bytes; includes the gap if any
+ size_t step;
+ //! pointer to the data(OCL memory object)
+ uchar *data;
+
+ //! pointer to the reference counter;
+ // when oclMatrix points to user-allocated data, the pointer is NULL
+ int *refcount;
+
+ //! helper fields used in locateROI and adjustROI
+ //datastart and dataend are not used in current version
+ uchar *datastart;
+ uchar *dataend;
+
+ //! OpenCL context associated with the oclMat object.
+ Context *clCxt;
+ //add offset for handle ROI, calculated in byte
+ int offset;
+ //add wholerows and wholecols for the whole matrix, datastart and dataend are no longer used
+ int wholerows;
+ int wholecols;
+ };
+
+ // convert InputArray/OutputArray to oclMat references
+ CV_EXPORTS oclMat& getOclMatRef(InputArray src);
+ CV_EXPORTS oclMat& getOclMatRef(OutputArray src);
+
+ ///////////////////// mat split and merge /////////////////////////////////
+ //! Compose a multi-channel array from several single-channel arrays
+ // Support all types
+ CV_EXPORTS void merge(const oclMat *src, size_t n, oclMat &dst);
+ CV_EXPORTS void merge(const std::vector<oclMat> &src, oclMat &dst);
+
+ //! Divides multi-channel array into several single-channel arrays
+ // Support all types
+ CV_EXPORTS void split(const oclMat &src, oclMat *dst);
+ CV_EXPORTS void split(const oclMat &src, std::vector<oclMat> &dst);
+
+ ////////////////////////////// Arithmetics ///////////////////////////////////
+ //#if defined DOUBLE_SUPPORT
+ //typedef double F;
+ //#else
+ //typedef float F;
+ //#endif
+ // CV_EXPORTS void addWeighted(const oclMat& a,F alpha, const oclMat& b,F beta,F gama, oclMat& c);
+ CV_EXPORTS void addWeighted(const oclMat &a, double alpha, const oclMat &b, double beta, double gama, oclMat &c);
+ //! adds one matrix to another (c = a + b)
+ // supports all types except CV_8SC1,CV_8SC2,CV8SC3 and CV_8SC4
+ CV_EXPORTS void add(const oclMat &a, const oclMat &b, oclMat &c);
+ //! adds one matrix to another (c = a + b)
+ // supports all types except CV_8SC1,CV_8SC2,CV8SC3 and CV_8SC4
+ CV_EXPORTS void add(const oclMat &a, const oclMat &b, oclMat &c, const oclMat &mask);
+ //! adds scalar to a matrix (c = a + s)
+ // supports all types except CV_8SC1,CV_8SC2,CV8SC3 and CV_8SC4
+ CV_EXPORTS void add(const oclMat &a, const Scalar &sc, oclMat &c, const oclMat &mask = oclMat());
+ //! subtracts one matrix from another (c = a - b)
+ // supports all types except CV_8SC1,CV_8SC2,CV8SC3 and CV_8SC4
+ CV_EXPORTS void subtract(const oclMat &a, const oclMat &b, oclMat &c);
+ //! subtracts one matrix from another (c = a - b)
+ // supports all types except CV_8SC1,CV_8SC2,CV8SC3 and CV_8SC4
+ CV_EXPORTS void subtract(const oclMat &a, const oclMat &b, oclMat &c, const oclMat &mask);
+ //! subtracts scalar from a matrix (c = a - s)
+ // supports all types except CV_8SC1,CV_8SC2,CV8SC3 and CV_8SC4
+ CV_EXPORTS void subtract(const oclMat &a, const Scalar &sc, oclMat &c, const oclMat &mask = oclMat());
+ //! subtracts scalar from a matrix (c = a - s)
+ // supports all types except CV_8SC1,CV_8SC2,CV8SC3 and CV_8SC4
+ CV_EXPORTS void subtract(const Scalar &sc, const oclMat &a, oclMat &c, const oclMat &mask = oclMat());
+ //! computes element-wise product of the two arrays (c = a * b)
+ // supports all types except CV_8SC1,CV_8SC2,CV8SC3 and CV_8SC4
+ CV_EXPORTS void multiply(const oclMat &a, const oclMat &b, oclMat &c, double scale = 1);
+ //! multiplies matrix to a number (dst = scalar * src)
+ // supports CV_32FC1 only
+ CV_EXPORTS void multiply(double scalar, const oclMat &src, oclMat &dst);
+ //! computes element-wise quotient of the two arrays (c = a / b)
+ // supports all types except CV_8SC1,CV_8SC2,CV8SC3 and CV_8SC4
+ CV_EXPORTS void divide(const oclMat &a, const oclMat &b, oclMat &c, double scale = 1);
+ //! computes element-wise quotient of the two arrays (c = a / b)
+ // supports all types except CV_8SC1,CV_8SC2,CV8SC3 and CV_8SC4
+ CV_EXPORTS void divide(double scale, const oclMat &b, oclMat &c);
+
+ //! compares elements of two arrays (c = a <cmpop> b)
+ // supports except CV_8SC1,CV_8SC2,CV8SC3,CV_8SC4 types
+ CV_EXPORTS void compare(const oclMat &a, const oclMat &b, oclMat &c, int cmpop);
+
+ //! transposes the matrix
+ // supports CV_8UC1, 8UC4, 8SC4, 16UC2, 16SC2, 32SC1 and 32FC1.(the same as cuda)
+ CV_EXPORTS void transpose(const oclMat &src, oclMat &dst);
+
+ //! computes element-wise absolute difference of two arrays (c = abs(a - b))
+ // supports all types except CV_8SC1,CV_8SC2,CV8SC3 and CV_8SC4
+ CV_EXPORTS void absdiff(const oclMat &a, const oclMat &b, oclMat &c);
+ //! computes element-wise absolute difference of array and scalar (c = abs(a - s))
+ // supports all types except CV_8SC1,CV_8SC2,CV8SC3 and CV_8SC4
+ CV_EXPORTS void absdiff(const oclMat &a, const Scalar &s, oclMat &c);
+
+ //! computes mean value and standard deviation of all or selected array elements
+ // supports except CV_32F,CV_64F
+ CV_EXPORTS void meanStdDev(const oclMat &mtx, Scalar &mean, Scalar &stddev);
+
+ //! computes norm of array
+ // supports NORM_INF, NORM_L1, NORM_L2
+ // supports only CV_8UC1 type
+ CV_EXPORTS double norm(const oclMat &src1, int normType = NORM_L2);
+
+ //! computes norm of the difference between two arrays
+ // supports NORM_INF, NORM_L1, NORM_L2
+ // supports only CV_8UC1 type
+ CV_EXPORTS double norm(const oclMat &src1, const oclMat &src2, int normType = NORM_L2);
+
+ //! reverses the order of the rows, columns or both in a matrix
+ // supports all types
+ CV_EXPORTS void flip(const oclMat &a, oclMat &b, int flipCode);
+
+ //! computes sum of array elements
+ // disabled until fix crash
+ // support all types
+ CV_EXPORTS Scalar sum(const oclMat &m);
+ CV_EXPORTS Scalar absSum(const oclMat &m);
+ CV_EXPORTS Scalar sqrSum(const oclMat &m);
+
+ //! finds global minimum and maximum array elements and returns their values
+ // support all C1 types
+
+ CV_EXPORTS void minMax(const oclMat &src, double *minVal, double *maxVal = 0, const oclMat &mask = oclMat());
+ CV_EXPORTS void minMax_buf(const oclMat &src, double *minVal, double *maxVal, const oclMat &mask, oclMat& buf);
+
+ //! finds global minimum and maximum array elements and returns their values with locations
+ // support all C1 types
+
+ CV_EXPORTS void minMaxLoc(const oclMat &src, double *minVal, double *maxVal = 0, Point *minLoc = 0, Point *maxLoc = 0,
+ const oclMat &mask = oclMat());
+
+ //! counts non-zero array elements
+ // support all types
+ CV_EXPORTS int countNonZero(const oclMat &src);
+
+ //! transforms 8-bit unsigned integers using lookup table: dst(i)=lut(src(i))
+ // destination array will have the depth type as lut and the same channels number as source
+ //It supports 8UC1 8UC4 only
+ CV_EXPORTS void LUT(const oclMat &src, const oclMat &lut, oclMat &dst);
+
+ //! only 8UC1 and 256 bins is supported now
+ CV_EXPORTS void calcHist(const oclMat &mat_src, oclMat &mat_hist);
+ //! only 8UC1 and 256 bins is supported now
+ CV_EXPORTS void equalizeHist(const oclMat &mat_src, oclMat &mat_dst);
+
+ //! only 8UC1 is supported now
+ CV_EXPORTS Ptr<cv::CLAHE> createCLAHE(double clipLimit = 40.0, Size tileGridSize = Size(8, 8));
+
+ //! bilateralFilter
+ // supports 8UC1 8UC4
+ CV_EXPORTS void bilateralFilter(const oclMat& src, oclMat& dst, int d, double sigmaColor, double sigmaSpave, int borderType=BORDER_DEFAULT);
+ //! computes exponent of each matrix element (b = e**a)
+ // supports only CV_32FC1 type
+ CV_EXPORTS void exp(const oclMat &a, oclMat &b);
+
+ //! computes natural logarithm of absolute value of each matrix element: b = log(abs(a))
+ // supports only CV_32FC1 type
+ CV_EXPORTS void log(const oclMat &a, oclMat &b);
+
+ //! computes magnitude of each (x(i), y(i)) vector
+ // supports only CV_32F CV_64F type
+ CV_EXPORTS void magnitude(const oclMat &x, const oclMat &y, oclMat &magnitude);
+ CV_EXPORTS void magnitudeSqr(const oclMat &x, const oclMat &y, oclMat &magnitude);
+
+ CV_EXPORTS void magnitudeSqr(const oclMat &x, oclMat &magnitude);
+
+ //! computes angle (angle(i)) of each (x(i), y(i)) vector
+ // supports only CV_32F CV_64F type
+ CV_EXPORTS void phase(const oclMat &x, const oclMat &y, oclMat &angle, bool angleInDegrees = false);
+
+ //! the function raises every element of tne input array to p
+ //! support only CV_32F CV_64F type
+ CV_EXPORTS void pow(const oclMat &x, double p, oclMat &y);
+
+ //! converts Cartesian coordinates to polar
+ // supports only CV_32F CV_64F type
+ CV_EXPORTS void cartToPolar(const oclMat &x, const oclMat &y, oclMat &magnitude, oclMat &angle, bool angleInDegrees = false);
+
+ //! converts polar coordinates to Cartesian
+ // supports only CV_32F CV_64F type
+ CV_EXPORTS void polarToCart(const oclMat &magnitude, const oclMat &angle, oclMat &x, oclMat &y, bool angleInDegrees = false);
+
+ //! perfroms per-elements bit-wise inversion
+ // supports all types
+ CV_EXPORTS void bitwise_not(const oclMat &src, oclMat &dst);
+ //! calculates per-element bit-wise disjunction of two arrays
+ // supports all types
+ CV_EXPORTS void bitwise_or(const oclMat &src1, const oclMat &src2, oclMat &dst, const oclMat &mask = oclMat());
+ CV_EXPORTS void bitwise_or(const oclMat &src1, const Scalar &s, oclMat &dst, const oclMat &mask = oclMat());
+ //! calculates per-element bit-wise conjunction of two arrays
+ // supports all types
+ CV_EXPORTS void bitwise_and(const oclMat &src1, const oclMat &src2, oclMat &dst, const oclMat &mask = oclMat());
+ CV_EXPORTS void bitwise_and(const oclMat &src1, const Scalar &s, oclMat &dst, const oclMat &mask = oclMat());
+ //! calculates per-element bit-wise "exclusive or" operation
+ // supports all types
+ CV_EXPORTS void bitwise_xor(const oclMat &src1, const oclMat &src2, oclMat &dst, const oclMat &mask = oclMat());
+ CV_EXPORTS void bitwise_xor(const oclMat &src1, const Scalar &s, oclMat &dst, const oclMat &mask = oclMat());
+
+ //! Logical operators
+ CV_EXPORTS oclMat operator ~ (const oclMat &);
+ CV_EXPORTS oclMat operator | (const oclMat &, const oclMat &);
+ CV_EXPORTS oclMat operator & (const oclMat &, const oclMat &);
+ CV_EXPORTS oclMat operator ^ (const oclMat &, const oclMat &);
+
+
+ //! Mathematics operators
+ CV_EXPORTS oclMatExpr operator + (const oclMat &src1, const oclMat &src2);
+ CV_EXPORTS oclMatExpr operator - (const oclMat &src1, const oclMat &src2);
+ CV_EXPORTS oclMatExpr operator * (const oclMat &src1, const oclMat &src2);
+ CV_EXPORTS oclMatExpr operator / (const oclMat &src1, const oclMat &src2);
+
+ struct CV_EXPORTS ConvolveBuf
+ {
+ Size result_size;
+ Size block_size;
+ Size user_block_size;
+ Size dft_size;
+
+ oclMat image_spect, templ_spect, result_spect;
+ oclMat image_block, templ_block, result_data;
+
+ void create(Size image_size, Size templ_size);
+ static Size estimateBlockSize(Size result_size, Size templ_size);
+ };
+
+ //! computes convolution of two images, may use discrete Fourier transform
+ //! support only CV_32FC1 type
+ CV_EXPORTS void convolve(const oclMat &image, const oclMat &temp1, oclMat &result, bool ccorr = false);
+ CV_EXPORTS void convolve(const oclMat &image, const oclMat &temp1, oclMat &result, bool ccorr, ConvolveBuf& buf);
+
+ //! Performs a per-element multiplication of two Fourier spectrums.
+ //! Only full (not packed) CV_32FC2 complex spectrums in the interleaved format are supported for now.
+ //! support only CV_32FC2 type
+ CV_EXPORTS void mulSpectrums(const oclMat &a, const oclMat &b, oclMat &c, int flags, float scale, bool conjB = false);
+
+ CV_EXPORTS void cvtColor(const oclMat &src, oclMat &dst, int code , int dcn = 0);
+
+ //////////////////////////////// Filter Engine ////////////////////////////////
+
+ /*!
+ The Base Class for 1D or Row-wise Filters
+
+ This is the base class for linear or non-linear filters that process 1D data.
+ In particular, such filters are used for the "horizontal" filtering parts in separable filters.
+ */
+ class CV_EXPORTS BaseRowFilter_GPU
+ {
+ public:
+ BaseRowFilter_GPU(int ksize_, int anchor_, int bordertype_) : ksize(ksize_), anchor(anchor_), bordertype(bordertype_) {}
+ virtual ~BaseRowFilter_GPU() {}
+ virtual void operator()(const oclMat &src, oclMat &dst) = 0;
+ int ksize, anchor, bordertype;
+ };
+
+ /*!
+ The Base Class for Column-wise Filters
+
+ This is the base class for linear or non-linear filters that process columns of 2D arrays.
+ Such filters are used for the "vertical" filtering parts in separable filters.
+ */
+ class CV_EXPORTS BaseColumnFilter_GPU
+ {
+ public:
+ BaseColumnFilter_GPU(int ksize_, int anchor_, int bordertype_) : ksize(ksize_), anchor(anchor_), bordertype(bordertype_) {}
+ virtual ~BaseColumnFilter_GPU() {}
+ virtual void operator()(const oclMat &src, oclMat &dst) = 0;
+ int ksize, anchor, bordertype;
+ };
+
+ /*!
+ The Base Class for Non-Separable 2D Filters.
+
+ This is the base class for linear or non-linear 2D filters.
+ */
+ class CV_EXPORTS BaseFilter_GPU
+ {
+ public:
+ BaseFilter_GPU(const Size &ksize_, const Point &anchor_, const int &borderType_)
+ : ksize(ksize_), anchor(anchor_), borderType(borderType_) {}
+ virtual ~BaseFilter_GPU() {}
+ virtual void operator()(const oclMat &src, oclMat &dst) = 0;
+ Size ksize;
+ Point anchor;
+ int borderType;
+ };
+
+ /*!
+ The Base Class for Filter Engine.
+
+ The class can be used to apply an arbitrary filtering operation to an image.
+ It contains all the necessary intermediate buffers.
+ */
+ class CV_EXPORTS FilterEngine_GPU
+ {
+ public:
+ virtual ~FilterEngine_GPU() {}
+
+ virtual void apply(const oclMat &src, oclMat &dst, Rect roi = Rect(0, 0, -1, -1)) = 0;
+ };
+
+ //! returns the non-separable filter engine with the specified filter
+ CV_EXPORTS Ptr<FilterEngine_GPU> createFilter2D_GPU(const Ptr<BaseFilter_GPU> filter2D);
+
+ //! returns the primitive row filter with the specified kernel
+ CV_EXPORTS Ptr<BaseRowFilter_GPU> getLinearRowFilter_GPU(int srcType, int bufType, const Mat &rowKernel,
+ int anchor = -1, int bordertype = BORDER_DEFAULT);
+
+ //! returns the primitive column filter with the specified kernel
+ CV_EXPORTS Ptr<BaseColumnFilter_GPU> getLinearColumnFilter_GPU(int bufType, int dstType, const Mat &columnKernel,
+ int anchor = -1, int bordertype = BORDER_DEFAULT, double delta = 0.0);
+
+ //! returns the separable linear filter engine
+ CV_EXPORTS Ptr<FilterEngine_GPU> createSeparableLinearFilter_GPU(int srcType, int dstType, const Mat &rowKernel,
+ const Mat &columnKernel, const Point &anchor = Point(-1, -1), double delta = 0.0, int bordertype = BORDER_DEFAULT);
+
+ //! returns the separable filter engine with the specified filters
+ CV_EXPORTS Ptr<FilterEngine_GPU> createSeparableFilter_GPU(const Ptr<BaseRowFilter_GPU> &rowFilter,
+ const Ptr<BaseColumnFilter_GPU> &columnFilter);
+
+ //! returns the Gaussian filter engine
+ CV_EXPORTS Ptr<FilterEngine_GPU> createGaussianFilter_GPU(int type, Size ksize, double sigma1, double sigma2 = 0, int bordertype = BORDER_DEFAULT);
+
+ //! returns filter engine for the generalized Sobel operator
+ CV_EXPORTS Ptr<FilterEngine_GPU> createDerivFilter_GPU( int srcType, int dstType, int dx, int dy, int ksize, int borderType = BORDER_DEFAULT );
+
+ //! applies Laplacian operator to the image
+ // supports only ksize = 1 and ksize = 3 8UC1 8UC4 32FC1 32FC4 data type
+ CV_EXPORTS void Laplacian(const oclMat &src, oclMat &dst, int ddepth, int ksize = 1, double scale = 1);
+
+ //! returns 2D box filter
+ // supports CV_8UC1 and CV_8UC4 source type, dst type must be the same as source type
+ CV_EXPORTS Ptr<BaseFilter_GPU> getBoxFilter_GPU(int srcType, int dstType,
+ const Size &ksize, Point anchor = Point(-1, -1), int borderType = BORDER_DEFAULT);
+
+ //! returns box filter engine
+ CV_EXPORTS Ptr<FilterEngine_GPU> createBoxFilter_GPU(int srcType, int dstType, const Size &ksize,
+ const Point &anchor = Point(-1, -1), int borderType = BORDER_DEFAULT);
+
+ //! returns 2D filter with the specified kernel
+ // supports CV_8UC1 and CV_8UC4 types
+ CV_EXPORTS Ptr<BaseFilter_GPU> getLinearFilter_GPU(int srcType, int dstType, const Mat &kernel, const Size &ksize,
+ Point anchor = Point(-1, -1), int borderType = BORDER_DEFAULT);
+
+ //! returns the non-separable linear filter engine
+ CV_EXPORTS Ptr<FilterEngine_GPU> createLinearFilter_GPU(int srcType, int dstType, const Mat &kernel,
+ const Point &anchor = Point(-1, -1), int borderType = BORDER_DEFAULT);
+
+ //! smooths the image using the normalized box filter
+ // supports data type: CV_8UC1, CV_8UC4, CV_32FC1 and CV_32FC4
+ // supports border type: BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT,BORDER_REFLECT_101,BORDER_WRAP
+ CV_EXPORTS void boxFilter(const oclMat &src, oclMat &dst, int ddepth, Size ksize,
+ Point anchor = Point(-1, -1), int borderType = BORDER_DEFAULT);
+
+ //! returns 2D morphological filter
+ //! only MORPH_ERODE and MORPH_DILATE are supported
+ // supports CV_8UC1, CV_8UC4, CV_32FC1 and CV_32FC4 types
+ // kernel must have CV_8UC1 type, one rows and cols == ksize.width * ksize.height
+ CV_EXPORTS Ptr<BaseFilter_GPU> getMorphologyFilter_GPU(int op, int type, const Mat &kernel, const Size &ksize,
+ Point anchor = Point(-1, -1));
+
+ //! returns morphological filter engine. Only MORPH_ERODE and MORPH_DILATE are supported.
+ CV_EXPORTS Ptr<FilterEngine_GPU> createMorphologyFilter_GPU(int op, int type, const Mat &kernel,
+ const Point &anchor = Point(-1, -1), int iterations = 1);
+
+ //! a synonym for normalized box filter
+ // supports data type: CV_8UC1, CV_8UC4, CV_32FC1 and CV_32FC4
+ // supports border type: BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT,BORDER_REFLECT_101
+ static inline void blur(const oclMat &src, oclMat &dst, Size ksize, Point anchor = Point(-1, -1),
+ int borderType = BORDER_CONSTANT)
+ {
+ boxFilter(src, dst, -1, ksize, anchor, borderType);
+ }
+
+ //! applies non-separable 2D linear filter to the image
+ // Note, at the moment this function only works when anchor point is in the kernel center
+ // and kernel size supported is either 3x3 or 5x5; otherwise the function will fail to output valid result
+ CV_EXPORTS void filter2D(const oclMat &src, oclMat &dst, int ddepth, const Mat &kernel,
+ Point anchor = Point(-1, -1), int borderType = BORDER_DEFAULT);
+
+ //! applies separable 2D linear filter to the image
+ CV_EXPORTS void sepFilter2D(const oclMat &src, oclMat &dst, int ddepth, const Mat &kernelX, const Mat &kernelY,
+ Point anchor = Point(-1, -1), double delta = 0.0, int bordertype = BORDER_DEFAULT);
+
+ //! applies generalized Sobel operator to the image
+ // dst.type must equalize src.type
+ // supports data type: CV_8UC1, CV_8UC4, CV_32FC1 and CV_32FC4
+ // supports border type: BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT,BORDER_REFLECT_101
+ CV_EXPORTS void Sobel(const oclMat &src, oclMat &dst, int ddepth, int dx, int dy, int ksize = 3, double scale = 1, double delta = 0.0, int bordertype = BORDER_DEFAULT);
+
+ //! applies the vertical or horizontal Scharr operator to the image
+ // dst.type must equalize src.type
+ // supports data type: CV_8UC1, CV_8UC4, CV_32FC1 and CV_32FC4
+ // supports border type: BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT,BORDER_REFLECT_101
+ CV_EXPORTS void Scharr(const oclMat &src, oclMat &dst, int ddepth, int dx, int dy, double scale = 1, double delta = 0.0, int bordertype = BORDER_DEFAULT);
+
+ //! smooths the image using Gaussian filter.
+ // dst.type must equalize src.type
+ // supports data type: CV_8UC1, CV_8UC4, CV_32FC1 and CV_32FC4
+ // supports border type: BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT,BORDER_REFLECT_101
+ CV_EXPORTS void GaussianBlur(const oclMat &src, oclMat &dst, Size ksize, double sigma1, double sigma2 = 0, int bordertype = BORDER_DEFAULT);
+
+ //! erodes the image (applies the local minimum operator)
+ // supports data type: CV_8UC1, CV_8UC4, CV_32FC1 and CV_32FC4
+ CV_EXPORTS void erode( const oclMat &src, oclMat &dst, const Mat &kernel, Point anchor = Point(-1, -1), int iterations = 1,
+
+ int borderType = BORDER_CONSTANT, const Scalar &borderValue = morphologyDefaultBorderValue());
+
+
+ //! dilates the image (applies the local maximum operator)
+ // supports data type: CV_8UC1, CV_8UC4, CV_32FC1 and CV_32FC4
+ CV_EXPORTS void dilate( const oclMat &src, oclMat &dst, const Mat &kernel, Point anchor = Point(-1, -1), int iterations = 1,
+
+ int borderType = BORDER_CONSTANT, const Scalar &borderValue = morphologyDefaultBorderValue());
+
+
+ //! applies an advanced morphological operation to the image
+ CV_EXPORTS void morphologyEx( const oclMat &src, oclMat &dst, int op, const Mat &kernel, Point anchor = Point(-1, -1), int iterations = 1,
+
+ int borderType = BORDER_CONSTANT, const Scalar &borderValue = morphologyDefaultBorderValue());
+
+
+ ////////////////////////////// Image processing //////////////////////////////
+ //! Does mean shift filtering on GPU.
+ CV_EXPORTS void meanShiftFiltering(const oclMat &src, oclMat &dst, int sp, int sr,
+ TermCriteria criteria = TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 5, 1));
+
+ //! Does mean shift procedure on GPU.
+ CV_EXPORTS void meanShiftProc(const oclMat &src, oclMat &dstr, oclMat &dstsp, int sp, int sr,
+ TermCriteria criteria = TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 5, 1));
+
+ //! Does mean shift segmentation with elimiation of small regions.
+ CV_EXPORTS void meanShiftSegmentation(const oclMat &src, Mat &dst, int sp, int sr, int minsize,
+ TermCriteria criteria = TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 5, 1));
+
+ //! applies fixed threshold to the image.
+ // supports CV_8UC1 and CV_32FC1 data type
+ // supports threshold type: THRESH_BINARY, THRESH_BINARY_INV, THRESH_TRUNC, THRESH_TOZERO, THRESH_TOZERO_INV
+ CV_EXPORTS double threshold(const oclMat &src, oclMat &dst, double thresh, double maxVal, int type = THRESH_TRUNC);
+
+ //! resizes the image
+ // Supports INTER_NEAREST, INTER_LINEAR
+ // supports CV_8UC1, CV_8UC4, CV_32FC1 and CV_32FC4 types
+ CV_EXPORTS void resize(const oclMat &src, oclMat &dst, Size dsize, double fx = 0, double fy = 0, int interpolation = INTER_LINEAR);
+
+ //! Applies a generic geometrical transformation to an image.
+
+ // Supports INTER_NEAREST, INTER_LINEAR.
+
+ // Map1 supports CV_16SC2, CV_32FC2 types.
+
+ // Src supports CV_8UC1, CV_8UC2, CV_8UC4.
+
+ CV_EXPORTS void remap(const oclMat &src, oclMat &dst, oclMat &map1, oclMat &map2, int interpolation, int bordertype, const Scalar &value = Scalar());
+
+ //! copies 2D array to a larger destination array and pads borders with user-specifiable constant
+ // supports CV_8UC1, CV_8UC4, CV_32SC1 types
+ CV_EXPORTS void copyMakeBorder(const oclMat &src, oclMat &dst, int top, int bottom, int left, int right, int boardtype, const Scalar &value = Scalar());
+
+ //! Smoothes image using median filter
+ // The source 1- or 4-channel image. When m is 3 or 5, the image depth should be CV 8U or CV 32F.
+ CV_EXPORTS void medianFilter(const oclMat &src, oclMat &dst, int m);
+
+ //! warps the image using affine transformation
+ // Supports INTER_NEAREST, INTER_LINEAR, INTER_CUBIC
+ // supports CV_8UC1, CV_8UC4, CV_32FC1 and CV_32FC4 types
+ CV_EXPORTS void warpAffine(const oclMat &src, oclMat &dst, const Mat &M, Size dsize, int flags = INTER_LINEAR);
+
+ //! warps the image using perspective transformation
+ // Supports INTER_NEAREST, INTER_LINEAR, INTER_CUBIC
+ // supports CV_8UC1, CV_8UC4, CV_32FC1 and CV_32FC4 types
+ CV_EXPORTS void warpPerspective(const oclMat &src, oclMat &dst, const Mat &M, Size dsize, int flags = INTER_LINEAR);
+
+ //! computes the integral image and integral for the squared image
+ // sum will have CV_32S type, sqsum - CV32F type
+ // supports only CV_8UC1 source type
+ CV_EXPORTS void integral(const oclMat &src, oclMat &sum, oclMat &sqsum);
+ CV_EXPORTS void integral(const oclMat &src, oclMat &sum);
+ CV_EXPORTS void cornerHarris(const oclMat &src, oclMat &dst, int blockSize, int ksize, double k, int bordertype = cv::BORDER_DEFAULT);
+ CV_EXPORTS void cornerHarris_dxdy(const oclMat &src, oclMat &dst, oclMat &Dx, oclMat &Dy,
+ int blockSize, int ksize, double k, int bordertype = cv::BORDER_DEFAULT);
+ CV_EXPORTS void cornerMinEigenVal(const oclMat &src, oclMat &dst, int blockSize, int ksize, int bordertype = cv::BORDER_DEFAULT);
+ CV_EXPORTS void cornerMinEigenVal_dxdy(const oclMat &src, oclMat &dst, oclMat &Dx, oclMat &Dy,
+ int blockSize, int ksize, int bordertype = cv::BORDER_DEFAULT);
+
++
++ /////////////////////////////////// ML ///////////////////////////////////////////
++
++ //! Compute closest centers for each lines in source and lable it after center's index
++ // supports CV_32FC1/CV_32FC2/CV_32FC4 data type
++ CV_EXPORTS void distanceToCenters(oclMat &dists, oclMat &labels, const oclMat &src, const oclMat ¢ers);
++
++ //!Does k-means procedure on GPU
++ // supports CV_32FC1/CV_32FC2/CV_32FC4 data type
++ CV_EXPORTS double kmeans(const oclMat &src, int K, oclMat &bestLabels,
++ TermCriteria criteria, int attemps, int flags, oclMat ¢ers);
++
++
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////CascadeClassifier//////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#if 0
+ class CV_EXPORTS OclCascadeClassifier : public cv::CascadeClassifier
+ {
+ public:
+ OclCascadeClassifier() {};
+ ~OclCascadeClassifier() {};
+
+ CvSeq* oclHaarDetectObjects(oclMat &gimg, CvMemStorage *storage, double scaleFactor,
+ int minNeighbors, int flags, CvSize minSize = cvSize(0, 0), CvSize maxSize = cvSize(0, 0));
+ };
+#endif
+
+#if 0
+ class CV_EXPORTS OclCascadeClassifierBuf : public cv::CascadeClassifier
+ {
+ public:
+ OclCascadeClassifierBuf() :
+ m_flags(0), initialized(false), m_scaleFactor(0), buffers(NULL) {}
+
+ ~OclCascadeClassifierBuf() { release(); }
+
+ void detectMultiScale(oclMat &image, CV_OUT std::vector<cv::Rect>& faces,
+ double scaleFactor = 1.1, int minNeighbors = 3, int flags = 0,
+ Size minSize = Size(), Size maxSize = Size());
+ void release();
+
+ private:
+ void Init(const int rows, const int cols, double scaleFactor, int flags,
+ const int outputsz, const size_t localThreads[],
+ Size minSize, Size maxSize);
+ void CreateBaseBufs(const int datasize, const int totalclassifier, const int flags, const int outputsz);
+ void CreateFactorRelatedBufs(const int rows, const int cols, const int flags,
+ const double scaleFactor, const size_t localThreads[],
+ Size minSize, Size maxSize);
+ void GenResult(CV_OUT std::vector<cv::Rect>& faces, const std::vector<cv::Rect> &rectList, const std::vector<int> &rweights);
+
+ int m_rows;
+ int m_cols;
+ int m_flags;
+ int m_loopcount;
+ int m_nodenum;
+ bool findBiggestObject;
+ bool initialized;
+ double m_scaleFactor;
+ Size m_minSize;
+ Size m_maxSize;
+ std::vector<Size> sizev;
+ std::vector<float> scalev;
+ oclMat gimg1, gsum, gsqsum;
+ void * buffers;
+ };
+#endif
+
+ /////////////////////////////// Pyramid /////////////////////////////////////
+ CV_EXPORTS void pyrDown(const oclMat &src, oclMat &dst);
+
+ //! upsamples the source image and then smoothes it
+ CV_EXPORTS void pyrUp(const oclMat &src, oclMat &dst);
+
+ //! performs linear blending of two images
+ //! to avoid accuracy errors sum of weigths shouldn't be very close to zero
+ // supports only CV_8UC1 source type
+ CV_EXPORTS void blendLinear(const oclMat &img1, const oclMat &img2, const oclMat &weights1, const oclMat &weights2, oclMat &result);
+
+ //! computes vertical sum, supports only CV_32FC1 images
+ CV_EXPORTS void columnSum(const oclMat &src, oclMat &sum);
+
+ ///////////////////////////////////////// match_template /////////////////////////////////////////////////////////////
+ struct CV_EXPORTS MatchTemplateBuf
+ {
+ Size user_block_size;
+ oclMat imagef, templf;
+ std::vector<oclMat> images;
+ std::vector<oclMat> image_sums;
+ std::vector<oclMat> image_sqsums;
+ };
+
+ //! computes the proximity map for the raster template and the image where the template is searched for
+ // Supports TM_SQDIFF, TM_SQDIFF_NORMED, TM_CCORR, TM_CCORR_NORMED, TM_CCOEFF, TM_CCOEFF_NORMED for type 8UC1 and 8UC4
+ // Supports TM_SQDIFF, TM_CCORR for type 32FC1 and 32FC4
+ CV_EXPORTS void matchTemplate(const oclMat &image, const oclMat &templ, oclMat &result, int method);
+
+ //! computes the proximity map for the raster template and the image where the template is searched for
+ // Supports TM_SQDIFF, TM_SQDIFF_NORMED, TM_CCORR, TM_CCORR_NORMED, TM_CCOEFF, TM_CCOEFF_NORMED for type 8UC1 and 8UC4
+ // Supports TM_SQDIFF, TM_CCORR for type 32FC1 and 32FC4
+ CV_EXPORTS void matchTemplate(const oclMat &image, const oclMat &templ, oclMat &result, int method, MatchTemplateBuf &buf);
+
+
+
+ ///////////////////////////////////////////// Canny /////////////////////////////////////////////
+ struct CV_EXPORTS CannyBuf;
+
+ //! compute edges of the input image using Canny operator
+ // Support CV_8UC1 only
+ CV_EXPORTS void Canny(const oclMat &image, oclMat &edges, double low_thresh, double high_thresh, int apperture_size = 3, bool L2gradient = false);
+ CV_EXPORTS void Canny(const oclMat &image, CannyBuf &buf, oclMat &edges, double low_thresh, double high_thresh, int apperture_size = 3, bool L2gradient = false);
+ CV_EXPORTS void Canny(const oclMat &dx, const oclMat &dy, oclMat &edges, double low_thresh, double high_thresh, bool L2gradient = false);
+ CV_EXPORTS void Canny(const oclMat &dx, const oclMat &dy, CannyBuf &buf, oclMat &edges, double low_thresh, double high_thresh, bool L2gradient = false);
+
+ struct CV_EXPORTS CannyBuf
+ {
+ CannyBuf() : counter(NULL) {}
+ ~CannyBuf()
+ {
+ release();
+ }
+ explicit CannyBuf(const Size &image_size, int apperture_size = 3) : counter(NULL)
+ {
+ create(image_size, apperture_size);
+ }
+ CannyBuf(const oclMat &dx_, const oclMat &dy_);
+ void create(const Size &image_size, int apperture_size = 3);
+ void release();
+
+ oclMat dx, dy;
+ oclMat dx_buf, dy_buf;
+ oclMat magBuf, mapBuf;
+ oclMat trackBuf1, trackBuf2;
+ void *counter;
+ Ptr<FilterEngine_GPU> filterDX, filterDY;
+ };
+
+ ///////////////////////////////////////// Hough Transform /////////////////////////////////////////
+ //! HoughCircles
+ struct HoughCirclesBuf
+ {
+ oclMat edges;
+ oclMat accum;
+ oclMat srcPoints;
+ oclMat centers;
+ CannyBuf cannyBuf;
+ };
+
+ CV_EXPORTS void HoughCircles(const oclMat& src, oclMat& circles, int method, float dp, float minDist, int cannyThreshold, int votesThreshold, int minRadius, int maxRadius, int maxCircles = 4096);
+ CV_EXPORTS void HoughCircles(const oclMat& src, oclMat& circles, HoughCirclesBuf& buf, int method, float dp, float minDist, int cannyThreshold, int votesThreshold, int minRadius, int maxRadius, int maxCircles = 4096);
+ CV_EXPORTS void HoughCirclesDownload(const oclMat& d_circles, OutputArray h_circles);
+
+
+ ///////////////////////////////////////// clAmdFft related /////////////////////////////////////////
+ //! Performs a forward or inverse discrete Fourier transform (1D or 2D) of floating point matrix.
+ //! Param dft_size is the size of DFT transform.
+ //!
+ //! For complex-to-real transform it is assumed that the source matrix is packed in CLFFT's format.
+ // support src type of CV32FC1, CV32FC2
+ // support flags: DFT_INVERSE, DFT_REAL_OUTPUT, DFT_COMPLEX_OUTPUT, DFT_ROWS
+ // dft_size is the size of original input, which is used for transformation from complex to real.
+ // dft_size must be powers of 2, 3 and 5
+ // real to complex dft requires at least v1.8 clAmdFft
+ // real to complex dft output is not the same with cpu version
+ // real to complex and complex to real does not support DFT_ROWS
+ CV_EXPORTS void dft(const oclMat &src, oclMat &dst, Size dft_size = Size(0, 0), int flags = 0);
+
+ //! implements generalized matrix product algorithm GEMM from BLAS
+ // The functionality requires clAmdBlas library
+ // only support type CV_32FC1
+ // flag GEMM_3_T is not supported
+ CV_EXPORTS void gemm(const oclMat &src1, const oclMat &src2, double alpha,
+ const oclMat &src3, double beta, oclMat &dst, int flags = 0);
+
+ //////////////// HOG (Histogram-of-Oriented-Gradients) Descriptor and Object Detector //////////////
+
+ struct CV_EXPORTS HOGDescriptor
+
+ {
+
+ enum { DEFAULT_WIN_SIGMA = -1 };
+
+ enum { DEFAULT_NLEVELS = 64 };
+
+ enum { DESCR_FORMAT_ROW_BY_ROW, DESCR_FORMAT_COL_BY_COL };
+
+
+
+ HOGDescriptor(Size win_size = Size(64, 128), Size block_size = Size(16, 16),
+
+ Size block_stride = Size(8, 8), Size cell_size = Size(8, 8),
+
+ int nbins = 9, double win_sigma = DEFAULT_WIN_SIGMA,
+
+ double threshold_L2hys = 0.2, bool gamma_correction = true,
+
+ int nlevels = DEFAULT_NLEVELS);
+
+
+
+ size_t getDescriptorSize() const;
+
+ size_t getBlockHistogramSize() const;
+
+
+
+ void setSVMDetector(const std::vector<float> &detector);
+
+
+
+ static std::vector<float> getDefaultPeopleDetector();
+
+ static std::vector<float> getPeopleDetector48x96();
+
+ static std::vector<float> getPeopleDetector64x128();
+
+
+
+ void detect(const oclMat &img, std::vector<Point> &found_locations,
+
+ double hit_threshold = 0, Size win_stride = Size(),
+
+ Size padding = Size());
+
+
+
+ void detectMultiScale(const oclMat &img, std::vector<Rect> &found_locations,
+
+ double hit_threshold = 0, Size win_stride = Size(),
+
+ Size padding = Size(), double scale0 = 1.05,
+
+ int group_threshold = 2);
+
+
+
+ void getDescriptors(const oclMat &img, Size win_stride,
+
+ oclMat &descriptors,
+
+ int descr_format = DESCR_FORMAT_COL_BY_COL);
+
+
+
+ Size win_size;
+
+ Size block_size;
+
+ Size block_stride;
+
+ Size cell_size;
+
+ int nbins;
+
+ double win_sigma;
+
+ double threshold_L2hys;
+
+ bool gamma_correction;
+
+ int nlevels;
+
+
+
+ protected:
+
+ // initialize buffers; only need to do once in case of multiscale detection
+
+ void init_buffer(const oclMat &img, Size win_stride);
+
+
+
+ void computeBlockHistograms(const oclMat &img);
+
+ void computeGradient(const oclMat &img, oclMat &grad, oclMat &qangle);
+
+
+
+ double getWinSigma() const;
+
+ bool checkDetectorSize() const;
+
+
+
+ static int numPartsWithin(int size, int part_size, int stride);
+
+ static Size numPartsWithin(Size size, Size part_size, Size stride);
+
+
+
+ // Coefficients of the separating plane
+
+ float free_coef;
+
+ oclMat detector;
+
+
+
+ // Results of the last classification step
+
+ oclMat labels;
+
+ Mat labels_host;
+
+
+
+ // Results of the last histogram evaluation step
+
+ oclMat block_hists;
+
+
+
+ // Gradients conputation results
+
+ oclMat grad, qangle;
+
+
+
+ // scaled image
+
+ oclMat image_scale;
+
+
+
+ // effect size of input image (might be different from original size after scaling)
+
+ Size effect_size;
+
+ };
+
+
+ ////////////////////////feature2d_ocl/////////////////
+ /****************************************************************************************\
+ * Distance *
+ \****************************************************************************************/
+ template<typename T>
+ struct CV_EXPORTS Accumulator
+ {
+ typedef T Type;
+ };
+ template<> struct Accumulator<unsigned char>
+ {
+ typedef float Type;
+ };
+ template<> struct Accumulator<unsigned short>
+ {
+ typedef float Type;
+ };
+ template<> struct Accumulator<char>
+ {
+ typedef float Type;
+ };
+ template<> struct Accumulator<short>
+ {
+ typedef float Type;
+ };
+
+ /*
+ * Manhattan distance (city block distance) functor
+ */
+ template<class T>
+ struct CV_EXPORTS L1
+ {
+ enum { normType = NORM_L1 };
+ typedef T ValueType;
+ typedef typename Accumulator<T>::Type ResultType;
+
+ ResultType operator()( const T *a, const T *b, int size ) const
+ {
+ return normL1<ValueType, ResultType>(a, b, size);
+ }
+ };
+
+ /*
+ * Euclidean distance functor
+ */
+ template<class T>
+ struct CV_EXPORTS L2
+ {
+ enum { normType = NORM_L2 };
+ typedef T ValueType;
+ typedef typename Accumulator<T>::Type ResultType;
+
+ ResultType operator()( const T *a, const T *b, int size ) const
+ {
+ return (ResultType)std::sqrt((double)normL2Sqr<ValueType, ResultType>(a, b, size));
+ }
+ };
+
+ /*
+ * Hamming distance functor - counts the bit differences between two strings - useful for the Brief descriptor
+ * bit count of A exclusive XOR'ed with B
+ */
+ struct CV_EXPORTS Hamming
+ {
+ enum { normType = NORM_HAMMING };
+ typedef unsigned char ValueType;
+ typedef int ResultType;
+
+ /** this will count the bits in a ^ b
+ */
+ ResultType operator()( const unsigned char *a, const unsigned char *b, int size ) const
+ {
+ return normHamming(a, b, size);
+ }
+ };
+
+ ////////////////////////////////// BruteForceMatcher //////////////////////////////////
+
+ class CV_EXPORTS BruteForceMatcher_OCL_base
+ {
+ public:
+ enum DistType {L1Dist = 0, L2Dist, HammingDist};
+ explicit BruteForceMatcher_OCL_base(DistType distType = L2Dist);
+
+ // Add descriptors to train descriptor collection
+ void add(const std::vector<oclMat> &descCollection);
+
+ // Get train descriptors collection
+ const std::vector<oclMat> &getTrainDescriptors() const;
+
+ // Clear train descriptors collection
+ void clear();
+
+ // Return true if there are not train descriptors in collection
+ bool empty() const;
+
+ // Return true if the matcher supports mask in match methods
+ bool isMaskSupported() const;
+
+ // Find one best match for each query descriptor
+ void matchSingle(const oclMat &query, const oclMat &train,
+ oclMat &trainIdx, oclMat &distance,
+ const oclMat &mask = oclMat());
+
+ // Download trainIdx and distance and convert it to CPU vector with DMatch
+ static void matchDownload(const oclMat &trainIdx, const oclMat &distance, std::vector<DMatch> &matches);
+ // Convert trainIdx and distance to vector with DMatch
+ static void matchConvert(const Mat &trainIdx, const Mat &distance, std::vector<DMatch> &matches);
+
+ // Find one best match for each query descriptor
+ void match(const oclMat &query, const oclMat &train, std::vector<DMatch> &matches, const oclMat &mask = oclMat());
+
+ // Make gpu collection of trains and masks in suitable format for matchCollection function
+ void makeGpuCollection(oclMat &trainCollection, oclMat &maskCollection, const std::vector<oclMat> &masks = std::vector<oclMat>());
+
+ // Find one best match from train collection for each query descriptor
+ void matchCollection(const oclMat &query, const oclMat &trainCollection,
+ oclMat &trainIdx, oclMat &imgIdx, oclMat &distance,
+ const oclMat &masks = oclMat());
+
+ // Download trainIdx, imgIdx and distance and convert it to vector with DMatch
+ static void matchDownload(const oclMat &trainIdx, const oclMat &imgIdx, const oclMat &distance, std::vector<DMatch> &matches);
+ // Convert trainIdx, imgIdx and distance to vector with DMatch
+ static void matchConvert(const Mat &trainIdx, const Mat &imgIdx, const Mat &distance, std::vector<DMatch> &matches);
+
+ // Find one best match from train collection for each query descriptor.
+ void match(const oclMat &query, std::vector<DMatch> &matches, const std::vector<oclMat> &masks = std::vector<oclMat>());
+
+ // Find k best matches for each query descriptor (in increasing order of distances)
+ void knnMatchSingle(const oclMat &query, const oclMat &train,
+ oclMat &trainIdx, oclMat &distance, oclMat &allDist, int k,
+ const oclMat &mask = oclMat());
+
+ // Download trainIdx and distance and convert it to vector with DMatch
+ // compactResult is used when mask is not empty. If compactResult is false matches
+ // vector will have the same size as queryDescriptors rows. If compactResult is true
+ // matches vector will not contain matches for fully masked out query descriptors.
+ static void knnMatchDownload(const oclMat &trainIdx, const oclMat &distance,
+ std::vector< std::vector<DMatch> > &matches, bool compactResult = false);
+ // Convert trainIdx and distance to vector with DMatch
+ static void knnMatchConvert(const Mat &trainIdx, const Mat &distance,
+ std::vector< std::vector<DMatch> > &matches, bool compactResult = false);
+
+ // Find k best matches for each query descriptor (in increasing order of distances).
+ // compactResult is used when mask is not empty. If compactResult is false matches
+ // vector will have the same size as queryDescriptors rows. If compactResult is true
+ // matches vector will not contain matches for fully masked out query descriptors.
+ void knnMatch(const oclMat &query, const oclMat &train,
+ std::vector< std::vector<DMatch> > &matches, int k, const oclMat &mask = oclMat(),
+ bool compactResult = false);
+
+ // Find k best matches from train collection for each query descriptor (in increasing order of distances)
+ void knnMatch2Collection(const oclMat &query, const oclMat &trainCollection,
+ oclMat &trainIdx, oclMat &imgIdx, oclMat &distance,
+ const oclMat &maskCollection = oclMat());
+
+ // Download trainIdx and distance and convert it to vector with DMatch
+ // compactResult is used when mask is not empty. If compactResult is false matches
+ // vector will have the same size as queryDescriptors rows. If compactResult is true
+ // matches vector will not contain matches for fully masked out query descriptors.
+ static void knnMatch2Download(const oclMat &trainIdx, const oclMat &imgIdx, const oclMat &distance,
+ std::vector< std::vector<DMatch> > &matches, bool compactResult = false);
+ // Convert trainIdx and distance to vector with DMatch
+ static void knnMatch2Convert(const Mat &trainIdx, const Mat &imgIdx, const Mat &distance,
+ std::vector< std::vector<DMatch> > &matches, bool compactResult = false);
+
+ // Find k best matches for each query descriptor (in increasing order of distances).
+ // compactResult is used when mask is not empty. If compactResult is false matches
+ // vector will have the same size as queryDescriptors rows. If compactResult is true
+ // matches vector will not contain matches for fully masked out query descriptors.
+ void knnMatch(const oclMat &query, std::vector< std::vector<DMatch> > &matches, int k,
+ const std::vector<oclMat> &masks = std::vector<oclMat>(), bool compactResult = false);
+
+ // Find best matches for each query descriptor which have distance less than maxDistance.
+ // nMatches.at<int>(0, queryIdx) will contain matches count for queryIdx.
+ // carefully nMatches can be greater than trainIdx.cols - it means that matcher didn't find all matches,
+ // because it didn't have enough memory.
+ // If trainIdx is empty, then trainIdx and distance will be created with size nQuery x max((nTrain / 100), 10),
+ // otherwize user can pass own allocated trainIdx and distance with size nQuery x nMaxMatches
+ // Matches doesn't sorted.
+ void radiusMatchSingle(const oclMat &query, const oclMat &train,
+ oclMat &trainIdx, oclMat &distance, oclMat &nMatches, float maxDistance,
+ const oclMat &mask = oclMat());
+
+ // Download trainIdx, nMatches and distance and convert it to vector with DMatch.
+ // matches will be sorted in increasing order of distances.
+ // compactResult is used when mask is not empty. If compactResult is false matches
+ // vector will have the same size as queryDescriptors rows. If compactResult is true
+ // matches vector will not contain matches for fully masked out query descriptors.
+ static void radiusMatchDownload(const oclMat &trainIdx, const oclMat &distance, const oclMat &nMatches,
+ std::vector< std::vector<DMatch> > &matches, bool compactResult = false);
+ // Convert trainIdx, nMatches and distance to vector with DMatch.
+ static void radiusMatchConvert(const Mat &trainIdx, const Mat &distance, const Mat &nMatches,
+ std::vector< std::vector<DMatch> > &matches, bool compactResult = false);
+
+ // Find best matches for each query descriptor which have distance less than maxDistance
+ // in increasing order of distances).
+ void radiusMatch(const oclMat &query, const oclMat &train,
+ std::vector< std::vector<DMatch> > &matches, float maxDistance,
+ const oclMat &mask = oclMat(), bool compactResult = false);
+
+ // Find best matches for each query descriptor which have distance less than maxDistance.
+ // If trainIdx is empty, then trainIdx and distance will be created with size nQuery x max((nQuery / 100), 10),
+ // otherwize user can pass own allocated trainIdx and distance with size nQuery x nMaxMatches
+ // Matches doesn't sorted.
+ void radiusMatchCollection(const oclMat &query, oclMat &trainIdx, oclMat &imgIdx, oclMat &distance, oclMat &nMatches, float maxDistance,
+ const std::vector<oclMat> &masks = std::vector<oclMat>());
+
+ // Download trainIdx, imgIdx, nMatches and distance and convert it to vector with DMatch.
+ // matches will be sorted in increasing order of distances.
+ // compactResult is used when mask is not empty. If compactResult is false matches
+ // vector will have the same size as queryDescriptors rows. If compactResult is true
+ // matches vector will not contain matches for fully masked out query descriptors.
+ static void radiusMatchDownload(const oclMat &trainIdx, const oclMat &imgIdx, const oclMat &distance, const oclMat &nMatches,
+ std::vector< std::vector<DMatch> > &matches, bool compactResult = false);
+ // Convert trainIdx, nMatches and distance to vector with DMatch.
+ static void radiusMatchConvert(const Mat &trainIdx, const Mat &imgIdx, const Mat &distance, const Mat &nMatches,
+ std::vector< std::vector<DMatch> > &matches, bool compactResult = false);
+
+ // Find best matches from train collection for each query descriptor which have distance less than
+ // maxDistance (in increasing order of distances).
+ void radiusMatch(const oclMat &query, std::vector< std::vector<DMatch> > &matches, float maxDistance,
+ const std::vector<oclMat> &masks = std::vector<oclMat>(), bool compactResult = false);
+
+ DistType distType;
+
+ private:
+ std::vector<oclMat> trainDescCollection;
+ };
+
+ template <class Distance>
+ class CV_EXPORTS BruteForceMatcher_OCL;
+
+ template <typename T>
+ class CV_EXPORTS BruteForceMatcher_OCL< L1<T> > : public BruteForceMatcher_OCL_base
+ {
+ public:
+ explicit BruteForceMatcher_OCL() : BruteForceMatcher_OCL_base(L1Dist) {}
+ explicit BruteForceMatcher_OCL(L1<T> /*d*/) : BruteForceMatcher_OCL_base(L1Dist) {}
+ };
+ template <typename T>
+ class CV_EXPORTS BruteForceMatcher_OCL< L2<T> > : public BruteForceMatcher_OCL_base
+ {
+ public:
+ explicit BruteForceMatcher_OCL() : BruteForceMatcher_OCL_base(L2Dist) {}
+ explicit BruteForceMatcher_OCL(L2<T> /*d*/) : BruteForceMatcher_OCL_base(L2Dist) {}
+ };
+ template <> class CV_EXPORTS BruteForceMatcher_OCL< Hamming > : public BruteForceMatcher_OCL_base
+ {
+ public:
+ explicit BruteForceMatcher_OCL() : BruteForceMatcher_OCL_base(HammingDist) {}
+ explicit BruteForceMatcher_OCL(Hamming /*d*/) : BruteForceMatcher_OCL_base(HammingDist) {}
+ };
+
+ class CV_EXPORTS BFMatcher_OCL : public BruteForceMatcher_OCL_base
+ {
+ public:
+ explicit BFMatcher_OCL(int norm = NORM_L2) : BruteForceMatcher_OCL_base(norm == NORM_L1 ? L1Dist : norm == NORM_L2 ? L2Dist : HammingDist) {}
+ };
+
+ class CV_EXPORTS GoodFeaturesToTrackDetector_OCL
+ {
+ public:
+ explicit GoodFeaturesToTrackDetector_OCL(int maxCorners = 1000, double qualityLevel = 0.01, double minDistance = 0.0,
+ int blockSize = 3, bool useHarrisDetector = false, double harrisK = 0.04);
+
+ //! return 1 rows matrix with CV_32FC2 type
+ void operator ()(const oclMat& image, oclMat& corners, const oclMat& mask = oclMat());
+ //! download points of type Point2f to a vector. the vector's content will be erased
+ void downloadPoints(const oclMat &points, std::vector<Point2f> &points_v);
+
+ int maxCorners;
+ double qualityLevel;
+ double minDistance;
+
+ int blockSize;
+ bool useHarrisDetector;
+ double harrisK;
+ void releaseMemory()
+ {
+ Dx_.release();
+ Dy_.release();
+ eig_.release();
+ minMaxbuf_.release();
+ tmpCorners_.release();
+ }
+ private:
+ oclMat Dx_;
+ oclMat Dy_;
+ oclMat eig_;
+ oclMat minMaxbuf_;
+ oclMat tmpCorners_;
+ };
+
+ inline GoodFeaturesToTrackDetector_OCL::GoodFeaturesToTrackDetector_OCL(int maxCorners_, double qualityLevel_, double minDistance_,
+ int blockSize_, bool useHarrisDetector_, double harrisK_)
+ {
+ maxCorners = maxCorners_;
+ qualityLevel = qualityLevel_;
+ minDistance = minDistance_;
+ blockSize = blockSize_;
+ useHarrisDetector = useHarrisDetector_;
+ harrisK = harrisK_;
+ }
+
+ /////////////////////////////// PyrLKOpticalFlow /////////////////////////////////////
+
+ class CV_EXPORTS PyrLKOpticalFlow
+ {
+ public:
+ PyrLKOpticalFlow()
+ {
+ winSize = Size(21, 21);
+ maxLevel = 3;
+ iters = 30;
+ derivLambda = 0.5;
+ useInitialFlow = false;
+ minEigThreshold = 1e-4f;
+ getMinEigenVals = false;
+ isDeviceArch11_ = false;
+ }
+
+ void sparse(const oclMat &prevImg, const oclMat &nextImg, const oclMat &prevPts, oclMat &nextPts,
+ oclMat &status, oclMat *err = 0);
+
+ void dense(const oclMat &prevImg, const oclMat &nextImg, oclMat &u, oclMat &v, oclMat *err = 0);
+
+ Size winSize;
+ int maxLevel;
+ int iters;
+ double derivLambda;
+ bool useInitialFlow;
+ float minEigThreshold;
+ bool getMinEigenVals;
+
+ void releaseMemory()
+ {
+ dx_calcBuf_.release();
+ dy_calcBuf_.release();
+
+ prevPyr_.clear();
+ nextPyr_.clear();
+
+ dx_buf_.release();
+ dy_buf_.release();
+ }
+
+ private:
+ void calcSharrDeriv(const oclMat &src, oclMat &dx, oclMat &dy);
+
+ void buildImagePyramid(const oclMat &img0, std::vector<oclMat> &pyr, bool withBorder);
+
+ oclMat dx_calcBuf_;
+ oclMat dy_calcBuf_;
+
+ std::vector<oclMat> prevPyr_;
+ std::vector<oclMat> nextPyr_;
+
+ oclMat dx_buf_;
+ oclMat dy_buf_;
+
+ oclMat uPyr_[2];
+ oclMat vPyr_[2];
+
+ bool isDeviceArch11_;
+ };
+
+ class CV_EXPORTS FarnebackOpticalFlow
+ {
+ public:
+ FarnebackOpticalFlow();
+
+ int numLevels;
+ double pyrScale;
+ bool fastPyramids;
+ int winSize;
+ int numIters;
+ int polyN;
+ double polySigma;
+ int flags;
+
+ void operator ()(const oclMat &frame0, const oclMat &frame1, oclMat &flowx, oclMat &flowy);
+
+ void releaseMemory();
+
+ private:
+ void prepareGaussian(
+ int n, double sigma, float *g, float *xg, float *xxg,
+ double &ig11, double &ig03, double &ig33, double &ig55);
+
+ void setPolynomialExpansionConsts(int n, double sigma);
+
+ void updateFlow_boxFilter(
+ const oclMat& R0, const oclMat& R1, oclMat& flowx, oclMat &flowy,
+ oclMat& M, oclMat &bufM, int blockSize, bool updateMatrices);
+
+ void updateFlow_gaussianBlur(
+ const oclMat& R0, const oclMat& R1, oclMat& flowx, oclMat& flowy,
+ oclMat& M, oclMat &bufM, int blockSize, bool updateMatrices);
+
+ oclMat frames_[2];
+ oclMat pyrLevel_[2], M_, bufM_, R_[2], blurredFrame_[2];
+ std::vector<oclMat> pyramid0_, pyramid1_;
+ };
+
+ //////////////// build warping maps ////////////////////
+ //! builds plane warping maps
+ CV_EXPORTS void buildWarpPlaneMaps(Size src_size, Rect dst_roi, const Mat &K, const Mat &R, const Mat &T, float scale, oclMat &map_x, oclMat &map_y);
+ //! builds cylindrical warping maps
+ CV_EXPORTS void buildWarpCylindricalMaps(Size src_size, Rect dst_roi, const Mat &K, const Mat &R, float scale, oclMat &map_x, oclMat &map_y);
+ //! builds spherical warping maps
+ CV_EXPORTS void buildWarpSphericalMaps(Size src_size, Rect dst_roi, const Mat &K, const Mat &R, float scale, oclMat &map_x, oclMat &map_y);
+ //! builds Affine warping maps
+ CV_EXPORTS void buildWarpAffineMaps(const Mat &M, bool inverse, Size dsize, oclMat &xmap, oclMat &ymap);
+
+ //! builds Perspective warping maps
+ CV_EXPORTS void buildWarpPerspectiveMaps(const Mat &M, bool inverse, Size dsize, oclMat &xmap, oclMat &ymap);
+
+ ///////////////////////////////////// interpolate frames //////////////////////////////////////////////
+ //! Interpolate frames (images) using provided optical flow (displacement field).
+ //! frame0 - frame 0 (32-bit floating point images, single channel)
+ //! frame1 - frame 1 (the same type and size)
+ //! fu - forward horizontal displacement
+ //! fv - forward vertical displacement
+ //! bu - backward horizontal displacement
+ //! bv - backward vertical displacement
+ //! pos - new frame position
+ //! newFrame - new frame
+ //! buf - temporary buffer, will have width x 6*height size, CV_32FC1 type and contain 6 oclMat;
+ //! occlusion masks 0, occlusion masks 1,
+ //! interpolated forward flow 0, interpolated forward flow 1,
+ //! interpolated backward flow 0, interpolated backward flow 1
+ //!
+ CV_EXPORTS void interpolateFrames(const oclMat &frame0, const oclMat &frame1,
+ const oclMat &fu, const oclMat &fv,
+ const oclMat &bu, const oclMat &bv,
+ float pos, oclMat &newFrame, oclMat &buf);
+
+ //! computes moments of the rasterized shape or a vector of points
+ CV_EXPORTS Moments ocl_moments(InputArray _array, bool binaryImage);
+
+ class CV_EXPORTS StereoBM_OCL
+ {
+ public:
+ enum { BASIC_PRESET = 0, PREFILTER_XSOBEL = 1 };
+
+ enum { DEFAULT_NDISP = 64, DEFAULT_WINSZ = 19 };
+
+ //! the default constructor
+ StereoBM_OCL();
+ //! the full constructor taking the camera-specific preset, number of disparities and the SAD window size. ndisparities must be multiple of 8.
+ StereoBM_OCL(int preset, int ndisparities = DEFAULT_NDISP, int winSize = DEFAULT_WINSZ);
+
+ //! the stereo correspondence operator. Finds the disparity for the specified rectified stereo pair
+ //! Output disparity has CV_8U type.
+ void operator() ( const oclMat &left, const oclMat &right, oclMat &disparity);
+
+ //! Some heuristics that tries to estmate
+ // if current GPU will be faster then CPU in this algorithm.
+ // It queries current active device.
+ static bool checkIfGpuCallReasonable();
+
+ int preset;
+ int ndisp;
+ int winSize;
+
+ // If avergeTexThreshold == 0 => post procesing is disabled
+ // If avergeTexThreshold != 0 then disparity is set 0 in each point (x,y) where for left image
+ // SumOfHorizontalGradiensInWindow(x, y, winSize) < (winSize * winSize) * avergeTexThreshold
+ // i.e. input left image is low textured.
+ float avergeTexThreshold;
+ private:
+ oclMat minSSD, leBuf, riBuf;
+ };
+
+ class CV_EXPORTS StereoBeliefPropagation
+ {
+ public:
+ enum { DEFAULT_NDISP = 64 };
+ enum { DEFAULT_ITERS = 5 };
+ enum { DEFAULT_LEVELS = 5 };
+ static void estimateRecommendedParams(int width, int height, int &ndisp, int &iters, int &levels);
+ explicit StereoBeliefPropagation(int ndisp = DEFAULT_NDISP,
+ int iters = DEFAULT_ITERS,
+ int levels = DEFAULT_LEVELS,
+ int msg_type = CV_16S);
+ StereoBeliefPropagation(int ndisp, int iters, int levels,
+ float max_data_term, float data_weight,
+ float max_disc_term, float disc_single_jump,
+ int msg_type = CV_32F);
+ void operator()(const oclMat &left, const oclMat &right, oclMat &disparity);
+ void operator()(const oclMat &data, oclMat &disparity);
+ int ndisp;
+ int iters;
+ int levels;
+ float max_data_term;
+ float data_weight;
+ float max_disc_term;
+ float disc_single_jump;
+ int msg_type;
+ private:
+ oclMat u, d, l, r, u2, d2, l2, r2;
+ std::vector<oclMat> datas;
+ oclMat out;
+ };
+
+ class CV_EXPORTS StereoConstantSpaceBP
+ {
+ public:
+ enum { DEFAULT_NDISP = 128 };
+ enum { DEFAULT_ITERS = 8 };
+ enum { DEFAULT_LEVELS = 4 };
+ enum { DEFAULT_NR_PLANE = 4 };
+ static void estimateRecommendedParams(int width, int height, int &ndisp, int &iters, int &levels, int &nr_plane);
+ explicit StereoConstantSpaceBP(
+ int ndisp = DEFAULT_NDISP,
+ int iters = DEFAULT_ITERS,
+ int levels = DEFAULT_LEVELS,
+ int nr_plane = DEFAULT_NR_PLANE,
+ int msg_type = CV_32F);
+ StereoConstantSpaceBP(int ndisp, int iters, int levels, int nr_plane,
+ float max_data_term, float data_weight, float max_disc_term, float disc_single_jump,
+ int min_disp_th = 0,
+ int msg_type = CV_32F);
+ void operator()(const oclMat &left, const oclMat &right, oclMat &disparity);
+ int ndisp;
+ int iters;
+ int levels;
+ int nr_plane;
+ float max_data_term;
+ float data_weight;
+ float max_disc_term;
+ float disc_single_jump;
+ int min_disp_th;
+ int msg_type;
+ bool use_local_init_data_cost;
+ private:
+ oclMat u[2], d[2], l[2], r[2];
+ oclMat disp_selected_pyr[2];
+ oclMat data_cost;
+ oclMat data_cost_selected;
+ oclMat temp;
+ oclMat out;
+ };
+
+ // Implementation of the Zach, Pock and Bischof Dual TV-L1 Optical Flow method
+ //
+ // see reference:
+ // [1] C. Zach, T. Pock and H. Bischof, "A Duality Based Approach for Realtime TV-L1 Optical Flow".
+ // [2] Javier Sanchez, Enric Meinhardt-Llopis and Gabriele Facciolo. "TV-L1 Optical Flow Estimation".
+ class CV_EXPORTS OpticalFlowDual_TVL1_OCL
+ {
+ public:
+ OpticalFlowDual_TVL1_OCL();
+
+ void operator ()(const oclMat& I0, const oclMat& I1, oclMat& flowx, oclMat& flowy);
+
+ void collectGarbage();
+
+ /**
+ * Time step of the numerical scheme.
+ */
+ double tau;
+
+ /**
+ * Weight parameter for the data term, attachment parameter.
+ * This is the most relevant parameter, which determines the smoothness of the output.
+ * The smaller this parameter is, the smoother the solutions we obtain.
+ * It depends on the range of motions of the images, so its value should be adapted to each image sequence.
+ */
+ double lambda;
+
+ /**
+ * Weight parameter for (u - v)^2, tightness parameter.
+ * It serves as a link between the attachment and the regularization terms.
+ * In theory, it should have a small value in order to maintain both parts in correspondence.
+ * The method is stable for a large range of values of this parameter.
+ */
+ double theta;
+
+ /**
+ * Number of scales used to create the pyramid of images.
+ */
+ int nscales;
+
+ /**
+ * Number of warpings per scale.
+ * Represents the number of times that I1(x+u0) and grad( I1(x+u0) ) are computed per scale.
+ * This is a parameter that assures the stability of the method.
+ * It also affects the running time, so it is a compromise between speed and accuracy.
+ */
+ int warps;
+
+ /**
+ * Stopping criterion threshold used in the numerical scheme, which is a trade-off between precision and running time.
+ * A small value will yield more accurate solutions at the expense of a slower convergence.
+ */
+ double epsilon;
+
+ /**
+ * Stopping criterion iterations number used in the numerical scheme.
+ */
+ int iterations;
+
+ bool useInitialFlow;
+
+ private:
+ void procOneScale(const oclMat& I0, const oclMat& I1, oclMat& u1, oclMat& u2);
+
+ std::vector<oclMat> I0s;
+ std::vector<oclMat> I1s;
+ std::vector<oclMat> u1s;
+ std::vector<oclMat> u2s;
+
+ oclMat I1x_buf;
+ oclMat I1y_buf;
+
+ oclMat I1w_buf;
+ oclMat I1wx_buf;
+ oclMat I1wy_buf;
+
+ oclMat grad_buf;
+ oclMat rho_c_buf;
+
+ oclMat p11_buf;
+ oclMat p12_buf;
+ oclMat p21_buf;
+ oclMat p22_buf;
+
+ oclMat diff_buf;
+ oclMat norm_buf;
+ };
+ }
+}
+#if defined _MSC_VER && _MSC_VER >= 1200
+# pragma warning( push)
+# pragma warning( disable: 4267)
+#endif
+#include "opencv2/ocl/matrix_operations.hpp"
+#if defined _MSC_VER && _MSC_VER >= 1200
+# pragma warning( pop)
+#endif
+
+#endif /* __OPENCV_OCL_HPP__ */
--- /dev/null
-static void generateRandomCenter(const vector<Vec2f>& box, float* center, RNG& rng)
+ /*M///////////////////////////////////////////////////////////////////////////////////////
+ //
+ // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+ //
+ // By downloading, copying, installing or using the software you agree to this license.
+ // If you do not agree to this license, do not download, install,
+ // copy or use the software.
+ //
+ //
+ // License Agreement
+ // For Open Source Computer Vision Library
+ //
+ // Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
+ // Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
+ // Third party copyrights are property of their respective owners.
+ //
+ // @Authors
+ // Xiaopeng Fu, fuxiaopeng2222@163.com
+ //
+ // Redistribution and use in source and binary forms, with or without modification,
+ // are permitted provided that the following conditions are met:
+ //
+ // * Redistribution's of source code must retain the above copyright notice,
+ // this list of conditions and the following disclaimer.
+ //
+ // * Redistribution's in binary form must reproduce the above copyright notice,
+ // this list of conditions and the following disclaimer in the documentation
+ // and/or other oclMaterials provided with the distribution.
+ //
+ // * The name of the copyright holders may not be used to endorse or promote products
+ // derived from this software without specific prior written permission.
+ //
+ // This software is provided by the copyright holders and contributors as is and
+ // any express or implied warranties, including, but not limited to, the implied
+ // warranties of merchantability and fitness for a particular purpose are disclaimed.
+ // In no event shall the Intel Corporation or contributors be liable for any direct,
+ // indirect, incidental, special, exemplary, or consequential damages
+ // (including, but not limited to, procurement of substitute goods or services;
+ // loss of use, data, or profits; or business interruption) however caused
+ // and on any theory of liability, whether in contract, strict liability,
+ // or tort (including negligence or otherwise) arising in any way out of
+ // the use of this software, even if advised of the possibility of such damage.
+ //
+ //M*/
+
+ #include <iomanip>
+ #include "precomp.hpp"
+
+ using namespace cv;
+ using namespace ocl;
+
+ namespace cv
+ {
+ namespace ocl
+ {
+ ////////////////////////////////////OpenCL kernel strings//////////////////////////
+ extern const char *kmeans_kernel;
+ }
+ }
+
- vector<int> _centers(K);
++static void generateRandomCenter(const std::vector<Vec2f>& box, float* center, RNG& rng)
+ {
+ size_t j, dims = box.size();
+ float margin = 1.f/dims;
+ for( j = 0; j < dims; j++ )
+ center[j] = ((float)rng*(1.f+margin*2.f)-margin)*(box[j][1] - box[j][0]) + box[j][0];
+ }
+
+ // This class is copied from matrix.cpp in core module.
+ class KMeansPPDistanceComputer : public ParallelLoopBody
+ {
+ public:
+ KMeansPPDistanceComputer( float *_tdist2,
+ const float *_data,
+ const float *_dist,
+ int _dims,
+ size_t _step,
+ size_t _stepci )
+ : tdist2(_tdist2),
+ data(_data),
+ dist(_dist),
+ dims(_dims),
+ step(_step),
+ stepci(_stepci) { }
+
+ void operator()( const cv::Range& range ) const
+ {
+ const int begin = range.start;
+ const int end = range.end;
+
+ for ( int i = begin; i<end; i++ )
+ {
+ tdist2[i] = std::min(normL2Sqr_(data + step*i, data + stepci, dims), dist[i]);
+ }
+ }
+
+ private:
+ KMeansPPDistanceComputer& operator=(const KMeansPPDistanceComputer&); // to quiet MSVC
+
+ float *tdist2;
+ const float *data;
+ const float *dist;
+ const int dims;
+ const size_t step;
+ const size_t stepci;
+ };
+ /*
+ k-means center initialization using the following algorithm:
+ Arthur & Vassilvitskii (2007) k-means++: The Advantages of Careful Seeding
+ */
+ static void generateCentersPP(const Mat& _data, Mat& _out_centers,
+ int K, RNG& rng, int trials)
+ {
+ int i, j, k, dims = _data.cols, N = _data.rows;
+ const float* data = (float*)_data.data;
+ size_t step = _data.step/sizeof(data[0]);
- vector<float> _dist(N*3);
++ std::vector<int> _centers(K);
+ int* centers = &_centers[0];
- string kernelname = "distanceToCenters";
++ std::vector<float> _dist(N*3);
+ float* dist = &_dist[0], *tdist = dist + N, *tdist2 = tdist + N;
+ double sum0 = 0;
+
+ centers[0] = (unsigned)rng % N;
+
+ for( i = 0; i < N; i++ )
+ {
+ dist[i] = normL2Sqr_(data + step*i, data + step*centers[0], dims);
+ sum0 += dist[i];
+ }
+
+ for( k = 1; k < K; k++ )
+ {
+ double bestSum = DBL_MAX;
+ int bestCenter = -1;
+
+ for( j = 0; j < trials; j++ )
+ {
+ double p = (double)rng*sum0, s = 0;
+ for( i = 0; i < N-1; i++ )
+ if( (p -= dist[i]) <= 0 )
+ break;
+ int ci = i;
+
+ parallel_for_(Range(0, N),
+ KMeansPPDistanceComputer(tdist2, data, dist, dims, step, step*ci));
+ for( i = 0; i < N; i++ )
+ {
+ s += tdist2[i];
+ }
+
+ if( s < bestSum )
+ {
+ bestSum = s;
+ bestCenter = ci;
+ std::swap(tdist, tdist2);
+ }
+ }
+ centers[k] = bestCenter;
+ sum0 = bestSum;
+ std::swap(dist, tdist);
+ }
+
+ for( k = 0; k < K; k++ )
+ {
+ const float* src = data + step*centers[k];
+ float* dst = _out_centers.ptr<float>(k);
+ for( j = 0; j < dims; j++ )
+ dst[j] = src[j];
+ }
+ }
+
+ void cv::ocl::distanceToCenters(oclMat &dists, oclMat &labels, const oclMat &src, const oclMat ¢ers)
+ {
+ //if(src.clCxt -> impl -> double_support == 0 && src.type() == CV_64F)
+ //{
+ // CV_Error(CV_GpuNotSupported, "Selected device don't support double\r\n");
+ // return;
+ //}
+
+ Context *clCxt = src.clCxt;
+ int labels_step = (int)(labels.step/labels.elemSize());
- vector<pair<size_t, const void *> > args;
- args.push_back(make_pair(sizeof(cl_int), (void *)&labels_step));
- args.push_back(make_pair(sizeof(cl_int), (void *)¢ers.rows));
- args.push_back(make_pair(sizeof(cl_mem), (void *)&src.data));
- args.push_back(make_pair(sizeof(cl_mem), (void *)&labels.data));
- args.push_back(make_pair(sizeof(cl_int), (void *)¢ers.cols));
- args.push_back(make_pair(sizeof(cl_int), (void *)&src.rows));
- args.push_back(make_pair(sizeof(cl_mem), (void *)¢ers.data));
- args.push_back(make_pair(sizeof(cl_mem), (void*)&dists.data));
++ String kernelname = "distanceToCenters";
+ int threadNum = src.rows > 256 ? 256 : src.rows;
+ size_t localThreads[3] = {1, threadNum, 1};
+ size_t globalThreads[3] = {1, src.rows, 1};
+
- if( flags & CV_KMEANS_USE_INITIAL_LABELS )
++ std::vector<std::pair<size_t, const void *> > args;
++ args.push_back(std::make_pair(sizeof(cl_int), (void *)&labels_step));
++ args.push_back(std::make_pair(sizeof(cl_int), (void *)¢ers.rows));
++ args.push_back(std::make_pair(sizeof(cl_mem), (void *)&src.data));
++ args.push_back(std::make_pair(sizeof(cl_mem), (void *)&labels.data));
++ args.push_back(std::make_pair(sizeof(cl_int), (void *)¢ers.cols));
++ args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.rows));
++ args.push_back(std::make_pair(sizeof(cl_mem), (void *)¢ers.data));
++ args.push_back(std::make_pair(sizeof(cl_mem), (void*)&dists.data));
+
+ openCLExecuteKernel(clCxt, &kmeans_kernel, kernelname, globalThreads, localThreads, args, -1, -1, NULL);
+ }
+ ///////////////////////////////////k - means /////////////////////////////////////////////////////////
+ double cv::ocl::kmeans(const oclMat &_src, int K, oclMat &_bestLabels,
+ TermCriteria criteria, int attempts, int flags, oclMat &_centers)
+ {
+ const int SPP_TRIALS = 3;
+ bool isrow = _src.rows == 1 && _src.oclchannels() > 1;
+ int N = !isrow ? _src.rows : _src.cols;
+ int dims = (!isrow ? _src.cols : 1) * _src.oclchannels();
+ int type = _src.depth();
+
+ attempts = std::max(attempts, 1);
+ CV_Assert(type == CV_32F && K > 0 );
+ CV_Assert( N >= K );
+
+ Mat _labels;
- vector<int> counters(K);
- vector<Vec2f> _box(dims);
++ if( flags & KMEANS_USE_INITIAL_LABELS )
+ {
+ CV_Assert( (_bestLabels.cols == 1 || _bestLabels.rows == 1) &&
+ _bestLabels.cols * _bestLabels.rows == N &&
+ _bestLabels.type() == CV_32S );
+ _bestLabels.download(_labels);
+ }
+ else
+ {
+ if( !((_bestLabels.cols == 1 || _bestLabels.rows == 1) &&
+ _bestLabels.cols * _bestLabels.rows == N &&
+ _bestLabels.type() == CV_32S &&
+ _bestLabels.isContinuous()))
+ _bestLabels.create(N, 1, CV_32S);
+ _labels.create(_bestLabels.size(), _bestLabels.type());
+ }
+ int* labels = _labels.ptr<int>();
+
+ Mat data;
+ _src.download(data);
+ Mat centers(K, dims, type), old_centers(K, dims, type), temp(1, dims, type);
++ std::vector<int> counters(K);
++ std::vector<Vec2f> _box(dims);
+ Vec2f* box = &_box[0];
+ double best_compactness = DBL_MAX, compactness = 0;
+ RNG& rng = theRNG();
+ int a, iter, i, j, k;
+
+ if( criteria.type & TermCriteria::EPS )
+ criteria.epsilon = std::max(criteria.epsilon, 0.);
+ else
+ criteria.epsilon = FLT_EPSILON;
+ criteria.epsilon *= criteria.epsilon;
+
+ if( criteria.type & TermCriteria::COUNT )
+ criteria.maxCount = std::min(std::max(criteria.maxCount, 2), 100);
+ else
+ criteria.maxCount = 100;
+
+ if( K == 1 )
+ {
+ attempts = 1;
+ criteria.maxCount = 2;
+ }
+
+ const float* sample = data.ptr<float>();
+ for( j = 0; j < dims; j++ )
+ box[j] = Vec2f(sample[j], sample[j]);
+
+ for( i = 1; i < N; i++ )
+ {
+ sample = data.ptr<float>(i);
+ for( j = 0; j < dims; j++ )
+ {
+ float v = sample[j];
+ box[j][0] = std::min(box[j][0], v);
+ box[j][1] = std::max(box[j][1], v);
+ }
+ }
+
+ for( a = 0; a < attempts; a++ )
+ {
+ double max_center_shift = DBL_MAX;
+ for( iter = 0;; )
+ {
+ swap(centers, old_centers);
+
+ if( iter == 0 && (a > 0 || !(flags & KMEANS_USE_INITIAL_LABELS)) )
+ {
+ if( flags & KMEANS_PP_CENTERS )
+ generateCentersPP(data, centers, K, rng, SPP_TRIALS);
+ else
+ {
+ for( k = 0; k < K; k++ )
+ generateRandomCenter(_box, centers.ptr<float>(k), rng);
+ }
+ }
+ else
+ {
+ if( iter == 0 && a == 0 && (flags & KMEANS_USE_INITIAL_LABELS) )
+ {
+ for( i = 0; i < N; i++ )
+ CV_Assert( (unsigned)labels[i] < (unsigned)K );
+ }
+
+ // compute centers
+ centers = Scalar(0);
+ for( k = 0; k < K; k++ )
+ counters[k] = 0;
+
+ for( i = 0; i < N; i++ )
+ {
+ sample = data.ptr<float>(i);
+ k = labels[i];
+ float* center = centers.ptr<float>(k);
+ j=0;
+ #if CV_ENABLE_UNROLLED
+ for(; j <= dims - 4; j += 4 )
+ {
+ float t0 = center[j] + sample[j];
+ float t1 = center[j+1] + sample[j+1];
+
+ center[j] = t0;
+ center[j+1] = t1;
+
+ t0 = center[j+2] + sample[j+2];
+ t1 = center[j+3] + sample[j+3];
+
+ center[j+2] = t0;
+ center[j+3] = t1;
+ }
+ #endif
+ for( ; j < dims; j++ )
+ center[j] += sample[j];
+ counters[k]++;
+ }
+
+ if( iter > 0 )
+ max_center_shift = 0;
+
+ for( k = 0; k < K; k++ )
+ {
+ if( counters[k] != 0 )
+ continue;
+
+ // if some cluster appeared to be empty then:
+ // 1. find the biggest cluster
+ // 2. find the farthest from the center point in the biggest cluster
+ // 3. exclude the farthest point from the biggest cluster and form a new 1-point cluster.
+ int max_k = 0;
+ for( int k1 = 1; k1 < K; k1++ )
+ {
+ if( counters[max_k] < counters[k1] )
+ max_k = k1;
+ }
+
+ double max_dist = 0;
+ int farthest_i = -1;
+ float* new_center = centers.ptr<float>(k);
+ float* old_center = centers.ptr<float>(max_k);
+ float* _old_center = temp.ptr<float>(); // normalized
+ float scale = 1.f/counters[max_k];
+ for( j = 0; j < dims; j++ )
+ _old_center[j] = old_center[j]*scale;
+
+ for( i = 0; i < N; i++ )
+ {
+ if( labels[i] != max_k )
+ continue;
+ sample = data.ptr<float>(i);
+ double dist = normL2Sqr_(sample, _old_center, dims);
+
+ if( max_dist <= dist )
+ {
+ max_dist = dist;
+ farthest_i = i;
+ }
+ }
+
+ counters[max_k]--;
+ counters[k]++;
+ labels[farthest_i] = k;
+ sample = data.ptr<float>(farthest_i);
+
+ for( j = 0; j < dims; j++ )
+ {
+ old_center[j] -= sample[j];
+ new_center[j] += sample[j];
+ }
+ }
+
+ for( k = 0; k < K; k++ )
+ {
+ float* center = centers.ptr<float>(k);
+ CV_Assert( counters[k] != 0 );
+
+ float scale = 1.f/counters[k];
+ for( j = 0; j < dims; j++ )
+ center[j] *= scale;
+
+ if( iter > 0 )
+ {
+ double dist = 0;
+ const float* old_center = old_centers.ptr<float>(k);
+ for( j = 0; j < dims; j++ )
+ {
+ double t = center[j] - old_center[j];
+ dist += t*t;
+ }
+ max_center_shift = std::max(max_center_shift, dist);
+ }
+ }
+ }
+
+ if( ++iter == MAX(criteria.maxCount, 2) || max_center_shift <= criteria.epsilon )
+ break;
+
+ // assign labels
+ oclMat _dists(1, N, CV_64F);
+
+ _bestLabels.upload(_labels);
+ _centers.upload(centers);
+ distanceToCenters(_dists, _bestLabels, _src, _centers);
+
+ Mat dists;
+ _dists.download(dists);
+ _bestLabels.download(_labels);
+
+ double* dist = dists.ptr<double>(0);
+ compactness = 0;
+ for( i = 0; i < N; i++ )
+ {
+ compactness += dist[i];
+ }
+ }
+
+ if( compactness < best_compactness )
+ {
+ best_compactness = compactness;
+ }
+ }
+
+ return best_compactness;
+ }
+
#endif
}
- std::string workdir;
int main(int argc, char **argv)
{
- TS::ptr()->init("ocl");
+ TS::ptr()->init(".");
InitGoogleTest(&argc, argv);
const char *keys =
- "{ h | help | false | print help message }"
- "{ t | type | gpu | set device type:cpu or gpu}"
- "{ p | platform | 0 | set platform id }"
- "{ d | device | 0 | set device id }";
+ "{ h | false | print help message }"
- "{ w | ../../../samples/c/| set working directory i.e. -w=C:\\}"
+ "{ t | gpu | set device type:i.e. -t=cpu or gpu}"
+ "{ p | 0 | set platform id i.e. -p=0}"
+ "{ d | 0 | set device id i.e. -d=0}";
CommandLineParser cmd(argc, argv, keys);
- if (cmd.get<bool>("help"))
+ if (cmd.get<string>("h")=="true")
{
cout << "Avaible options besides goole test option:" << endl;
- cmd.printParams();
+ cmd.printMessage();
return 0;
}
- workdir = cmd.get<string>("w");
- string type = cmd.get<string>("type");
- unsigned int pid = cmd.get<unsigned int>("platform");
- int device = cmd.get<int>("device");
+ string type = cmd.get<string>("t");
+ unsigned int pid = cmd.get<unsigned int>("p");
+ int device = cmd.get<int>("d");
print_info();
int flag = CVCL_DEVICE_TYPE_GPU;
--- /dev/null
- TermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 100, 0),
+ /*M///////////////////////////////////////////////////////////////////////////////////////
+ //
+ // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+ //
+ // By downloading, copying, installing or using the software you agree to this license.
+ // If you do not agree to this license, do not download, install,
+ // copy or use the software.
+ //
+ //
+ // License Agreement
+ // For Open Source Computer Vision Library
+ //
+ // Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
+ // Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
+ // Third party copyrights are property of their respective owners.
+ //
+ // @Authors
+ // Erping Pang, pang_er_ping@163.com
+ // Xiaopeng Fu, fuxiaopeng2222@163.com
+ //
+ // Redistribution and use in source and binary forms, with or without modification,
+ // are permitted provided that the following conditions are met:
+ //
+ // * Redistribution's of source code must retain the above copyright notice,
+ // this list of conditions and the following disclaimer.
+ //
+ // * Redistribution's in binary form must reproduce the above copyright notice,
+ // this list of conditions and the following disclaimer in the documentation
+ // and/or other oclMaterials provided with the distribution.
+ //
+ // * The name of the copyright holders may not be used to endorse or promote products
+ // derived from this software without specific prior written permission.
+ //
+ // This software is provided by the copyright holders and contributors "as is" and
+ // any express or implied warranties, including, but not limited to, the implied
+ // warranties of merchantability and fitness for a particular purpose are disclaimed.
+ // In no event shall the Intel Corporation or contributors be liable for any direct,
+ // indirect, incidental, special, exemplary, or consequential damages
+ // (including, but not limited to, procurement of substitute goods or services;
+ // loss of use, data, or profits; or business interruption) however caused
+ // and on any theory of liability, whether in contract, strict liability,
+ // or tort (including negligence or otherwise) arising in any way out of
+ // the use of this software, even if advised of the possibility of such damage.
+ //
+ //M*/
+
+ #include "precomp.hpp"
+
+ #ifdef HAVE_OPENCL
+
+ using namespace cvtest;
+ using namespace testing;
+ using namespace std;
+ using namespace cv;
+
+ #define OCL_KMEANS_USE_INITIAL_LABELS 1
+ #define OCL_KMEANS_PP_CENTERS 2
+
+ PARAM_TEST_CASE(Kmeans, int, int, int)
+ {
+ int type;
+ int K;
+ int flags;
+ cv::Mat src ;
+ ocl::oclMat d_src, d_dists;
+
+ Mat labels, centers;
+ ocl::oclMat d_labels, d_centers;
+ cv::RNG rng ;
+ virtual void SetUp(){
+ K = GET_PARAM(0);
+ type = GET_PARAM(1);
+ flags = GET_PARAM(2);
+ rng = TS::ptr()->get_rng();
+
+ // MWIDTH=256, MHEIGHT=256. defined in utility.hpp
+ cv::Size size = cv::Size(MWIDTH, MHEIGHT);
+ src.create(size, type);
+ int row_idx = 0;
+ const int max_neighbour = MHEIGHT / K - 1;
+ CV_Assert(K <= MWIDTH);
+ for(int i = 0; i < K; i++ )
+ {
+ Mat center_row_header = src.row(row_idx);
+ center_row_header.setTo(0);
+ int nchannel = center_row_header.channels();
+ for(int j = 0; j < nchannel; j++)
+ center_row_header.at<float>(0, i*nchannel+j) = 50000.0;
+
+ for(int j = 0; (j < max_neighbour) ||
+ (i == K-1 && j < max_neighbour + MHEIGHT%K); j ++)
+ {
+ Mat cur_row_header = src.row(row_idx + 1 + j);
+ center_row_header.copyTo(cur_row_header);
+ Mat tmpmat = randomMat(rng, cur_row_header.size(), cur_row_header.type(), -200, 200, false);
+ cur_row_header += tmpmat;
+ }
+ row_idx += 1 + max_neighbour;
+ }
+ }
+ };
+ TEST_P(Kmeans, Mat){
+
+ if(flags & KMEANS_USE_INITIAL_LABELS)
+ {
+ // inital a given labels
+ labels.create(src.rows, 1, CV_32S);
+ int *label = labels.ptr<int>();
+ for(int i = 0; i < src.rows; i++)
+ label[i] = rng.uniform(0, K);
+ d_labels.upload(labels);
+ }
+ d_src.upload(src);
+
+ for(int j = 0; j < LOOP_TIMES; j++)
+ {
+ kmeans(src, K, labels,
- TermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 100, 0),
++ TermCriteria( TermCriteria::EPS + TermCriteria::MAX_ITER, 100, 0),
+ 1, flags, centers);
+
+ ocl::kmeans(d_src, K, d_labels,
++ TermCriteria( TermCriteria::EPS + TermCriteria::MAX_ITER, 100, 0),
+ 1, flags, d_centers);
+
+ Mat dd_labels(d_labels);
+ Mat dd_centers(d_centers);
+ if(flags & KMEANS_USE_INITIAL_LABELS)
+ {
+ EXPECT_MAT_NEAR(labels, dd_labels, 0);
+ EXPECT_MAT_NEAR(centers, dd_centers, 1e-3);
+ }
+ else
+ {
+ int row_idx = 0;
+ for(int i = 0; i < K; i++)
+ {
+ // verify lables with ground truth resutls
+ int label = labels.at<int>(row_idx);
+ int header_label = dd_labels.at<int>(row_idx);
+ for(int j = 0; (j < MHEIGHT/K)||(i == K-1 && j < MHEIGHT/K+MHEIGHT%K); j++)
+ {
+ ASSERT_NEAR(labels.at<int>(row_idx+j), label, 0);
+ ASSERT_NEAR(dd_labels.at<int>(row_idx+j), header_label, 0);
+ }
+
+ // verify centers
+ float *center = centers.ptr<float>(label);
+ float *header_center = dd_centers.ptr<float>(header_label);
+ for(int t = 0; t < centers.cols; t++)
+ ASSERT_NEAR(center[t], header_center[t], 1e-3);
+
+ row_idx += MHEIGHT/K;
+ }
+ }
+ }
+ }
+ INSTANTIATE_TEST_CASE_P(OCL_ML, Kmeans, Combine(
+ Values(3, 5, 8),
+ Values(CV_32FC1, CV_32FC2, CV_32FC4),
+ Values(OCL_KMEANS_USE_INITIAL_LABELS/*, OCL_KMEANS_PP_CENTERS*/)));
+
+ #endif
set(the_description "Super Resolution")
ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4127 -Wundef)
-ocv_define_module(superres opencv_imgproc opencv_video OPTIONAL opencv_gpu opencv_highgui opencv_ocl)
+ocv_define_module(superres opencv_imgproc opencv_video
- OPTIONAL opencv_highgui
++ OPTIONAL opencv_highgui opencv_ocl
+ opencv_gpuarithm opencv_gpufilters opencv_gpuwarping opencv_gpuimgproc opencv_gpuoptflow opencv_gpucodec)
--- /dev/null
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+// By downloading, copying, installing or using the software you agree to this license.
+// If you do not agree to this license, do not download, install,
+// copy or use the software.
+//
+//
+// License Agreement
+// For Open Source Computer Vision Library
+//
+// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
+// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistribution's of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// * Redistribution's in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// * The name of the copyright holders may not be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#ifndef __OPENCV_SUPERRES_HPP__
+#define __OPENCV_SUPERRES_HPP__
+
+#include "opencv2/core.hpp"
+
+namespace cv
+{
+ namespace superres
+ {
+ CV_EXPORTS bool initModule_superres();
+
+ class CV_EXPORTS FrameSource
+ {
+ public:
+ virtual ~FrameSource();
+
+ virtual void nextFrame(OutputArray frame) = 0;
+ virtual void reset() = 0;
+ };
+
+ CV_EXPORTS Ptr<FrameSource> createFrameSource_Empty();
+
+ CV_EXPORTS Ptr<FrameSource> createFrameSource_Video(const String& fileName);
+ CV_EXPORTS Ptr<FrameSource> createFrameSource_Video_GPU(const String& fileName);
+
+ CV_EXPORTS Ptr<FrameSource> createFrameSource_Camera(int deviceId = 0);
+
+ class CV_EXPORTS SuperResolution : public cv::Algorithm, public FrameSource
+ {
+ public:
+ void setInput(const Ptr<FrameSource>& frameSource);
+
+ void nextFrame(OutputArray frame);
+ void reset();
+
+ virtual void collectGarbage();
+
+ protected:
+ SuperResolution();
+
+ virtual void initImpl(Ptr<FrameSource>& frameSource) = 0;
+ virtual void processImpl(Ptr<FrameSource>& frameSource, OutputArray output) = 0;
+
+ private:
+ Ptr<FrameSource> frameSource_;
+ bool firstCall_;
+ };
+
+ // S. Farsiu , D. Robinson, M. Elad, P. Milanfar. Fast and robust multiframe super resolution.
+ // Dennis Mitzel, Thomas Pock, Thomas Schoenemann, Daniel Cremers. Video Super Resolution using Duality Based TV-L1 Optical Flow.
+ CV_EXPORTS Ptr<SuperResolution> createSuperResolution_BTVL1();
+ CV_EXPORTS Ptr<SuperResolution> createSuperResolution_BTVL1_GPU();
++ CV_EXPORTS Ptr<SuperResolution> createSuperResolution_BTVL1_OCL();
+ }
+}
+
+#endif // __OPENCV_SUPERRES_HPP__
--- /dev/null
-#include "opencv2/ocl/ocl.hpp"
+ /*M///////////////////////////////////////////////////////////////////////////////////////
+ //
+ // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+ //
+ // By downloading, copying, installing or using the software you agree to this license.
+ // If you do not agree to this license, do not download, install,
+ // copy or use the software.
+ //
+ //
+ // License Agreement
+ // For Open Source Computer Vision Library
+ //
+ // Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
+ // Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
+ // Third party copyrights are property of their respective owners.
+ //
+ // Redistribution and use in source and binary forms, with or without modification,
+ // are permitted provided that the following conditions are met:
+ //
+ // * Redistribution's of source code must retain the above copyright notice,
+ // this list of conditions and the following disclaimer.
+ //
+ // * Redistribution's in binary form must reproduce the above copyright notice,
+ // this list of conditions and the following disclaimer in the documentation
+ // and/or other materials provided with the distribution.
+ //
+ // * The name of the copyright holders may not be used to endorse or promote products
+ // derived from this software without specific prior written permission.
+ //
+ // This software is provided by the copyright holders and contributors "as is" and
+ // any express or implied warranties, including, but not limited to, the implied
+ // warranties of merchantability and fitness for a particular purpose are disclaimed.
+ // In no event shall the Intel Corporation or contributors be liable for any direct,
+ // indirect, incidental, special, exemplary, or consequential damages
+ // (including, but not limited to, procurement of substitute goods or services;
+ // loss of use, data, or profits; or business interruption) however caused
+ // and on any theory of liability, whether in contract, strict liability,
+ // or tort (including negligence or otherwise) arising in any way out of
+ // the use of this software, even if advised of the possibility of such damage.
+ //
+ //M*/
+
+ #include "perf_precomp.hpp"
+
+ #ifdef HAVE_OPENCL
+
++#include "opencv2/ocl.hpp"
+ using namespace std;
++using namespace std::tr1;
+ using namespace testing;
+ using namespace perf;
+ using namespace cv;
+ using namespace cv::superres;
+
+ namespace
+ {
+ class OneFrameSource_OCL : public FrameSource
+ {
+ public:
+ explicit OneFrameSource_OCL(const ocl::oclMat& frame) : frame_(frame) {}
+
+ void nextFrame(OutputArray frame)
+ {
+ ocl::getOclMatRef(frame) = frame_;
+ }
+ void reset()
+ {
+ }
+
+ private:
+ ocl::oclMat frame_;
+ };
+
+
+ class ZeroOpticalFlowOCL : public DenseOpticalFlowExt
+ {
+ public:
+ void calc(InputArray frame0, InputArray, OutputArray flow1, OutputArray flow2)
+ {
+ ocl::oclMat& frame0_ = ocl::getOclMatRef(frame0);
+ ocl::oclMat& flow1_ = ocl::getOclMatRef(flow1);
+ ocl::oclMat& flow2_ = ocl::getOclMatRef(flow2);
+
+ cv::Size size = frame0_.size();
+
+ if(!flow2.needed())
+ {
+ flow1_.create(size, CV_32FC2);
+ flow1_.setTo(Scalar::all(0));
+ }
+ else
+ {
+ flow1_.create(size, CV_32FC1);
+ flow2_.create(size, CV_32FC1);
+
+ flow1_.setTo(Scalar::all(0));
+ flow2_.setTo(Scalar::all(0));
+ }
+ }
+
+ void collectGarbage()
+ {
+ }
+ };
+ }
+
+ PERF_TEST_P(Size_MatType, SuperResolution_BTVL1_OCL,
+ Combine(Values(szSmall64, szSmall128),
+ Values(MatType(CV_8UC1), MatType(CV_8UC3))))
+ {
+ std::vector<cv::ocl::Info>info;
+ cv::ocl::getDevice(info);
+
+ declare.time(5 * 60);
+
+ const Size size = get<0>(GetParam());
+ const int type = get<1>(GetParam());
+
+ Mat frame(size, type);
+ declare.in(frame, WARMUP_RNG);
+
+ ocl::oclMat frame_ocl;
+ frame_ocl.upload(frame);
+
+
+ const int scale = 2;
+ const int iterations = 50;
+ const int temporalAreaRadius = 1;
+ Ptr<DenseOpticalFlowExt> opticalFlowOcl(new ZeroOpticalFlowOCL);
+
+ Ptr<SuperResolution> superRes_ocl = createSuperResolution_BTVL1_OCL();
+
+ superRes_ocl->set("scale", scale);
+ superRes_ocl->set("iterations", iterations);
+ superRes_ocl->set("temporalAreaRadius", temporalAreaRadius);
+ superRes_ocl->set("opticalFlow", opticalFlowOcl);
+
+ superRes_ocl->setInput(new OneFrameSource_OCL(frame_ocl));
+
+ ocl::oclMat dst_ocl;
+ superRes_ocl->nextFrame(dst_ocl);
+
+ TEST_CYCLE_N(10) superRes_ocl->nextFrame(dst_ocl);
+ frame_ocl.release();
+ CPU_SANITY_CHECK(dst_ocl);
+ }
+ #endif
--- /dev/null
- CV_Error(CV_StsNotImplemented, "The called functionality is disabled for current build or platform");
+ /*M///////////////////////////////////////////////////////////////////////////////////////
+ //
+ // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+ //
+ // By downloading, copying, installing or using the software you agree to this license.
+ // If you do not agree to this license, do not download, install,
+ // copy or use the software.
+ //
+ //
+ // License Agreement
+ // For Open Source Computer Vision Library
+ //
+ // Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
+ // Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
+ // Third party copyrights are property of their respective owners.
+ //
+ // @Authors
+ // Jin Ma, jin@multicorewareinc.com
+ // Redistribution and use in source and binary forms, with or without modification,
+ // are permitted provided that the following conditions are met:
+ //
+ // * Redistribution's of source code must retain the above copyright notice,
+ // this list of conditions and the following disclaimer.
+ //
+ // * Redistribution's in binary form must reproduce the above copyright notice,
+ // this list of conditions and the following disclaimer in the documentation
+ // and/or other materials provided with the distribution.
+ //
+ // * The name of the copyright holders may not be used to endorse or promote products
+ // derived from this software without specific prior written permission.
+ //
+ // This software is provided by the copyright holders and contributors "as is" and
+ // any express or implied warranties, including, but not limited to, the implied
+ // warranties of merchantability and fitness for a particular purpose are disclaimed.
+ // In no event shall the Intel Corporation or contributors be liable for any direct,
+ // indirect, incidental, special, exemplary, or consequential damages
+ // (including, but not limited to, procurement of substitute goods or services;
+ // loss of use, data, or profits; or business interruption) however caused
+ // and on any theory of liability, whether in contract, strict liability,
+ // or tort (including negligence or otherwise) arising in any way out of
+ // the use of this software, even if advised of the possibility of such damage.
+ //
+ //M*/
+
+ // S. Farsiu , D. Robinson, M. Elad, P. Milanfar. Fast and robust multiframe super resolution.
+ // Dennis Mitzel, Thomas Pock, Thomas Schoenemann, Daniel Cremers. Video Super Resolution using Duality Based TV-L1 Optical Flow.
+
+ #include "precomp.hpp"
+
+ #if !defined(HAVE_OPENCL) || !defined(HAVE_OPENCV_OCL)
+
+ cv::Ptr<cv::superres::SuperResolution> cv::superres::createSuperResolution_BTVL1_OCL()
+ {
-#endif
++ CV_Error(cv::Error::StsNotImplemented, "The called functionality is disabled for current build or platform");
+ return Ptr<SuperResolution>();
+ }
+
+ #else
+
+ using namespace std;
+ using namespace cv;
+ using namespace cv::ocl;
+ using namespace cv::superres;
+ using namespace cv::superres::detail;
+
+ namespace cv
+ {
+ namespace ocl
+ {
+ extern const char* superres_btvl1;
+
+ float* btvWeights_ = NULL;
+ size_t btvWeights_size = 0;
+ }
+ }
+
+ namespace btv_l1_device_ocl
+ {
+ void buildMotionMaps(const oclMat& forwardMotionX, const oclMat& forwardMotionY,
+ const oclMat& backwardMotionX, const oclMat& bacwardMotionY,
+ oclMat& forwardMapX, oclMat& forwardMapY,
+ oclMat& backwardMapX, oclMat& backwardMapY);
+
+ void upscale(const oclMat& src, oclMat& dst, int scale);
+
+ float diffSign(float a, float b);
+
+ Point3f diffSign(Point3f a, Point3f b);
+
+ void diffSign(const oclMat& src1, const oclMat& src2, oclMat& dst);
+
+ void calcBtvRegularization(const oclMat& src, oclMat& dst, int ksize);
+ }
+
+ void btv_l1_device_ocl::buildMotionMaps(const oclMat& forwardMotionX, const oclMat& forwardMotionY,
+ const oclMat& backwardMotionX, const oclMat& backwardMotionY,
+ oclMat& forwardMapX, oclMat& forwardMapY,
+ oclMat& backwardMapX, oclMat& backwardMapY)
+ {
+ Context* clCxt = Context::getContext();
+
+ size_t local_thread[] = {32, 8, 1};
+ size_t global_thread[] = {forwardMapX.cols, forwardMapX.rows, 1};
+
+ int forwardMotionX_step = (int)(forwardMotionX.step/forwardMotionX.elemSize());
+ int forwardMotionY_step = (int)(forwardMotionY.step/forwardMotionY.elemSize());
+ int backwardMotionX_step = (int)(backwardMotionX.step/backwardMotionX.elemSize());
+ int backwardMotionY_step = (int)(backwardMotionY.step/backwardMotionY.elemSize());
+ int forwardMapX_step = (int)(forwardMapX.step/forwardMapX.elemSize());
+ int forwardMapY_step = (int)(forwardMapY.step/forwardMapY.elemSize());
+ int backwardMapX_step = (int)(backwardMapX.step/backwardMapX.elemSize());
+ int backwardMapY_step = (int)(backwardMapY.step/backwardMapY.elemSize());
+
+ String kernel_name = "buildMotionMapsKernel";
+ vector< pair<size_t, const void*> > args;
+
+ args.push_back(make_pair(sizeof(cl_mem), (void*)&forwardMotionX.data));
+ args.push_back(make_pair(sizeof(cl_mem), (void*)&forwardMotionY.data));
+ args.push_back(make_pair(sizeof(cl_mem), (void*)&backwardMotionX.data));
+ args.push_back(make_pair(sizeof(cl_mem), (void*)&backwardMotionY.data));
+ args.push_back(make_pair(sizeof(cl_mem), (void*)&forwardMapX.data));
+ args.push_back(make_pair(sizeof(cl_mem), (void*)&forwardMapY.data));
+ args.push_back(make_pair(sizeof(cl_mem), (void*)&backwardMapX.data));
+ args.push_back(make_pair(sizeof(cl_mem), (void*)&backwardMapY.data));
+
+ args.push_back(make_pair(sizeof(cl_int), (void*)&forwardMotionX.rows));
+ args.push_back(make_pair(sizeof(cl_int), (void*)&forwardMotionY.cols));
+
+ args.push_back(make_pair(sizeof(cl_int), (void*)&forwardMotionX_step));
+ args.push_back(make_pair(sizeof(cl_int), (void*)&forwardMotionY_step));
+ args.push_back(make_pair(sizeof(cl_int), (void*)&backwardMotionX_step));
+ args.push_back(make_pair(sizeof(cl_int), (void*)&backwardMotionY_step));
+ args.push_back(make_pair(sizeof(cl_int), (void*)&forwardMapX_step));
+ args.push_back(make_pair(sizeof(cl_int), (void*)&forwardMapY_step));
+ args.push_back(make_pair(sizeof(cl_int), (void*)&backwardMapX_step));
+ args.push_back(make_pair(sizeof(cl_int), (void*)&backwardMapY_step));
+
+ openCLExecuteKernel(clCxt, &superres_btvl1, kernel_name, global_thread, local_thread, args, -1, -1);
+ }
+
+ void btv_l1_device_ocl::upscale(const oclMat& src, oclMat& dst, int scale)
+ {
+ Context* clCxt = Context::getContext();
+
+ size_t local_thread[] = {32, 8, 1};
+ size_t global_thread[] = {src.cols, src.rows, 1};
+
+ int src_step = (int)(src.step/src.elemSize());
+ int dst_step = (int)(dst.step/dst.elemSize());
+
+ String kernel_name = "upscaleKernel";
+ vector< pair<size_t, const void*> > args;
+
+ int cn = src.oclchannels();
+
+ args.push_back(make_pair(sizeof(cl_mem), (void*)&src.data));
+ args.push_back(make_pair(sizeof(cl_mem), (void*)&dst.data));
+ args.push_back(make_pair(sizeof(cl_int), (void*)&src_step));
+ args.push_back(make_pair(sizeof(cl_int), (void*)&dst_step));
+ args.push_back(make_pair(sizeof(cl_int), (void*)&src.rows));
+ args.push_back(make_pair(sizeof(cl_int), (void*)&src.cols));
+ args.push_back(make_pair(sizeof(cl_int), (void*)&scale));
+ args.push_back(make_pair(sizeof(cl_int), (void*)&cn));
+
+ openCLExecuteKernel(clCxt, &superres_btvl1, kernel_name, global_thread, local_thread, args, -1, -1);
+
+ }
+
+ float btv_l1_device_ocl::diffSign(float a, float b)
+ {
+ return a > b ? 1.0f : a < b ? -1.0f : 0.0f;
+ }
+
+ Point3f btv_l1_device_ocl::diffSign(Point3f a, Point3f b)
+ {
+ return Point3f(
+ a.x > b.x ? 1.0f : a.x < b.x ? -1.0f : 0.0f,
+ a.y > b.y ? 1.0f : a.y < b.y ? -1.0f : 0.0f,
+ a.z > b.z ? 1.0f : a.z < b.z ? -1.0f : 0.0f
+ );
+ }
+
+ void btv_l1_device_ocl::diffSign(const oclMat& src1, const oclMat& src2, oclMat& dst)
+ {
+ Context* clCxt = Context::getContext();
+
+ oclMat src1_ = src1.reshape(1);
+ oclMat src2_ = src2.reshape(1);
+ oclMat dst_ = dst.reshape(1);
+
+ int src1_step = (int)(src1_.step/src1_.elemSize());
+ int src2_step = (int)(src2_.step/src2_.elemSize());
+ int dst_step = (int)(dst_.step/dst_.elemSize());
+
+ size_t local_thread[] = {32, 8, 1};
+ size_t global_thread[] = {src1_.cols, src1_.rows, 1};
+
+ String kernel_name = "diffSignKernel";
+ vector< pair<size_t, const void*> > args;
+
+ args.push_back(make_pair(sizeof(cl_mem), (void*)&src1_.data));
+ args.push_back(make_pair(sizeof(cl_mem), (void*)&src2_.data));
+ args.push_back(make_pair(sizeof(cl_mem), (void*)&dst_.data));
+
+ args.push_back(make_pair(sizeof(cl_int), (void*)&src1_.rows));
+ args.push_back(make_pair(sizeof(cl_int), (void*)&src1_.cols));
+ args.push_back(make_pair(sizeof(cl_int), (void*)&dst_step));
+ args.push_back(make_pair(sizeof(cl_int), (void*)&src1_step));
+ args.push_back(make_pair(sizeof(cl_int), (void*)&src2_step));
+
+ openCLExecuteKernel(clCxt, &superres_btvl1, kernel_name, global_thread, local_thread, args, -1, -1);
+ }
+
+ void btv_l1_device_ocl::calcBtvRegularization(const oclMat& src, oclMat& dst, int ksize)
+ {
+ Context* clCxt = Context::getContext();
+
+ oclMat src_ = src.reshape(1);
+ oclMat dst_ = dst.reshape(1);
+
+ size_t local_thread[] = {32, 8, 1};
+ size_t global_thread[] = {src.cols, src.rows, 1};
+
+ int src_step = (int)(src_.step/src_.elemSize());
+ int dst_step = (int)(dst_.step/dst_.elemSize());
+
+ String kernel_name = "calcBtvRegularizationKernel";
+ vector< pair<size_t, const void*> > args;
+
+ int cn = src.oclchannels();
+
+ cl_mem c_btvRegWeights;
+ size_t count = btvWeights_size * sizeof(float);
+ c_btvRegWeights = openCLCreateBuffer(clCxt, CL_MEM_READ_ONLY, count);
+ int cl_safe_check = clEnqueueWriteBuffer((cl_command_queue)clCxt->oclCommandQueue(), c_btvRegWeights, 1, 0, count, btvWeights_, 0, NULL, NULL);
+ CV_Assert(cl_safe_check == CL_SUCCESS);
+
+ args.push_back(make_pair(sizeof(cl_mem), (void*)&src_.data));
+ args.push_back(make_pair(sizeof(cl_mem), (void*)&dst_.data));
+ args.push_back(make_pair(sizeof(cl_int), (void*)&src_step));
+ args.push_back(make_pair(sizeof(cl_int), (void*)&dst_step));
+ args.push_back(make_pair(sizeof(cl_int), (void*)&src.rows));
+ args.push_back(make_pair(sizeof(cl_int), (void*)&src.cols));
+ args.push_back(make_pair(sizeof(cl_int), (void*)&ksize));
+ args.push_back(make_pair(sizeof(cl_int), (void*)&cn));
+ args.push_back(make_pair(sizeof(cl_mem), (void*)&c_btvRegWeights));
+
+ openCLExecuteKernel(clCxt, &superres_btvl1, kernel_name, global_thread, local_thread, args, -1, -1);
+ cl_safe_check = clReleaseMemObject(c_btvRegWeights);
+ CV_Assert(cl_safe_check == CL_SUCCESS);
+ }
+
+ namespace
+ {
+ void calcRelativeMotions(const vector<pair<oclMat, oclMat> >& forwardMotions, const vector<pair<oclMat, oclMat> >& backwardMotions,
+ vector<pair<oclMat, oclMat> >& relForwardMotions, vector<pair<oclMat, oclMat> >& relBackwardMotions,
+ int baseIdx, Size size)
+ {
+ const int count = static_cast<int>(forwardMotions.size());
+
+ relForwardMotions.resize(count);
+ relForwardMotions[baseIdx].first.create(size, CV_32FC1);
+ relForwardMotions[baseIdx].first.setTo(Scalar::all(0));
+ relForwardMotions[baseIdx].second.create(size, CV_32FC1);
+ relForwardMotions[baseIdx].second.setTo(Scalar::all(0));
+
+ relBackwardMotions.resize(count);
+ relBackwardMotions[baseIdx].first.create(size, CV_32FC1);
+ relBackwardMotions[baseIdx].first.setTo(Scalar::all(0));
+ relBackwardMotions[baseIdx].second.create(size, CV_32FC1);
+ relBackwardMotions[baseIdx].second.setTo(Scalar::all(0));
+
+ for (int i = baseIdx - 1; i >= 0; --i)
+ {
+ ocl::add(relForwardMotions[i + 1].first, forwardMotions[i].first, relForwardMotions[i].first);
+ ocl::add(relForwardMotions[i + 1].second, forwardMotions[i].second, relForwardMotions[i].second);
+
+ ocl::add(relBackwardMotions[i + 1].first, backwardMotions[i + 1].first, relBackwardMotions[i].first);
+ ocl::add(relBackwardMotions[i + 1].second, backwardMotions[i + 1].second, relBackwardMotions[i].second);
+ }
+
+ for (int i = baseIdx + 1; i < count; ++i)
+ {
+ ocl::add(relForwardMotions[i - 1].first, backwardMotions[i].first, relForwardMotions[i].first);
+ ocl::add(relForwardMotions[i - 1].second, backwardMotions[i].second, relForwardMotions[i].second);
+
+ ocl::add(relBackwardMotions[i - 1].first, forwardMotions[i - 1].first, relBackwardMotions[i].first);
+ ocl::add(relBackwardMotions[i - 1].second, forwardMotions[i - 1].second, relBackwardMotions[i].second);
+ }
+ }
+
+ void upscaleMotions(const vector<pair<oclMat, oclMat> >& lowResMotions, vector<pair<oclMat, oclMat> >& highResMotions, int scale)
+ {
+ highResMotions.resize(lowResMotions.size());
+
+ for (size_t i = 0; i < lowResMotions.size(); ++i)
+ {
+ ocl::resize(lowResMotions[i].first, highResMotions[i].first, Size(), scale, scale, INTER_LINEAR);
+ ocl::resize(lowResMotions[i].second, highResMotions[i].second, Size(), scale, scale, INTER_LINEAR);
+
+ ocl::multiply(scale, highResMotions[i].first, highResMotions[i].first);
+ ocl::multiply(scale, highResMotions[i].second, highResMotions[i].second);
+ }
+ }
+
+ void buildMotionMaps(const pair<oclMat, oclMat>& forwardMotion, const pair<oclMat, oclMat>& backwardMotion,
+ pair<oclMat, oclMat>& forwardMap, pair<oclMat, oclMat>& backwardMap)
+ {
+ forwardMap.first.create(forwardMotion.first.size(), CV_32FC1);
+ forwardMap.second.create(forwardMotion.first.size(), CV_32FC1);
+
+ backwardMap.first.create(forwardMotion.first.size(), CV_32FC1);
+ backwardMap.second.create(forwardMotion.first.size(), CV_32FC1);
+
+ btv_l1_device_ocl::buildMotionMaps(forwardMotion.first, forwardMotion.second,
+ backwardMotion.first, backwardMotion.second,
+ forwardMap.first, forwardMap.second,
+ backwardMap.first, backwardMap.second);
+ }
+
+ void upscale(const oclMat& src, oclMat& dst, int scale)
+ {
+ CV_Assert( src.channels() == 1 || src.channels() == 3 || src.channels() == 4 );
+
+ dst.create(src.rows * scale, src.cols * scale, src.type());
+ dst.setTo(Scalar::all(0));
+
+ btv_l1_device_ocl::upscale(src, dst, scale);
+ }
+
+ void diffSign(const oclMat& src1, const oclMat& src2, oclMat& dst)
+ {
+ dst.create(src1.size(), src1.type());
+
+ btv_l1_device_ocl::diffSign(src1, src2, dst);
+ }
+
+ void calcBtvWeights(int btvKernelSize, double alpha, vector<float>& btvWeights)
+ {
+ const size_t size = btvKernelSize * btvKernelSize;
+
+ btvWeights.resize(size);
+
+ const int ksize = (btvKernelSize - 1) / 2;
+ const float alpha_f = static_cast<float>(alpha);
+
+ for (int m = 0, ind = 0; m <= ksize; ++m)
+ {
+ for (int l = ksize; l + m >= 0; --l, ++ind)
+ btvWeights[ind] = pow(alpha_f, std::abs(m) + std::abs(l));
+ }
+
+ btvWeights_ = &btvWeights[0];
+ btvWeights_size = size;
+ }
+
+ void calcBtvRegularization(const oclMat& src, oclMat& dst, int btvKernelSize)
+ {
+ dst.create(src.size(), src.type());
+ dst.setTo(Scalar::all(0));
+
+ const int ksize = (btvKernelSize - 1) / 2;
+
+ btv_l1_device_ocl::calcBtvRegularization(src, dst, ksize);
+ }
+
+ class BTVL1_OCL_Base
+ {
+ public:
+ BTVL1_OCL_Base();
+
+ void process(const vector<oclMat>& src, oclMat& dst,
+ const vector<pair<oclMat, oclMat> >& forwardMotions, const vector<pair<oclMat, oclMat> >& backwardMotions,
+ int baseIdx);
+
+ void collectGarbage();
+
+ protected:
+ int scale_;
+ int iterations_;
+ double lambda_;
+ double tau_;
+ double alpha_;
+ int btvKernelSize_;
+ int blurKernelSize_;
+ double blurSigma_;
+ Ptr<DenseOpticalFlowExt> opticalFlow_;
+
+ private:
+ vector<Ptr<cv::ocl::FilterEngine_GPU> > filters_;
+ int curBlurKernelSize_;
+ double curBlurSigma_;
+ int curSrcType_;
+
+ vector<float> btvWeights_;
+ int curBtvKernelSize_;
+ double curAlpha_;
+
+ vector<pair<oclMat, oclMat> > lowResForwardMotions_;
+ vector<pair<oclMat, oclMat> > lowResBackwardMotions_;
+
+ vector<pair<oclMat, oclMat> > highResForwardMotions_;
+ vector<pair<oclMat, oclMat> > highResBackwardMotions_;
+
+ vector<pair<oclMat, oclMat> > forwardMaps_;
+ vector<pair<oclMat, oclMat> > backwardMaps_;
+
+ oclMat highRes_;
+
+ vector<oclMat> diffTerms_;
+ vector<oclMat> a_, b_, c_;
+ oclMat regTerm_;
+ };
+
+ BTVL1_OCL_Base::BTVL1_OCL_Base()
+ {
+ scale_ = 4;
+ iterations_ = 180;
+ lambda_ = 0.03;
+ tau_ = 1.3;
+ alpha_ = 0.7;
+ btvKernelSize_ = 7;
+ blurKernelSize_ = 5;
+ blurSigma_ = 0.0;
+ opticalFlow_ = createOptFlow_DualTVL1_OCL();
+
+ curBlurKernelSize_ = -1;
+ curBlurSigma_ = -1.0;
+ curSrcType_ = -1;
+
+ curBtvKernelSize_ = -1;
+ curAlpha_ = -1.0;
+ }
+
+ void BTVL1_OCL_Base::process(const vector<oclMat>& src, oclMat& dst,
+ const vector<pair<oclMat, oclMat> >& forwardMotions, const vector<pair<oclMat, oclMat> >& backwardMotions,
+ int baseIdx)
+ {
+ CV_Assert( scale_ > 1 );
+ CV_Assert( iterations_ > 0 );
+ CV_Assert( tau_ > 0.0 );
+ CV_Assert( alpha_ > 0.0 );
+ CV_Assert( btvKernelSize_ > 0 && btvKernelSize_ <= 16 );
+ CV_Assert( blurKernelSize_ > 0 );
+ CV_Assert( blurSigma_ >= 0.0 );
+
+ // update blur filter and btv weights
+
+ if (filters_.size() != src.size() || blurKernelSize_ != curBlurKernelSize_ || blurSigma_ != curBlurSigma_ || src[0].type() != curSrcType_)
+ {
+ filters_.resize(src.size());
+ for (size_t i = 0; i < src.size(); ++i)
+ filters_[i] = cv::ocl::createGaussianFilter_GPU(src[0].type(), Size(blurKernelSize_, blurKernelSize_), blurSigma_);
+ curBlurKernelSize_ = blurKernelSize_;
+ curBlurSigma_ = blurSigma_;
+ curSrcType_ = src[0].type();
+ }
+
+ if (btvWeights_.empty() || btvKernelSize_ != curBtvKernelSize_ || alpha_ != curAlpha_)
+ {
+ calcBtvWeights(btvKernelSize_, alpha_, btvWeights_);
+ curBtvKernelSize_ = btvKernelSize_;
+ curAlpha_ = alpha_;
+ }
+
+ // calc motions between input frames
+
+ calcRelativeMotions(forwardMotions, backwardMotions,
+ lowResForwardMotions_, lowResBackwardMotions_,
+ baseIdx, src[0].size());
+
+ upscaleMotions(lowResForwardMotions_, highResForwardMotions_, scale_);
+ upscaleMotions(lowResBackwardMotions_, highResBackwardMotions_, scale_);
+
+ forwardMaps_.resize(highResForwardMotions_.size());
+ backwardMaps_.resize(highResForwardMotions_.size());
+ for (size_t i = 0; i < highResForwardMotions_.size(); ++i)
+ {
+ buildMotionMaps(highResForwardMotions_[i], highResBackwardMotions_[i], forwardMaps_[i], backwardMaps_[i]);
+ }
+ // initial estimation
+
+ const Size lowResSize = src[0].size();
+ const Size highResSize(lowResSize.width * scale_, lowResSize.height * scale_);
+
+ ocl::resize(src[baseIdx], highRes_, highResSize, 0, 0, INTER_LINEAR);
+
+ // iterations
+
+ diffTerms_.resize(src.size());
+ a_.resize(src.size());
+ b_.resize(src.size());
+ c_.resize(src.size());
+
+ for (int i = 0; i < iterations_; ++i)
+ {
+ for (size_t k = 0; k < src.size(); ++k)
+ {
+ diffTerms_[k].create(highRes_.size(), highRes_.type());
+ a_[k].create(highRes_.size(), highRes_.type());
+ b_[k].create(highRes_.size(), highRes_.type());
+ c_[k].create(lowResSize, highRes_.type());
+
+ // a = M * Ih
+ ocl::remap(highRes_, a_[k], backwardMaps_[k].first, backwardMaps_[k].second, INTER_NEAREST, BORDER_CONSTANT, Scalar());
+ // b = HM * Ih
+ filters_[k]->apply(a_[k], b_[k], Rect(0,0,-1,-1));
+ // c = DHF * Ih
+ ocl::resize(b_[k], c_[k], lowResSize, 0, 0, INTER_NEAREST);
+
+ diffSign(src[k], c_[k], c_[k]);
+
+ // a = Dt * diff
+ upscale(c_[k], a_[k], scale_);
+ // b = HtDt * diff
+ filters_[k]->apply(a_[k], b_[k], Rect(0,0,-1,-1));
+ // diffTerm = MtHtDt * diff
+ ocl::remap(b_[k], diffTerms_[k], forwardMaps_[k].first, forwardMaps_[k].second, INTER_NEAREST, BORDER_CONSTANT, Scalar());
+ }
+
+ if (lambda_ > 0)
+ {
+ calcBtvRegularization(highRes_, regTerm_, btvKernelSize_);
+ ocl::addWeighted(highRes_, 1.0, regTerm_, -tau_ * lambda_, 0.0, highRes_);
+ }
+
+ for (size_t k = 0; k < src.size(); ++k)
+ {
+ ocl::addWeighted(highRes_, 1.0, diffTerms_[k], tau_, 0.0, highRes_);
+ }
+ }
+
+ Rect inner(btvKernelSize_, btvKernelSize_, highRes_.cols - 2 * btvKernelSize_, highRes_.rows - 2 * btvKernelSize_);
+ highRes_(inner).copyTo(dst);
+ }
+
+ void BTVL1_OCL_Base::collectGarbage()
+ {
+ filters_.clear();
+
+ lowResForwardMotions_.clear();
+ lowResBackwardMotions_.clear();
+
+ highResForwardMotions_.clear();
+ highResBackwardMotions_.clear();
+
+ forwardMaps_.clear();
+ backwardMaps_.clear();
+
+ highRes_.release();
+
+ diffTerms_.clear();
+ a_.clear();
+ b_.clear();
+ c_.clear();
+ regTerm_.release();
+ }
+
+ ////////////////////////////////////////////////////////////
+
+ class BTVL1_OCL : public SuperResolution, private BTVL1_OCL_Base
+ {
+ public:
+ AlgorithmInfo* info() const;
+
+ BTVL1_OCL();
+
+ void collectGarbage();
+
+ protected:
+ void initImpl(Ptr<FrameSource>& frameSource);
+ void processImpl(Ptr<FrameSource>& frameSource, OutputArray output);
+
+ private:
+ int temporalAreaRadius_;
+
+ void readNextFrame(Ptr<FrameSource>& frameSource);
+ void processFrame(int idx);
+
+ oclMat curFrame_;
+ oclMat prevFrame_;
+
+ vector<oclMat> frames_;
+ vector<pair<oclMat, oclMat> > forwardMotions_;
+ vector<pair<oclMat, oclMat> > backwardMotions_;
+ vector<oclMat> outputs_;
+
+ int storePos_;
+ int procPos_;
+ int outPos_;
+
+ vector<oclMat> srcFrames_;
+ vector<pair<oclMat, oclMat> > srcForwardMotions_;
+ vector<pair<oclMat, oclMat> > srcBackwardMotions_;
+ oclMat finalOutput_;
+ };
+
+ CV_INIT_ALGORITHM(BTVL1_OCL, "SuperResolution.BTVL1_OCL",
+ obj.info()->addParam(obj, "scale", obj.scale_, false, 0, 0, "Scale factor.");
+ obj.info()->addParam(obj, "iterations", obj.iterations_, false, 0, 0, "Iteration count.");
+ obj.info()->addParam(obj, "tau", obj.tau_, false, 0, 0, "Asymptotic value of steepest descent method.");
+ obj.info()->addParam(obj, "lambda", obj.lambda_, false, 0, 0, "Weight parameter to balance data term and smoothness term.");
+ obj.info()->addParam(obj, "alpha", obj.alpha_, false, 0, 0, "Parameter of spacial distribution in Bilateral-TV.");
+ obj.info()->addParam(obj, "btvKernelSize", obj.btvKernelSize_, false, 0, 0, "Kernel size of Bilateral-TV filter.");
+ obj.info()->addParam(obj, "blurKernelSize", obj.blurKernelSize_, false, 0, 0, "Gaussian blur kernel size.");
+ obj.info()->addParam(obj, "blurSigma", obj.blurSigma_, false, 0, 0, "Gaussian blur sigma.");
+ obj.info()->addParam(obj, "temporalAreaRadius", obj.temporalAreaRadius_, false, 0, 0, "Radius of the temporal search area.");
+ obj.info()->addParam<DenseOpticalFlowExt>(obj, "opticalFlow", obj.opticalFlow_, false, 0, 0, "Dense optical flow algorithm."));
+
+ BTVL1_OCL::BTVL1_OCL()
+ {
+ temporalAreaRadius_ = 4;
+ }
+
+ void BTVL1_OCL::collectGarbage()
+ {
+ curFrame_.release();
+ prevFrame_.release();
+
+ frames_.clear();
+ forwardMotions_.clear();
+ backwardMotions_.clear();
+ outputs_.clear();
+
+ srcFrames_.clear();
+ srcForwardMotions_.clear();
+ srcBackwardMotions_.clear();
+ finalOutput_.release();
+
+ SuperResolution::collectGarbage();
+ BTVL1_OCL_Base::collectGarbage();
+ }
+
+ void BTVL1_OCL::initImpl(Ptr<FrameSource>& frameSource)
+ {
+ const int cacheSize = 2 * temporalAreaRadius_ + 1;
+
+ frames_.resize(cacheSize);
+ forwardMotions_.resize(cacheSize);
+ backwardMotions_.resize(cacheSize);
+ outputs_.resize(cacheSize);
+
+ storePos_ = -1;
+
+ for (int t = -temporalAreaRadius_; t <= temporalAreaRadius_; ++t)
+ readNextFrame(frameSource);
+
+ for (int i = 0; i <= temporalAreaRadius_; ++i)
+ processFrame(i);
+
+ procPos_ = temporalAreaRadius_;
+ outPos_ = -1;
+ }
+
+ void BTVL1_OCL::processImpl(Ptr<FrameSource>& frameSource, OutputArray _output)
+ {
+ if (outPos_ >= storePos_)
+ {
+ if(_output.kind() == _InputArray::OCL_MAT)
+ {
+ getOclMatRef(_output).release();
+ }
+ else
+ {
+ _output.release();
+ }
+ return;
+ }
+
+ readNextFrame(frameSource);
+
+ if (procPos_ < storePos_)
+ {
+ ++procPos_;
+ processFrame(procPos_);
+ }
+
+ ++outPos_;
+ const oclMat& curOutput = at(outPos_, outputs_);
+
+ if (_output.kind() == _InputArray::OCL_MAT)
+ curOutput.convertTo(getOclMatRef(_output), CV_8U);
+ else
+ {
+ curOutput.convertTo(finalOutput_, CV_8U);
+ arrCopy(finalOutput_, _output);
+ }
+ }
+
+ void BTVL1_OCL::readNextFrame(Ptr<FrameSource>& frameSource)
+ {
+ curFrame_.release();
+ frameSource->nextFrame(curFrame_);
+
+ if (curFrame_.empty())
+ return;
+
+ ++storePos_;
+ curFrame_.convertTo(at(storePos_, frames_), CV_32F);
+
+ if (storePos_ > 0)
+ {
+ pair<oclMat, oclMat>& forwardMotion = at(storePos_ - 1, forwardMotions_);
+ pair<oclMat, oclMat>& backwardMotion = at(storePos_, backwardMotions_);
+
+ opticalFlow_->calc(prevFrame_, curFrame_, forwardMotion.first, forwardMotion.second);
+ opticalFlow_->calc(curFrame_, prevFrame_, backwardMotion.first, backwardMotion.second);
+ }
+
+ curFrame_.copyTo(prevFrame_);
+ }
+
+ void BTVL1_OCL::processFrame(int idx)
+ {
+ const int startIdx = max(idx - temporalAreaRadius_, 0);
+ const int procIdx = idx;
+ const int endIdx = min(startIdx + 2 * temporalAreaRadius_, storePos_);
+
+ const int count = endIdx - startIdx + 1;
+
+ srcFrames_.resize(count);
+ srcForwardMotions_.resize(count);
+ srcBackwardMotions_.resize(count);
+
+ int baseIdx = -1;
+
+ for (int i = startIdx, k = 0; i <= endIdx; ++i, ++k)
+ {
+ if (i == procIdx)
+ baseIdx = k;
+
+ srcFrames_[k] = at(i, frames_);
+
+ if (i < endIdx)
+ srcForwardMotions_[k] = at(i, forwardMotions_);
+ if (i > startIdx)
+ srcBackwardMotions_[k] = at(i, backwardMotions_);
+ }
+
+ process(srcFrames_, at(idx, outputs_), srcForwardMotions_, srcBackwardMotions_, baseIdx);
+ }
+ }
+
+ Ptr<SuperResolution> cv::superres::createSuperResolution_BTVL1_OCL()
+ {
+ return new BTVL1_OCL;
+ }
++#endif
{
src.getGpuMat().copyTo(dst.getGpuMatRef());
}
- CV_Error(CV_StsNotImplemented, "The called functionality is disabled for current build or platform");;
+ #ifdef HAVE_OPENCV_OCL
+ void ocl2mat(InputArray src, OutputArray dst)
+ {
+ dst.getMatRef() = (Mat)ocl::getOclMatRef(src);
+ }
+ void mat2ocl(InputArray src, OutputArray dst)
+ {
+ Mat m = src.getMat();
+ ocl::getOclMatRef(dst) = (ocl::oclMat)m;
+ }
+ void ocl2ocl(InputArray src, OutputArray dst)
+ {
+ ocl::getOclMatRef(src).copyTo(ocl::getOclMatRef(dst));
+ }
+ #else
+ void ocl2mat(InputArray, OutputArray)
+ {
- CV_Error(CV_StsNotImplemented, "The called functionality is disabled for current build or platform");;
++ CV_Error(Error::StsNotImplemented, "The called functionality is disabled for current build or platform");;
+ }
+ void mat2ocl(InputArray, OutputArray)
+ {
- CV_Error(CV_StsNotImplemented, "The called functionality is disabled for current build or platform");
++ CV_Error(Error::StsNotImplemented, "The called functionality is disabled for current build or platform");;
+ }
+ void ocl2ocl(InputArray, OutputArray)
+ {
++ CV_Error(Error::StsNotImplemented, "The called functionality is disabled for current build or platform");
+ }
+ #endif
}
void cv::superres::arrCopy(InputArray src, OutputArray dst)
{
typedef void (*func_t)(InputArray src, OutputArray dst);
- static const func_t funcs[10][10] =
+ static const func_t funcs[11][11] =
{
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {0, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, arr2buf, 0 /*arr2tex*/, mat2gpu},
- {0, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, arr2buf, 0 /*arr2tex*/, mat2gpu},
- {0, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, arr2buf, 0 /*arr2tex*/, mat2gpu},
- {0, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, arr2buf, 0 /*arr2tex*/, mat2gpu},
- {0, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, arr2buf, 0 /*arr2tex*/, mat2gpu},
- {0, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, arr2buf, 0 /*arr2tex*/, mat2gpu},
- {0, buf2arr, buf2arr, buf2arr, buf2arr, buf2arr, buf2arr, buf2arr, 0 /*buf2arr*/, buf2arr},
- {0, 0 /*tex2arr*/, 0 /*tex2arr*/, 0 /*tex2arr*/, 0 /*tex2arr*/, 0 /*tex2arr*/, 0 /*tex2arr*/, 0 /*tex2arr*/, 0 /*tex2arr*/, 0 /*tex2arr*/},
- {0, gpu2mat, gpu2mat, gpu2mat, gpu2mat, gpu2mat, gpu2mat, arr2buf, 0 /*arr2tex*/, gpu2gpu}
- {0, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, arr2buf, arr2tex, mat2gpu, mat2ocl},
- {0, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, arr2buf, arr2tex, mat2gpu, mat2ocl},
- {0, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, arr2buf, arr2tex, mat2gpu, mat2ocl},
- {0, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, arr2buf, arr2tex, mat2gpu, mat2ocl},
- {0, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, arr2buf, arr2tex, mat2gpu, mat2ocl},
- {0, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, arr2buf, arr2tex, mat2gpu, mat2ocl},
- {0, buf2arr, buf2arr, buf2arr, buf2arr, buf2arr, buf2arr, buf2arr, buf2arr, buf2arr, 0 },
- {0, tex2arr, tex2arr, tex2arr, tex2arr, tex2arr, tex2arr, tex2arr, tex2arr, tex2arr, 0 },
- {0, gpu2mat, gpu2mat, gpu2mat, gpu2mat, gpu2mat, gpu2mat, arr2buf, arr2tex, gpu2gpu, 0 },
- {0, ocl2mat, ocl2mat, ocl2mat, ocl2mat, ocl2mat, ocl2mat, 0, 0, 0, ocl2ocl}
++ {0, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, arr2buf, 0 /*arr2tex*/, mat2gpu, mat2ocl},
++ {0, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, arr2buf, 0 /*arr2tex*/, mat2gpu, mat2ocl},
++ {0, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, arr2buf, 0 /*arr2tex*/, mat2gpu, mat2ocl},
++ {0, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, arr2buf, 0 /*arr2tex*/, mat2gpu, mat2ocl},
++ {0, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, arr2buf, 0 /*arr2tex*/, mat2gpu, mat2ocl},
++ {0, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, mat2mat, arr2buf, 0 /*arr2tex*/, mat2gpu, mat2ocl},
++ {0, buf2arr, buf2arr, buf2arr, buf2arr, buf2arr, buf2arr, buf2arr, 0 /*buf2arr*/, buf2arr, 0 },
++ {0, 0 /*tex2arr*/, 0 /*tex2arr*/, 0 /*tex2arr*/, 0 /*tex2arr*/, 0 /*tex2arr*/, 0 /*tex2arr*/, 0 /*tex2arr*/, 0 /*tex2arr*/, 0 /*tex2arr*/, 0},
++ {0, gpu2mat, gpu2mat, gpu2mat, gpu2mat, gpu2mat, gpu2mat, arr2buf, 0 /*arr2tex*/, gpu2gpu, 0 },
++ {0, ocl2mat, ocl2mat, ocl2mat, ocl2mat, ocl2mat, ocl2mat, 0, 0, 0, ocl2ocl}
};
const int src_kind = src.kind() >> _InputArray::KIND_SHIFT;
#ifndef __OPENCV_SUPERRES_INPUT_ARRAY_UTILITY_HPP__
#define __OPENCV_SUPERRES_INPUT_ARRAY_UTILITY_HPP__
-#include "opencv2/core/core.hpp"
-#include "opencv2/core/gpumat.hpp"
+#include "opencv2/core.hpp"
+#include "opencv2/core/gpu.hpp"
+ #ifdef HAVE_OPENCV_OCL
-#include "opencv2/ocl/ocl.hpp"
++#include "opencv2/ocl.hpp"
+ #endif
namespace cv
{
return new DualTVL1_GPU;
}
-#endif // HAVE_OPENCV_GPU
+#endif // HAVE_OPENCV_GPUOPTFLOW
+ #ifdef HAVE_OPENCV_OCL
+
+ namespace
+ {
+ class oclOpticalFlow : public DenseOpticalFlowExt
+ {
+ public:
+ explicit oclOpticalFlow(int work_type);
+
+ void calc(InputArray frame0, InputArray frame1, OutputArray flow1, OutputArray flow2);
+ void collectGarbage();
+
+ protected:
+ virtual void impl(const cv::ocl::oclMat& input0, const cv::ocl::oclMat& input1, cv::ocl::oclMat& dst1, cv::ocl::oclMat& dst2) = 0;
+
+ private:
+ int work_type_;
+ cv::ocl::oclMat buf_[6];
+ cv::ocl::oclMat u_, v_, flow_;
+ };
+
+ oclOpticalFlow::oclOpticalFlow(int work_type) : work_type_(work_type)
+ {
+ }
+
+ void oclOpticalFlow::calc(InputArray frame0, InputArray frame1, OutputArray flow1, OutputArray flow2)
+ {
+ ocl::oclMat& _frame0 = ocl::getOclMatRef(frame0);
+ ocl::oclMat& _frame1 = ocl::getOclMatRef(frame1);
+ ocl::oclMat& _flow1 = ocl::getOclMatRef(flow1);
+ ocl::oclMat& _flow2 = ocl::getOclMatRef(flow2);
+
+ CV_Assert( _frame1.type() == _frame0.type() );
+ CV_Assert( _frame1.size() == _frame0.size() );
+
+ cv::ocl::oclMat input0_ = convertToType(_frame0, work_type_, buf_[2], buf_[3]);
+ cv::ocl::oclMat input1_ = convertToType(_frame1, work_type_, buf_[4], buf_[5]);
+
+ impl(input0_, input1_, u_, v_);//go to tvl1 algorithm
+
+ u_.copyTo(_flow1);
+ v_.copyTo(_flow2);
+ }
+
+ void oclOpticalFlow::collectGarbage()
+ {
+ for (int i = 0; i < 6; ++i)
+ buf_[i].release();
+ u_.release();
+ v_.release();
+ flow_.release();
+ }
+ }
+ ///////////////////////////////////////////////////////////////////
+ // PyrLK_OCL
+
+ namespace
+ {
+ class PyrLK_OCL : public oclOpticalFlow
+ {
+ public:
+ AlgorithmInfo* info() const;
+
+ PyrLK_OCL();
+
+ void collectGarbage();
+
+ protected:
+ void impl(const ocl::oclMat& input0, const ocl::oclMat& input1, ocl::oclMat& dst1, ocl::oclMat& dst2);
+
+ private:
+ int winSize_;
+ int maxLevel_;
+ int iterations_;
+
+ ocl::PyrLKOpticalFlow alg_;
+ };
+
+ CV_INIT_ALGORITHM(PyrLK_OCL, "DenseOpticalFlowExt.PyrLK_OCL",
+ obj.info()->addParam(obj, "winSize", obj.winSize_);
+ obj.info()->addParam(obj, "maxLevel", obj.maxLevel_);
+ obj.info()->addParam(obj, "iterations", obj.iterations_));
+
+ PyrLK_OCL::PyrLK_OCL() : oclOpticalFlow(CV_8UC1)
+ {
+ winSize_ = alg_.winSize.width;
+ maxLevel_ = alg_.maxLevel;
+ iterations_ = alg_.iters;
+ }
+
+ void PyrLK_OCL::impl(const cv::ocl::oclMat& input0, const cv::ocl::oclMat& input1, cv::ocl::oclMat& dst1, cv::ocl::oclMat& dst2)
+ {
+ alg_.winSize.width = winSize_;
+ alg_.winSize.height = winSize_;
+ alg_.maxLevel = maxLevel_;
+ alg_.iters = iterations_;
+
+ alg_.dense(input0, input1, dst1, dst2);
+ }
+
+ void PyrLK_OCL::collectGarbage()
+ {
+ alg_.releaseMemory();
+ oclOpticalFlow::collectGarbage();
+ }
+ }
+
+ Ptr<DenseOpticalFlowExt> cv::superres::createOptFlow_PyrLK_OCL()
+ {
+ return new PyrLK_OCL;
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ // DualTVL1_OCL
+
+ namespace
+ {
+ class DualTVL1_OCL : public oclOpticalFlow
+ {
+ public:
+ AlgorithmInfo* info() const;
+
+ DualTVL1_OCL();
+
+ void collectGarbage();
+
+ protected:
+ void impl(const cv::ocl::oclMat& input0, const cv::ocl::oclMat& input1, cv::ocl::oclMat& dst1, cv::ocl::oclMat& dst2);
+
+ private:
+ double tau_;
+ double lambda_;
+ double theta_;
+ int nscales_;
+ int warps_;
+ double epsilon_;
+ int iterations_;
+ bool useInitialFlow_;
+
+ ocl::OpticalFlowDual_TVL1_OCL alg_;
+ };
+
+ CV_INIT_ALGORITHM(DualTVL1_OCL, "DenseOpticalFlowExt.DualTVL1_OCL",
+ obj.info()->addParam(obj, "tau", obj.tau_);
+ obj.info()->addParam(obj, "lambda", obj.lambda_);
+ obj.info()->addParam(obj, "theta", obj.theta_);
+ obj.info()->addParam(obj, "nscales", obj.nscales_);
+ obj.info()->addParam(obj, "warps", obj.warps_);
+ obj.info()->addParam(obj, "epsilon", obj.epsilon_);
+ obj.info()->addParam(obj, "iterations", obj.iterations_);
+ obj.info()->addParam(obj, "useInitialFlow", obj.useInitialFlow_));
+
+ DualTVL1_OCL::DualTVL1_OCL() : oclOpticalFlow(CV_8UC1)
+ {
+ tau_ = alg_.tau;
+ lambda_ = alg_.lambda;
+ theta_ = alg_.theta;
+ nscales_ = alg_.nscales;
+ warps_ = alg_.warps;
+ epsilon_ = alg_.epsilon;
+ iterations_ = alg_.iterations;
+ useInitialFlow_ = alg_.useInitialFlow;
+ }
+
+ void DualTVL1_OCL::impl(const cv::ocl::oclMat& input0, const cv::ocl::oclMat& input1, cv::ocl::oclMat& dst1, cv::ocl::oclMat& dst2)
+ {
+ alg_.tau = tau_;
+ alg_.lambda = lambda_;
+ alg_.theta = theta_;
+ alg_.nscales = nscales_;
+ alg_.warps = warps_;
+ alg_.epsilon = epsilon_;
+ alg_.iterations = iterations_;
+ alg_.useInitialFlow = useInitialFlow_;
+
+ alg_(input0, input1, dst1, dst2);
+
+ }
+
+ void DualTVL1_OCL::collectGarbage()
+ {
+ alg_.collectGarbage();
+ oclOpticalFlow::collectGarbage();
+ }
+ }
+
+ Ptr<DenseOpticalFlowExt> cv::superres::createOptFlow_DualTVL1_OCL()
+ {
+ return new DualTVL1_OCL;
+ }
+
-#endif
++#endif
#include <vector>
#include <limits>
-#ifdef HAVE_CVCONFIG_H
- #include "cvconfig.h"
-#endif
-
#include "opencv2/opencv_modules.hpp"
-#include "opencv2/core/core.hpp"
-#include "opencv2/core/gpumat.hpp"
-#include "opencv2/core/opengl_interop.hpp"
-#include "opencv2/core/internal.hpp"
-#include "opencv2/imgproc/imgproc.hpp"
+#include "opencv2/core.hpp"
+#include "opencv2/core/gpu.hpp"
+#include "opencv2/core/opengl.hpp"
+#include "opencv2/core/utility.hpp"
+#include "opencv2/imgproc.hpp"
#include "opencv2/video/tracking.hpp"
+#include "opencv2/core/private.hpp"
+
+#include "opencv2/core/private.gpu.hpp"
+
+#ifdef HAVE_OPENCV_GPUARITHM
+# include "opencv2/gpuarithm.hpp"
+#endif
+
+#ifdef HAVE_OPENCV_GPUWARPING
+# include "opencv2/gpuwarping.hpp"
+#endif
-#ifdef HAVE_OPENCV_GPU
- #include "opencv2/gpu/gpu.hpp"
- #ifdef HAVE_CUDA
- #include "opencv2/gpu/stream_accessor.hpp"
- #endif
+#ifdef HAVE_OPENCV_GPUFILTERS
+# include "opencv2/gpufilters.hpp"
+#endif
+
+#ifdef HAVE_OPENCV_GPUIMGPROC
+# include "opencv2/gpuimgproc.hpp"
+#endif
+
+#ifdef HAVE_OPENCV_GPUOPTFLOW
+# include "opencv2/gpuoptflow.hpp"
+#endif
+
+#ifdef HAVE_OPENCV_GPUCODEC
+# include "opencv2/gpucodec.hpp"
#endif
+ #ifdef HAVE_OPENCV_OCL
+ #include "opencv2/ocl/private/util.hpp"
+ #endif
+
#ifdef HAVE_OPENCV_HIGHGUI
- #include "opencv2/highgui/highgui.hpp"
+ #include "opencv2/highgui.hpp"
#endif
-#include "opencv2/superres/superres.hpp"
+#include "opencv2/superres.hpp"
#include "opencv2/superres/optical_flow.hpp"
#include "input_array_utility.hpp"
--- /dev/null
+#ifndef __OPENCV_GTESTCV_HPP__
+#define __OPENCV_GTESTCV_HPP__
+
+#include "opencv2/core/cvdef.h"
+#include <stdarg.h> // for va_list
+
+#include "cvconfig.h"
+
+#ifndef GTEST_CREATE_SHARED_LIBRARY
+#ifdef BUILD_SHARED_LIBS
+#define GTEST_LINKED_AS_SHARED_LIBRARY 1
+#endif
+#endif
+
+#ifdef _MSC_VER
+#pragma warning( disable: 4127 )
+#endif
+
+#define GTEST_DONT_DEFINE_FAIL 0
+#define GTEST_DONT_DEFINE_SUCCEED 0
+#define GTEST_DONT_DEFINE_ASSERT_EQ 0
+#define GTEST_DONT_DEFINE_ASSERT_NE 0
+#define GTEST_DONT_DEFINE_ASSERT_LE 0
+#define GTEST_DONT_DEFINE_ASSERT_LT 0
+#define GTEST_DONT_DEFINE_ASSERT_GE 0
+#define GTEST_DONT_DEFINE_ASSERT_GT 0
+#define GTEST_DONT_DEFINE_TEST 0
+
+#include "opencv2/ts/ts_gtest.h"
+
+#ifndef GTEST_USES_SIMPLE_RE
+# define GTEST_USES_SIMPLE_RE 0
+#endif
+#ifndef GTEST_USES_POSIX_RE
+# define GTEST_USES_POSIX_RE 0
+#endif
+
+#include "opencv2/core.hpp"
+#include "opencv2/core/utility.hpp"
+
+namespace cvtest
+{
+
+using std::vector;
+using std::string;
+using cv::RNG;
+using cv::Mat;
+using cv::Scalar;
+using cv::Size;
+using cv::Point;
+using cv::Rect;
+
+class CV_EXPORTS TS;
+
+CV_EXPORTS int64 readSeed(const char* str);
+
+CV_EXPORTS void randUni( RNG& rng, Mat& a, const Scalar& param1, const Scalar& param2 );
+
+inline unsigned randInt( RNG& rng )
+{
+ return (unsigned)rng;
+}
+
+inline double randReal( RNG& rng )
+{
+ return (double)rng;
+}
+
+
+CV_EXPORTS const char* getTypeName( int type );
+CV_EXPORTS int typeByName( const char* type_name );
+
+CV_EXPORTS string vec2str(const string& sep, const int* v, size_t nelems);
+
+inline int clipInt( int val, int min_val, int max_val )
+{
+ if( val < min_val )
+ val = min_val;
+ if( val > max_val )
+ val = max_val;
+ return val;
+}
+
+CV_EXPORTS double getMinVal(int depth);
+CV_EXPORTS double getMaxVal(int depth);
+
+CV_EXPORTS Size randomSize(RNG& rng, double maxSizeLog);
+CV_EXPORTS void randomSize(RNG& rng, int minDims, int maxDims, double maxSizeLog, vector<int>& sz);
+CV_EXPORTS int randomType(RNG& rng, int typeMask, int minChannels, int maxChannels);
+CV_EXPORTS Mat randomMat(RNG& rng, Size size, int type, double minVal, double maxVal, bool useRoi);
+CV_EXPORTS Mat randomMat(RNG& rng, const vector<int>& size, int type, double minVal, double maxVal, bool useRoi);
+CV_EXPORTS void add(const Mat& a, double alpha, const Mat& b, double beta,
+ Scalar gamma, Mat& c, int ctype, bool calcAbs=false);
+CV_EXPORTS void multiply(const Mat& a, const Mat& b, Mat& c, double alpha=1);
+CV_EXPORTS void divide(const Mat& a, const Mat& b, Mat& c, double alpha=1);
+
+CV_EXPORTS void convert(const Mat& src, cv::OutputArray dst, int dtype, double alpha=1, double beta=0);
+CV_EXPORTS void copy(const Mat& src, Mat& dst, const Mat& mask=Mat(), bool invertMask=false);
+CV_EXPORTS void set(Mat& dst, const Scalar& gamma, const Mat& mask=Mat());
+
+// working with multi-channel arrays
+CV_EXPORTS void extract( const Mat& a, Mat& plane, int coi );
+CV_EXPORTS void insert( const Mat& plane, Mat& a, int coi );
+
+// checks that the array does not have NaNs and/or Infs and all the elements are
+// within [min_val,max_val). idx is the index of the first "bad" element.
+CV_EXPORTS int check( const Mat& data, double min_val, double max_val, vector<int>* idx );
+
+// modifies values that are close to zero
+CV_EXPORTS void patchZeros( Mat& mat, double level );
+
+CV_EXPORTS void transpose(const Mat& src, Mat& dst);
+CV_EXPORTS void erode(const Mat& src, Mat& dst, const Mat& _kernel, Point anchor=Point(-1,-1),
+ int borderType=0, const Scalar& borderValue=Scalar());
+CV_EXPORTS void dilate(const Mat& src, Mat& dst, const Mat& _kernel, Point anchor=Point(-1,-1),
+ int borderType=0, const Scalar& borderValue=Scalar());
+CV_EXPORTS void filter2D(const Mat& src, Mat& dst, int ddepth, const Mat& kernel,
+ Point anchor, double delta, int borderType,
+ const Scalar& borderValue=Scalar());
+CV_EXPORTS void copyMakeBorder(const Mat& src, Mat& dst, int top, int bottom, int left, int right,
+ int borderType, const Scalar& borderValue=Scalar());
+CV_EXPORTS Mat calcSobelKernel2D( int dx, int dy, int apertureSize, int origin=0 );
+CV_EXPORTS Mat calcLaplaceKernel2D( int aperture_size );
+
+CV_EXPORTS void initUndistortMap( const Mat& a, const Mat& k, Size sz, Mat& mapx, Mat& mapy );
+
+CV_EXPORTS void minMaxLoc(const Mat& src, double* minval, double* maxval,
+ vector<int>* minloc, vector<int>* maxloc, const Mat& mask=Mat());
+CV_EXPORTS double norm(const Mat& src, int normType, const Mat& mask=Mat());
+CV_EXPORTS double norm(const Mat& src1, const Mat& src2, int normType, const Mat& mask=Mat());
+CV_EXPORTS Scalar mean(const Mat& src, const Mat& mask=Mat());
+
+CV_EXPORTS bool cmpUlps(const Mat& data, const Mat& refdata, int expMaxDiff, double* realMaxDiff, vector<int>* idx);
+
+// compares two arrays. max_diff is the maximum actual difference,
+// success_err_level is maximum allowed difference, idx is the index of the first
+// element for which difference is >success_err_level
+// (or index of element with the maximum difference)
+CV_EXPORTS int cmpEps( const Mat& data, const Mat& refdata, double* max_diff,
+ double success_err_level, vector<int>* idx,
+ bool element_wise_relative_error );
+
+// a wrapper for the previous function. in case of error prints the message to log file.
+CV_EXPORTS int cmpEps2( TS* ts, const Mat& data, const Mat& refdata, double success_err_level,
+ bool element_wise_relative_error, const char* desc );
+
+CV_EXPORTS int cmpEps2_64f( TS* ts, const double* val, const double* refval, int len,
+ double eps, const char* param_name );
+
+CV_EXPORTS void logicOp(const Mat& src1, const Mat& src2, Mat& dst, char c);
+CV_EXPORTS void logicOp(const Mat& src, const Scalar& s, Mat& dst, char c);
+CV_EXPORTS void min(const Mat& src1, const Mat& src2, Mat& dst);
+CV_EXPORTS void min(const Mat& src, double s, Mat& dst);
+CV_EXPORTS void max(const Mat& src1, const Mat& src2, Mat& dst);
+CV_EXPORTS void max(const Mat& src, double s, Mat& dst);
+
+CV_EXPORTS void compare(const Mat& src1, const Mat& src2, Mat& dst, int cmpop);
+CV_EXPORTS void compare(const Mat& src, double s, Mat& dst, int cmpop);
+CV_EXPORTS void gemm(const Mat& src1, const Mat& src2, double alpha,
+ const Mat& src3, double beta, Mat& dst, int flags);
+ CV_EXPORTS void transform( const Mat& src, Mat& dst, const Mat& transmat, const Mat& shift );
+CV_EXPORTS double crossCorr(const Mat& src1, const Mat& src2);
+
+struct CV_EXPORTS MatInfo
+{
+ MatInfo(const Mat& _m) : m(&_m) {}
+ const Mat* m;
+};
+
+CV_EXPORTS std::ostream& operator << (std::ostream& out, const MatInfo& m);
+
+struct CV_EXPORTS MatComparator
+{
+public:
+ MatComparator(double maxdiff, int context);
+
+ ::testing::AssertionResult operator()(const char* expr1, const char* expr2,
+ const Mat& m1, const Mat& m2);
+
+ double maxdiff;
+ double realmaxdiff;
+ vector<int> loc0;
+ int context;
+};
+
+
+
+class BaseTest;
+class TS;
+
+class CV_EXPORTS BaseTest
+{
+public:
+ // constructor(s) and destructor
+ BaseTest();
+ virtual ~BaseTest();
+
+ // the main procedure of the test
+ virtual void run( int start_from );
+
+ // the wrapper for run that cares of exceptions
+ virtual void safe_run( int start_from=0 );
+
+ const string& get_name() const { return name; }
+
+ // returns true if and only if the different test cases do not depend on each other
+ // (so that test system could get right to a problematic test case)
+ virtual bool can_do_fast_forward();
+
+ // deallocates all the memory.
+ // called by init() (before initialization) and by the destructor
+ virtual void clear();
+
+protected:
+ int test_case_count; // the total number of test cases
+
+ // read test params
+ virtual int read_params( CvFileStorage* fs );
+
+ // returns the number of tests or -1 if it is unknown a-priori
+ virtual int get_test_case_count();
+
+ // prepares data for the next test case. rng seed is updated by the function
+ virtual int prepare_test_case( int test_case_idx );
+
+ // checks if the test output is valid and accurate
+ virtual int validate_test_results( int test_case_idx );
+
+ // calls the tested function. the method is called from run_test_case()
+ virtual void run_func(); // runs tested func(s)
+
+ // updates progress bar
+ virtual int update_progress( int progress, int test_case_idx, int count, double dt );
+
+ // finds test parameter
+ const CvFileNode* find_param( CvFileStorage* fs, const char* param_name );
+
+ // name of the test (it is possible to locate a test by its name)
+ string name;
+
+ // pointer to the system that includes the test
+ TS* ts;
+};
+
+
+/*****************************************************************************************\
+* Information about a failed test *
+\*****************************************************************************************/
+
+struct TestInfo
+{
+ TestInfo();
+
+ // pointer to the test
+ BaseTest* test;
+
+ // failure code (CV_FAIL*)
+ int code;
+
+ // seed value right before the data for the failed test case is prepared.
+ uint64 rng_seed;
+
+ // seed value right before running the test
+ uint64 rng_seed0;
+
+ // index of test case, can be then passed to BaseTest::proceed_to_test_case()
+ int test_case_idx;
+};
+
+/*****************************************************************************************\
+* Base Class for test system *
+\*****************************************************************************************/
+
+// common parameters:
+struct CV_EXPORTS TSParams
+{
+ TSParams();
+
+ // RNG seed, passed to and updated by every test executed.
+ uint64 rng_seed;
+
+ // whether to use IPP, MKL etc. or not
+ bool use_optimized;
+
+ // extensivity of the tests, scale factor for test_case_count
+ double test_case_count_scale;
+};
+
+
+class CV_EXPORTS TS
+{
+public:
+ // constructor(s) and destructor
+ TS();
+ virtual ~TS();
+
+ enum
+ {
+ NUL=0,
+ SUMMARY_IDX=0,
+ SUMMARY=1 << SUMMARY_IDX,
+ LOG_IDX=1,
+ LOG=1 << LOG_IDX,
+ CSV_IDX=2,
+ CSV=1 << CSV_IDX,
+ CONSOLE_IDX=3,
+ CONSOLE=1 << CONSOLE_IDX,
+ MAX_IDX=4
+ };
+
+ static TS* ptr();
+
+ // initialize test system before running the first test
+ virtual void init( const string& modulename );
+
+ // low-level printing functions that are used by individual tests and by the system itself
+ virtual void printf( int streams, const char* fmt, ... );
+ virtual void vprintf( int streams, const char* fmt, va_list arglist );
+
+ // updates the context: current test, test case, rng state
+ virtual void update_context( BaseTest* test, int test_case_idx, bool update_ts_context );
+
+ const TestInfo* get_current_test_info() { return ¤t_test_info; }
+
+ // sets information about a failed test
+ virtual void set_failed_test_info( int fail_code );
+
+ virtual void set_gtest_status();
+
+ // test error codes
+ enum
+ {
+ // everything is Ok
+ OK=0,
+
+ // generic error: stub value to be used
+ // temporarily if the error's cause is unknown
+ FAIL_GENERIC=-1,
+
+ // the test is missing some essential data to proceed further
+ FAIL_MISSING_TEST_DATA=-2,
+
+ // the tested function raised an error via cxcore error handler
+ FAIL_ERROR_IN_CALLED_FUNC=-3,
+
+ // an exception has been raised;
+ // for memory and arithmetic exception
+ // there are two specialized codes (see below...)
+ FAIL_EXCEPTION=-4,
+
+ // a memory exception
+ // (access violation, access to missed page, stack overflow etc.)
+ FAIL_MEMORY_EXCEPTION=-5,
+
+ // arithmetic exception (overflow, division by zero etc.)
+ FAIL_ARITHM_EXCEPTION=-6,
+
+ // the tested function corrupted memory (no exception have been raised)
+ FAIL_MEMORY_CORRUPTION_BEGIN=-7,
+ FAIL_MEMORY_CORRUPTION_END=-8,
+
+ // the tested function (or test ifself) do not deallocate some memory
+ FAIL_MEMORY_LEAK=-9,
+
+ // the tested function returned invalid object, e.g. matrix, containing NaNs,
+ // structure with NULL or out-of-range fields (while it should not)
+ FAIL_INVALID_OUTPUT=-10,
+
+ // the tested function returned valid object, but it does not match to
+ // the original (or produced by the test) object
+ FAIL_MISMATCH=-11,
+
+ // the tested function returned valid object (a single number or numerical array),
+ // but it differs too much from the original (or produced by the test) object
+ FAIL_BAD_ACCURACY=-12,
+
+ // the tested function hung. Sometimes, can be determined by unexpectedly long
+ // processing time (in this case there should be possibility to interrupt such a function
+ FAIL_HANG=-13,
+
+ // unexpected responce on passing bad arguments to the tested function
+ // (the function crashed, proceed succesfully (while it should not), or returned
+ // error code that is different from what is expected)
+ FAIL_BAD_ARG_CHECK=-14,
+
+ // the test data (in whole or for the particular test case) is invalid
+ FAIL_INVALID_TEST_DATA=-15,
+
+ // the test has been skipped because it is not in the selected subset of the tests to run,
+ // because it has been run already within the same run with the same parameters, or because
+ // of some other reason and this is not considered as an error.
+ // Normally TS::run() (or overrided method in the derived class) takes care of what
+ // needs to be run, so this code should not occur.
+ SKIPPED=1
+ };
+
+ // get file storage
+ CvFileStorage* get_file_storage();
+
+ // get RNG to generate random input data for a test
+ RNG& get_rng() { return rng; }
+
+ // returns the current error code
+ int get_err_code() { return current_test_info.code; }
+
+ // returns the test extensivity scale
+ double get_test_case_count_scale() { return params.test_case_count_scale; }
+
+ const string& get_data_path() const { return data_path; }
+
+ // returns textual description of failure code
+ static string str_from_code( int code );
+
+protected:
+
+ // these are allocated within a test to try keep them valid in case of stack corruption
+ RNG rng;
+
+ // information about the current test
+ TestInfo current_test_info;
+
+ // the path to data files used by tests
+ string data_path;
+
+ TSParams params;
+ std::string output_buf[MAX_IDX];
+};
+
+
+/*****************************************************************************************\
+* Subclass of BaseTest for testing functions that process dense arrays *
+\*****************************************************************************************/
+
+class CV_EXPORTS ArrayTest : public BaseTest
+{
+public:
+ // constructor(s) and destructor
+ ArrayTest();
+ virtual ~ArrayTest();
+
+ virtual void clear();
+
+protected:
+
+ virtual int read_params( CvFileStorage* fs );
+ virtual int prepare_test_case( int test_case_idx );
+ virtual int validate_test_results( int test_case_idx );
+
+ virtual void prepare_to_validation( int test_case_idx );
+ virtual void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
+ virtual void fill_array( int test_case_idx, int i, int j, Mat& arr );
+ virtual void get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high );
+ virtual double get_success_error_level( int test_case_idx, int i, int j );
+
+ bool cvmat_allowed;
+ bool iplimage_allowed;
+ bool optional_mask;
+ bool element_wise_relative_error;
+
+ int min_log_array_size;
+ int max_log_array_size;
+
+ enum { INPUT, INPUT_OUTPUT, OUTPUT, REF_INPUT_OUTPUT, REF_OUTPUT, TEMP, MASK, MAX_ARR };
+
+ vector<vector<void*> > test_array;
+ vector<vector<Mat> > test_mat;
+ float buf[4];
+};
+
+
+class CV_EXPORTS BadArgTest : public BaseTest
+{
+public:
+ // constructor(s) and destructor
+ BadArgTest();
+ virtual ~BadArgTest();
+
+protected:
+ virtual int run_test_case( int expected_code, const string& descr );
+ virtual void run_func(void) = 0;
+ int test_case_idx;
+
+ template<class F>
+ int run_test_case( int expected_code, const string& _descr, F f)
+ {
+ int errcount = 0;
+ bool thrown = false;
+ const char* descr = _descr.c_str() ? _descr.c_str() : "";
+
+ try
+ {
+ f();
+ }
+ catch(const cv::Exception& e)
+ {
+ thrown = true;
+ if( e.code != expected_code )
+ {
+ ts->printf(TS::LOG, "%s (test case #%d): the error code %d is different from the expected %d\n",
+ descr, test_case_idx, e.code, expected_code);
+ errcount = 1;
+ }
+ }
+ catch(...)
+ {
+ thrown = true;
+ ts->printf(TS::LOG, "%s (test case #%d): unknown exception was thrown (the function has likely crashed)\n",
+ descr, test_case_idx);
+ errcount = 1;
+ }
+ if(!thrown)
+ {
+ ts->printf(TS::LOG, "%s (test case #%d): no expected exception was thrown\n",
+ descr, test_case_idx);
+ errcount = 1;
+ }
+ test_case_idx++;
+
+ return errcount;
+ }
+};
+
+struct CV_EXPORTS DefaultRngAuto
+{
+ const uint64 old_state;
+
+ DefaultRngAuto() : old_state(cv::theRNG().state) { cv::theRNG().state = (uint64)-1; }
+ ~DefaultRngAuto() { cv::theRNG().state = old_state; }
+
+ DefaultRngAuto& operator=(const DefaultRngAuto&);
+};
+
+}
+
+namespace cvtest
+{
+
+// test images generation functions
+CV_EXPORTS void fillGradient(Mat& img, int delta = 5);
+CV_EXPORTS void smoothBorder(Mat& img, const Scalar& color, int delta = 3);
+
+CV_EXPORTS void printVersionInfo(bool useStdOut = true);
+} //namespace cvtest
+
+#define CV_TEST_MAIN(resourcesubdir) \
+int main(int argc, char **argv) \
+{ \
+ cvtest::TS::ptr()->init(resourcesubdir); \
+ ::testing::InitGoogleTest(&argc, argv); \
+ cvtest::printVersionInfo();\
+ return RUN_ALL_TESTS(); \
+}
+
++// This usually only makes sense in perf tests with several implementations,
++// some of which are not available.
++#define CV_TEST_FAIL_NO_IMPL() do { \
++ ::testing::Test::RecordProperty("custom_status", "noimpl"); \
++ FAIL() << "No equivalent implementation."; \
++} while (0)
++
+#endif
+
+#include "opencv2/ts/ts_perf.hpp"