From: Roman Donchenko Date: Mon, 15 Jul 2013 14:40:54 +0000 (+0400) Subject: Merge remote-tracking branch 'origin/2.4' into merge-2.4 X-Git-Tag: submit/tizen_ivi/20141117.190038~2^2~998^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=feaa12a27497ae46701358ff09d18bb8e39a041a;p=profile%2Fivi%2Fopencv.git Merge remote-tracking branch 'origin/2.4' into merge-2.4 Conflicts: modules/core/include/opencv2/core/version.hpp modules/ocl/include/opencv2/ocl/ocl.hpp modules/ocl/src/initialization.cpp modules/ocl/test/main.cpp modules/superres/CMakeLists.txt modules/superres/src/input_array_utility.cpp modules/superres/src/input_array_utility.hpp modules/superres/src/optical_flow.cpp --- feaa12a27497ae46701358ff09d18bb8e39a041a diff --cc modules/ocl/include/opencv2/ocl.hpp index 3da9352,0000000..a8ebcba mode 100644,000000..100644 --- a/modules/ocl/include/opencv2/ocl.hpp +++ b/modules/ocl/include/opencv2/ocl.hpp @@@ -1,1819 -1,0 +1,1832 @@@ +/*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 +#include + +#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 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 &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; + friend bool initialized(); + private: + static std::auto_ptr 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 > &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 > &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 _Tp *ptr(int y = 0); + template 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 &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 &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 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 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 createFilter2D_GPU(const Ptr filter2D); + + //! returns the primitive row filter with the specified kernel + CV_EXPORTS Ptr 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 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 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 createSeparableFilter_GPU(const Ptr &rowFilter, + const Ptr &columnFilter); + + //! returns the Gaussian filter engine + CV_EXPORTS Ptr 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 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 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 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 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 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 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 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& 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& faces, const std::vector &rectList, const std::vector &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 sizev; + std::vector 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 images; + std::vector image_sums; + std::vector 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 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 &detector); + + + + static std::vector getDefaultPeopleDetector(); + + static std::vector getPeopleDetector48x96(); + + static std::vector getPeopleDetector64x128(); + + + + void detect(const oclMat &img, std::vector &found_locations, + + double hit_threshold = 0, Size win_stride = Size(), + + Size padding = Size()); + + + + void detectMultiScale(const oclMat &img, std::vector &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 + struct CV_EXPORTS Accumulator + { + typedef T Type; + }; + template<> struct Accumulator + { + typedef float Type; + }; + template<> struct Accumulator + { + typedef float Type; + }; + template<> struct Accumulator + { + typedef float Type; + }; + template<> struct Accumulator + { + typedef float Type; + }; + + /* + * Manhattan distance (city block distance) functor + */ + template + struct CV_EXPORTS L1 + { + enum { normType = NORM_L1 }; + typedef T ValueType; + typedef typename Accumulator::Type ResultType; + + ResultType operator()( const T *a, const T *b, int size ) const + { + return normL1(a, b, size); + } + }; + + /* + * Euclidean distance functor + */ + template + struct CV_EXPORTS L2 + { + enum { normType = NORM_L2 }; + typedef T ValueType; + typedef typename Accumulator::Type ResultType; + + ResultType operator()( const T *a, const T *b, int size ) const + { + return (ResultType)std::sqrt((double)normL2Sqr(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 &descCollection); + + // Get train descriptors collection + const std::vector &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 &matches); + // Convert trainIdx and distance to vector with DMatch + static void matchConvert(const Mat &trainIdx, const Mat &distance, std::vector &matches); + + // Find one best match for each query descriptor + void match(const oclMat &query, const oclMat &train, std::vector &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 &masks = std::vector()); + + // 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 &matches); + // Convert trainIdx, imgIdx and distance to vector with DMatch + static void matchConvert(const Mat &trainIdx, const Mat &imgIdx, const Mat &distance, std::vector &matches); + + // Find one best match from train collection for each query descriptor. + void match(const oclMat &query, std::vector &matches, const std::vector &masks = std::vector()); + + // 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 > &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 > &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 > &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 > &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 > &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 > &matches, int k, + const std::vector &masks = std::vector(), bool compactResult = false); + + // Find best matches for each query descriptor which have distance less than maxDistance. + // nMatches.at(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 > &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 > &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 > &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 &masks = std::vector()); + + // 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 > &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 > &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 > &matches, float maxDistance, + const std::vector &masks = std::vector(), bool compactResult = false); + + DistType distType; + + private: + std::vector trainDescCollection; + }; + + template + class CV_EXPORTS BruteForceMatcher_OCL; + + template + class CV_EXPORTS BruteForceMatcher_OCL< L1 > : public BruteForceMatcher_OCL_base + { + public: + explicit BruteForceMatcher_OCL() : BruteForceMatcher_OCL_base(L1Dist) {} + explicit BruteForceMatcher_OCL(L1 /*d*/) : BruteForceMatcher_OCL_base(L1Dist) {} + }; + template + class CV_EXPORTS BruteForceMatcher_OCL< L2 > : public BruteForceMatcher_OCL_base + { + public: + explicit BruteForceMatcher_OCL() : BruteForceMatcher_OCL_base(L2Dist) {} + explicit BruteForceMatcher_OCL(L2 /*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 &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 &pyr, bool withBorder); + + oclMat dx_calcBuf_; + oclMat dy_calcBuf_; + + std::vector prevPyr_; + std::vector 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 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 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 I0s; + std::vector I1s; + std::vector u1s; + std::vector 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__ */ diff --cc modules/ocl/src/kmeans.cpp index 0000000,22f8660..ce5ecbc mode 000000,100644..100644 --- a/modules/ocl/src/kmeans.cpp +++ b/modules/ocl/src/kmeans.cpp @@@ -1,0 -1,438 +1,438 @@@ + /*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 + #include "precomp.hpp" + + using namespace cv; + using namespace ocl; + + namespace cv + { + namespace ocl + { + ////////////////////////////////////OpenCL kernel strings////////////////////////// + extern const char *kmeans_kernel; + } + } + -static void generateRandomCenter(const vector& box, float* center, RNG& rng) ++static void generateRandomCenter(const std::vector& 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 _centers(K); ++ std::vector _centers(K); + int* centers = &_centers[0]; - vector _dist(N*3); ++ std::vector _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(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()); - string kernelname = "distanceToCenters"; ++ 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}; + - vector > 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)); ++ std::vector > 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; - if( flags & CV_KMEANS_USE_INITIAL_LABELS ) ++ 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(); + + Mat data; + _src.download(data); + Mat centers(K, dims, type), old_centers(K, dims, type), temp(1, dims, type); - vector counters(K); - vector _box(dims); ++ std::vector counters(K); ++ std::vector _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(); + for( j = 0; j < dims; j++ ) + box[j] = Vec2f(sample[j], sample[j]); + + for( i = 1; i < N; i++ ) + { + sample = data.ptr(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(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(i); + k = labels[i]; + float* center = centers.ptr(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(k); + float* old_center = centers.ptr(max_k); + float* _old_center = temp.ptr(); // 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(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(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(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(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(0); + compactness = 0; + for( i = 0; i < N; i++ ) + { + compactness += dist[i]; + } + } + + if( compactness < best_compactness ) + { + best_compactness = compactness; + } + } + + return best_compactness; + } + diff --cc modules/ocl/test/main.cpp index 5f7b2ba,1250691..48d21b9 --- a/modules/ocl/test/main.cpp +++ b/modules/ocl/test/main.cpp @@@ -73,29 -73,26 +73,26 @@@ void print_info( #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("help")) + if (cmd.get("h")=="true") { cout << "Avaible options besides goole test option:" << endl; - cmd.printParams(); + cmd.printMessage(); return 0; } - workdir = cmd.get("w"); - string type = cmd.get("type"); - unsigned int pid = cmd.get("platform"); - int device = cmd.get("device"); + string type = cmd.get("t"); + unsigned int pid = cmd.get("p"); + int device = cmd.get("d"); print_info(); int flag = CVCL_DEVICE_TYPE_GPU; diff --cc modules/ocl/test/test_kmeans.cpp index 0000000,ebade3b..a29c879 mode 000000,100644..100644 --- a/modules/ocl/test/test_kmeans.cpp +++ b/modules/ocl/test/test_kmeans.cpp @@@ -1,0 -1,162 +1,162 @@@ + /*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(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(); + 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( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 100, 0), ++ 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(row_idx); + int header_label = dd_labels.at(row_idx); + for(int j = 0; (j < MHEIGHT/K)||(i == K-1 && j < MHEIGHT/K+MHEIGHT%K); j++) + { + ASSERT_NEAR(labels.at(row_idx+j), label, 0); + ASSERT_NEAR(dd_labels.at(row_idx+j), header_label, 0); + } + + // verify centers + float *center = centers.ptr(label); + float *header_center = dd_centers.ptr(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 diff --cc modules/superres/CMakeLists.txt index 065d8ce,44e9dc0..4515061 --- a/modules/superres/CMakeLists.txt +++ b/modules/superres/CMakeLists.txt @@@ -4,6 -4,4 +4,6 @@@ 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) diff --cc modules/superres/include/opencv2/superres.hpp index b85d0c1,0000000..ac12c42 mode 100644,000000..100644 --- a/modules/superres/include/opencv2/superres.hpp +++ b/modules/superres/include/opencv2/superres.hpp @@@ -1,98 -1,0 +1,99 @@@ +/*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 createFrameSource_Empty(); + + CV_EXPORTS Ptr createFrameSource_Video(const String& fileName); + CV_EXPORTS Ptr createFrameSource_Video_GPU(const String& fileName); + + CV_EXPORTS Ptr createFrameSource_Camera(int deviceId = 0); + + class CV_EXPORTS SuperResolution : public cv::Algorithm, public FrameSource + { + public: + void setInput(const Ptr& frameSource); + + void nextFrame(OutputArray frame); + void reset(); + + virtual void collectGarbage(); + + protected: + SuperResolution(); + + virtual void initImpl(Ptr& frameSource) = 0; + virtual void processImpl(Ptr& frameSource, OutputArray output) = 0; + + private: + Ptr 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 createSuperResolution_BTVL1(); + CV_EXPORTS Ptr createSuperResolution_BTVL1_GPU(); ++ CV_EXPORTS Ptr createSuperResolution_BTVL1_OCL(); + } +} + +#endif // __OPENCV_SUPERRES_HPP__ diff --cc modules/superres/perf/perf_superres_ocl.cpp index 0000000,e75a877..ca9c81e mode 000000,100644..100644 --- a/modules/superres/perf/perf_superres_ocl.cpp +++ b/modules/superres/perf/perf_superres_ocl.cpp @@@ -1,0 -1,146 +1,147 @@@ + /*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/ocl.hpp" ++#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::vectorinfo; + 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 opticalFlowOcl(new ZeroOpticalFlowOCL); + + Ptr 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 diff --cc modules/superres/src/btv_l1_ocl.cpp index 0000000,5f9e326..e417d89 mode 000000,100644..100644 --- a/modules/superres/src/btv_l1_ocl.cpp +++ b/modules/superres/src/btv_l1_ocl.cpp @@@ -1,0 -1,748 +1,748 @@@ + /*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::createSuperResolution_BTVL1_OCL() + { - CV_Error(CV_StsNotImplemented, "The called functionality is disabled for current build or platform"); ++ CV_Error(cv::Error::StsNotImplemented, "The called functionality is disabled for current build or platform"); + return Ptr(); + } + + #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 > 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 > 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 > 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 > 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 >& forwardMotions, const vector >& backwardMotions, + vector >& relForwardMotions, vector >& relBackwardMotions, + int baseIdx, Size size) + { + const int count = static_cast(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 >& lowResMotions, vector >& 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& forwardMotion, const pair& backwardMotion, + pair& forwardMap, pair& 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& btvWeights) + { + const size_t size = btvKernelSize * btvKernelSize; + + btvWeights.resize(size); + + const int ksize = (btvKernelSize - 1) / 2; + const float alpha_f = static_cast(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& src, oclMat& dst, + const vector >& forwardMotions, const vector >& backwardMotions, + int baseIdx); + + void collectGarbage(); + + protected: + int scale_; + int iterations_; + double lambda_; + double tau_; + double alpha_; + int btvKernelSize_; + int blurKernelSize_; + double blurSigma_; + Ptr opticalFlow_; + + private: + vector > filters_; + int curBlurKernelSize_; + double curBlurSigma_; + int curSrcType_; + + vector btvWeights_; + int curBtvKernelSize_; + double curAlpha_; + + vector > lowResForwardMotions_; + vector > lowResBackwardMotions_; + + vector > highResForwardMotions_; + vector > highResBackwardMotions_; + + vector > forwardMaps_; + vector > backwardMaps_; + + oclMat highRes_; + + vector diffTerms_; + vector 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& src, oclMat& dst, + const vector >& forwardMotions, const vector >& 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); + void processImpl(Ptr& frameSource, OutputArray output); + + private: + int temporalAreaRadius_; + + void readNextFrame(Ptr& frameSource); + void processFrame(int idx); + + oclMat curFrame_; + oclMat prevFrame_; + + vector frames_; + vector > forwardMotions_; + vector > backwardMotions_; + vector outputs_; + + int storePos_; + int procPos_; + int outPos_; + + vector srcFrames_; + vector > srcForwardMotions_; + vector > 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(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) + { + 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, 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) + { + curFrame_.release(); + frameSource->nextFrame(curFrame_); + + if (curFrame_.empty()) + return; + + ++storePos_; + curFrame_.convertTo(at(storePos_, frames_), CV_32F); + + if (storePos_ > 0) + { + pair& forwardMotion = at(storePos_ - 1, forwardMotions_); + pair& 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 cv::superres::createSuperResolution_BTVL1_OCL() + { + return new BTVL1_OCL; + } -#endif ++#endif diff --cc modules/superres/src/input_array_utility.cpp index e749050,075cf95..1f25ede --- a/modules/superres/src/input_array_utility.cpp +++ b/modules/superres/src/input_array_utility.cpp @@@ -108,23 -125,52 +108,52 @@@ namespac { src.getGpuMat().copyTo(dst.getGpuMatRef()); } + #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(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"); + } + #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; diff --cc modules/superres/src/input_array_utility.hpp index 488399f,9fa63da..0c86143 --- a/modules/superres/src/input_array_utility.hpp +++ b/modules/superres/src/input_array_utility.hpp @@@ -43,8 -43,11 +43,11 @@@ #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 { diff --cc modules/superres/src/optical_flow.cpp index 242b91e,6947d19..cabe08f --- a/modules/superres/src/optical_flow.cpp +++ b/modules/superres/src/optical_flow.cpp @@@ -717,4 -718,196 +717,196 @@@ Ptr cv::superres:: 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 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 cv::superres::createOptFlow_DualTVL1_OCL() + { + return new DualTVL1_OCL; + } + -#endif ++#endif diff --cc modules/superres/src/precomp.hpp index f3c993e,51e6c33..822d488 --- a/modules/superres/src/precomp.hpp +++ b/modules/superres/src/precomp.hpp @@@ -46,46 -46,34 +46,50 @@@ #include #include -#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" diff --cc modules/ts/include/opencv2/ts.hpp index f4ff827,0000000..f41b421 mode 100644,000000..100644 --- a/modules/ts/include/opencv2/ts.hpp +++ b/modules/ts/include/opencv2/ts.hpp @@@ -1,556 -1,0 +1,563 @@@ +#ifndef __OPENCV_GTESTCV_HPP__ +#define __OPENCV_GTESTCV_HPP__ + +#include "opencv2/core/cvdef.h" +#include // 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& 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& 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* 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* minloc, vector* 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* 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* 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 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 >& sizes, vector >& 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 > test_array; + vector > 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 + 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"