Merge pull request #1534 from jet47:fix-cuda-5.0-build
[profile/ivi/opencv.git] / modules / ocl / src / imgproc.cpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                           License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
14 // Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
15 // Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
16 // Third party copyrights are property of their respective owners.
17 //
18 // @Authors
19 //    Niko Li, newlife20080214@gmail.com
20 //    Jia Haipeng, jiahaipeng95@gmail.com
21 //    Shengen Yan, yanshengen@gmail.com
22 //    Rock Li, Rock.Li@amd.com
23 //    Zero Lin, Zero.Lin@amd.com
24 //    Zhang Ying, zhangying913@gmail.com
25 //    Xu Pang, pangxu010@163.com
26 //    Wu Zailong, bullet@yeah.net
27 //    Wenju He, wenju@multicorewareinc.com
28 //    Peng Xiao, pengxiao@outlook.com
29 //    Sen Liu, swjtuls1987@126.com
30 //
31 // Redistribution and use in source and binary forms, with or without modification,
32 // are permitted provided that the following conditions are met:
33 //
34 //   * Redistribution's of source code must retain the above copyright notice,
35 //     this list of conditions and the following disclaimer.
36 //
37 //   * Redistribution's in binary form must reproduce the above copyright notice,
38 //     this list of conditions and the following disclaimer in the documentation
39 //     and/or other oclMaterials provided with the distribution.
40 //
41 //   * The name of the copyright holders may not be used to endorse or promote products
42 //     derived from this software without specific prior written permission.
43 //
44 // This software is provided by the copyright holders and contributors "as is" and
45 // any express or implied warranties, including, but not limited to, the implied
46 // warranties of merchantability and fitness for a particular purpose are disclaimed.
47 // In no event shall the Intel Corporation or contributors be liable for any direct,
48 // indirect, incidental, special, exemplary, or consequential damages
49 // (including, but not limited to, procurement of substitute goods or services;
50 // loss of use, data, or profits; or business interruption) however caused
51 // and on any theory of liability, whether in contract, strict liability,
52 // or tort (including negligence or otherwise) arising in any way out of
53 // the use of this software, even if advised of the possibility of such damage.
54 //
55 //M*/
56
57 #include "precomp.hpp"
58 #include "opencl_kernels.hpp"
59
60 using namespace cv;
61 using namespace cv::ocl;
62
63 namespace cv
64 {
65     namespace ocl
66     {
67         ////////////////////////////////////OpenCL call wrappers////////////////////////////
68
69         template <typename T> struct index_and_sizeof;
70         template <> struct index_and_sizeof<char>
71         {
72             enum { index = 1 };
73         };
74         template <> struct index_and_sizeof<unsigned char>
75         {
76             enum { index = 2 };
77         };
78         template <> struct index_and_sizeof<short>
79         {
80             enum { index = 3 };
81         };
82         template <> struct index_and_sizeof<unsigned short>
83         {
84             enum { index = 4 };
85         };
86         template <> struct index_and_sizeof<int>
87         {
88             enum { index = 5 };
89         };
90         template <> struct index_and_sizeof<float>
91         {
92             enum { index = 6 };
93         };
94         template <> struct index_and_sizeof<double>
95         {
96             enum { index = 7 };
97         };
98
99         /////////////////////////////////////////////////////////////////////////////////////
100         // threshold
101
102         typedef void (*gpuThresh_t)(const oclMat &src, oclMat &dst, double thresh, double maxVal, int type);
103
104         static void threshold_8u(const oclMat &src, oclMat &dst, double thresh, double maxVal, int type)
105         {
106             uchar thresh_uchar = cvFloor(thresh);
107             uchar max_val = cvRound(maxVal);
108
109             size_t cols = (dst.cols + (dst.offset % 16) + 15) / 16;
110             size_t bSizeX = 16, bSizeY = 16;
111             size_t gSizeX = cols % bSizeX == 0 ? cols : (cols + bSizeX - 1) / bSizeX * bSizeX;
112             size_t gSizeY = dst.rows;
113             size_t globalThreads[3] = {gSizeX, gSizeY, 1};
114             size_t localThreads[3] = {bSizeX, bSizeY, 1};
115
116             std::vector< std::pair<size_t, const void *> > args;
117             args.push_back( std::make_pair(sizeof(cl_mem), &src.data));
118             args.push_back( std::make_pair(sizeof(cl_mem), &dst.data));
119             args.push_back( std::make_pair(sizeof(cl_int), (void *)&src.offset));
120             args.push_back( std::make_pair(sizeof(cl_int), (void *)&src.step));
121             args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst.offset));
122             args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst.rows));
123             args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst.cols));
124             args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst.step));
125             args.push_back( std::make_pair(sizeof(cl_uchar), (void *)&thresh_uchar));
126             args.push_back( std::make_pair(sizeof(cl_uchar), (void *)&max_val));
127             args.push_back( std::make_pair(sizeof(cl_int), (void *)&type));
128             openCLExecuteKernel(src.clCxt, &imgproc_threshold, "threshold", globalThreads, localThreads, args, src.oclchannels(), src.depth());
129         }
130
131         static void threshold_32f(const oclMat &src, oclMat &dst, double thresh, double maxVal, int type)
132         {
133             float thresh_f = thresh;
134             float max_val = maxVal;
135             int dst_offset = (dst.offset >> 2);
136             int dst_step = (dst.step >> 2);
137             int src_offset = (src.offset >> 2);
138             int src_step = (src.step >> 2);
139
140             size_t cols = (dst.cols + (dst_offset & 3) + 3) / 4;
141             size_t bSizeX = 16, bSizeY = 16;
142             size_t gSizeX = cols % bSizeX == 0 ? cols : (cols + bSizeX - 1) / bSizeX * bSizeX;
143             size_t gSizeY = dst.rows;
144             size_t globalThreads[3] = {gSizeX, gSizeY, 1};
145             size_t localThreads[3] = {bSizeX, bSizeY, 1};
146
147             std::vector< std::pair<size_t, const void *> > args;
148             args.push_back( std::make_pair(sizeof(cl_mem), &src.data));
149             args.push_back( std::make_pair(sizeof(cl_mem), &dst.data));
150             args.push_back( std::make_pair(sizeof(cl_int), (void *)&src_offset));
151             args.push_back( std::make_pair(sizeof(cl_int), (void *)&src_step));
152             args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst_offset));
153             args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst.rows));
154             args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst.cols));
155             args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst_step));
156             args.push_back( std::make_pair(sizeof(cl_float), (void *)&thresh_f));
157             args.push_back( std::make_pair(sizeof(cl_float), (void *)&max_val));
158             args.push_back( std::make_pair(sizeof(cl_int), (void *)&type));
159
160             openCLExecuteKernel(src.clCxt, &imgproc_threshold, "threshold", globalThreads, localThreads, args, src.oclchannels(), src.depth());
161         }
162
163         // threshold: support 8UC1 and 32FC1 data type and five threshold type
164         double threshold(const oclMat &src, oclMat &dst, double thresh, double maxVal, int type)
165         {
166             //TODO: These limitations shall be removed later.
167             CV_Assert(src.type() == CV_8UC1 || src.type() == CV_32FC1);
168             CV_Assert(type == THRESH_BINARY || type == THRESH_BINARY_INV || type == THRESH_TRUNC
169                       || type == THRESH_TOZERO || type == THRESH_TOZERO_INV );
170
171             static const gpuThresh_t gpuThresh_callers[2] = {threshold_8u, threshold_32f};
172
173             dst.create( src.size(), src.type() );
174             gpuThresh_callers[(src.type() == CV_32FC1)](src, dst, thresh, maxVal, type);
175
176             return thresh;
177         }
178
179         ////////////////////////////////////////////////////////////////////////////////////////////
180         ///////////////////////////////   remap   //////////////////////////////////////////////////
181         ////////////////////////////////////////////////////////////////////////////////////////////
182
183         void remap( const oclMat &src, oclMat &dst, oclMat &map1, oclMat &map2, int interpolation, int borderType, const Scalar &borderValue )
184         {
185             Context *clCxt = src.clCxt;
186             CV_Assert(interpolation == INTER_LINEAR || interpolation == INTER_NEAREST
187                       || interpolation == INTER_CUBIC || interpolation == INTER_LANCZOS4);
188             CV_Assert((map1.type() == CV_16SC2 && !map2.data) || (map1.type() == CV_32FC2 && !map2.data) || (map1.type() == CV_32FC1 && map2.type() == CV_32FC1));
189             CV_Assert(!map2.data || map2.size() == map1.size());
190             CV_Assert(dst.size() == map1.size());
191
192             dst.create(map1.size(), src.type());
193
194             String kernelName;
195
196             if ( map1.type() == CV_32FC2 && !map2.data )
197             {
198                 if (interpolation == INTER_LINEAR && borderType == BORDER_CONSTANT)
199                     kernelName = "remapLNFConstant";
200                 else if (interpolation == INTER_NEAREST && borderType == BORDER_CONSTANT)
201                     kernelName = "remapNNFConstant";
202             }
203             else if (map1.type() == CV_16SC2 && !map2.data)
204             {
205                 if (interpolation == INTER_LINEAR && borderType == BORDER_CONSTANT)
206                     kernelName = "remapLNSConstant";
207                 else if (interpolation == INTER_NEAREST && borderType == BORDER_CONSTANT)
208                     kernelName = "remapNNSConstant";
209
210             }
211             else if (map1.type() == CV_32FC1 && map2.type() == CV_32FC1)
212             {
213                 if (interpolation == INTER_LINEAR && borderType == BORDER_CONSTANT)
214                     kernelName = "remapLNF1Constant";
215                 else if (interpolation == INTER_NEAREST && borderType == BORDER_CONSTANT)
216                     kernelName = "remapNNF1Constant";
217             }
218
219             size_t blkSizeX = 16, blkSizeY = 16;
220             size_t glbSizeX;
221             int cols = dst.cols;
222             if (src.type() == CV_8UC1)
223             {
224                 cols = (dst.cols + dst.offset % 4 + 3) / 4;
225                 glbSizeX = cols % blkSizeX == 0 ? cols : (cols / blkSizeX + 1) * blkSizeX;
226
227             }
228             else if (src.type() == CV_32FC1 && interpolation == INTER_LINEAR)
229             {
230                 cols = (dst.cols + (dst.offset >> 2) % 4 + 3) / 4;
231                 glbSizeX = cols % blkSizeX == 0 ? cols : (cols / blkSizeX + 1) * blkSizeX;
232             }
233             else
234                 glbSizeX = dst.cols % blkSizeX == 0 ? dst.cols : (dst.cols / blkSizeX + 1) * blkSizeX;
235
236             size_t glbSizeY = dst.rows % blkSizeY == 0 ? dst.rows : (dst.rows / blkSizeY + 1) * blkSizeY;
237             size_t globalThreads[3] = {glbSizeX, glbSizeY, 1};
238             size_t localThreads[3] = {blkSizeX, blkSizeY, 1};
239
240             float borderFloat[4] = {(float)borderValue[0], (float)borderValue[1], (float)borderValue[2], (float)borderValue[3]};
241             std::vector< std::pair<size_t, const void *> > args;
242             if (map1.channels() == 2)
243             {
244                 args.push_back( std::make_pair(sizeof(cl_mem), (void *)&dst.data));
245                 args.push_back( std::make_pair(sizeof(cl_mem), (void *)&src.data));
246                 args.push_back( std::make_pair(sizeof(cl_mem), (void *)&map1.data));
247                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst.offset));
248                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&src.offset));
249                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&map1.offset));
250                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst.step));
251                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&src.step));
252                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&map1.step));
253                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&src.cols));
254                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&src.rows));
255                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst.cols));
256                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst.rows));
257                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&map1.cols));
258                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&map1.rows));
259                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&cols));
260                 float borderFloat[4] = {(float)borderValue[0], (float)borderValue[1], (float)borderValue[2], (float)borderValue[3]};
261
262                 if (src.clCxt->supportsFeature(FEATURE_CL_DOUBLE))
263                     args.push_back( std::make_pair(sizeof(cl_double4), (void *)&borderValue));
264                 else
265                     args.push_back( std::make_pair(sizeof(cl_float4), (void *)&borderFloat));
266             }
267             if (map1.channels() == 1)
268             {
269                 args.push_back( std::make_pair(sizeof(cl_mem), (void *)&dst.data));
270                 args.push_back( std::make_pair(sizeof(cl_mem), (void *)&src.data));
271                 args.push_back( std::make_pair(sizeof(cl_mem), (void *)&map1.data));
272                 args.push_back( std::make_pair(sizeof(cl_mem), (void *)&map2.data));
273                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst.offset));
274                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&src.offset));
275                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&map1.offset));
276                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst.step));
277                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&src.step));
278                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&map1.step));
279                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&src.cols));
280                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&src.rows));
281                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst.cols));
282                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst.rows));
283                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&map1.cols));
284                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&map1.rows));
285                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&cols));
286                 if (src.clCxt->supportsFeature(FEATURE_CL_DOUBLE))
287                     args.push_back( std::make_pair(sizeof(cl_double4), (void *)&borderValue));
288                 else
289                     args.push_back( std::make_pair(sizeof(cl_float4), (void *)&borderFloat));
290             }
291             openCLExecuteKernel(clCxt, &imgproc_remap, kernelName, globalThreads, localThreads, args, src.oclchannels(), src.depth());
292         }
293
294         ////////////////////////////////////////////////////////////////////////////////////////////
295         // resize
296
297         static void resize_gpu( const oclMat &src, oclMat &dst, double fx, double fy, int interpolation)
298         {
299             CV_Assert( (src.channels() == dst.channels()) );
300             Context *clCxt = src.clCxt;
301             float ifx = 1. / fx;
302             float ify = 1. / fy;
303             double ifx_d = 1. / fx;
304             double ify_d = 1. / fy;
305             int srcStep_in_pixel = src.step1() / src.oclchannels();
306             int srcoffset_in_pixel = src.offset / src.elemSize();
307             int dstStep_in_pixel = dst.step1() / dst.oclchannels();
308             int dstoffset_in_pixel = dst.offset / dst.elemSize();
309
310             String kernelName;
311             if (interpolation == INTER_LINEAR)
312                 kernelName = "resizeLN";
313             else if (interpolation == INTER_NEAREST)
314                 kernelName = "resizeNN";
315
316             //TODO: improve this kernel
317             size_t blkSizeX = 16, blkSizeY = 16;
318             size_t glbSizeX;
319             if (src.type() == CV_8UC1)
320             {
321                 size_t cols = (dst.cols + dst.offset % 4 + 3) / 4;
322                 glbSizeX = cols % blkSizeX == 0 && cols != 0 ? cols : (cols / blkSizeX + 1) * blkSizeX;
323             }
324             else
325                 glbSizeX = dst.cols % blkSizeX == 0 && dst.cols != 0 ? dst.cols : (dst.cols / blkSizeX + 1) * blkSizeX;
326
327             size_t glbSizeY = dst.rows % blkSizeY == 0 && dst.rows != 0 ? dst.rows : (dst.rows / blkSizeY + 1) * blkSizeY;
328             size_t globalThreads[3] = {glbSizeX, glbSizeY, 1};
329             size_t localThreads[3] = {blkSizeX, blkSizeY, 1};
330
331             std::vector< std::pair<size_t, const void *> > args;
332             if (interpolation == INTER_NEAREST)
333             {
334                 args.push_back( std::make_pair(sizeof(cl_mem), (void *)&dst.data));
335                 args.push_back( std::make_pair(sizeof(cl_mem), (void *)&src.data));
336                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&dstoffset_in_pixel));
337                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&srcoffset_in_pixel));
338                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&dstStep_in_pixel));
339                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&srcStep_in_pixel));
340                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&src.cols));
341                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&src.rows));
342                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst.cols));
343                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst.rows));
344                 if (src.clCxt->supportsFeature(FEATURE_CL_DOUBLE))
345                 {
346                     args.push_back( std::make_pair(sizeof(cl_double), (void *)&ifx_d));
347                     args.push_back( std::make_pair(sizeof(cl_double), (void *)&ify_d));
348                 }
349                 else
350                 {
351                     args.push_back( std::make_pair(sizeof(cl_float), (void *)&ifx));
352                     args.push_back( std::make_pair(sizeof(cl_float), (void *)&ify));
353                 }
354             }
355             else
356             {
357                 args.push_back( std::make_pair(sizeof(cl_mem), (void *)&dst.data));
358                 args.push_back( std::make_pair(sizeof(cl_mem), (void *)&src.data));
359                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&dstoffset_in_pixel));
360                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&srcoffset_in_pixel));
361                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&dstStep_in_pixel));
362                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&srcStep_in_pixel));
363                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&src.cols));
364                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&src.rows));
365                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst.cols));
366                 args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst.rows));
367                 args.push_back( std::make_pair(sizeof(cl_float), (void *)&ifx));
368                 args.push_back( std::make_pair(sizeof(cl_float), (void *)&ify));
369             }
370
371             openCLExecuteKernel(clCxt, &imgproc_resize, kernelName, globalThreads, localThreads, args, src.oclchannels(), src.depth());
372         }
373
374         void resize(const oclMat &src, oclMat &dst, Size dsize,
375                     double fx, double fy, int interpolation)
376         {
377             CV_Assert(src.type() == CV_8UC1 || src.type() == CV_8UC3 || src.type() == CV_8UC4
378                       || src.type() == CV_32FC1 || src.type() == CV_32FC3 || src.type() == CV_32FC4);
379             CV_Assert(interpolation == INTER_LINEAR || interpolation == INTER_NEAREST);
380             CV_Assert( src.size().area() > 0 );
381             CV_Assert( !(dsize == Size()) || (fx > 0 && fy > 0) );
382
383             if (!(dsize == Size()) && (fx > 0 && fy > 0))
384                 if (dsize.width != (int)(src.cols * fx) || dsize.height != (int)(src.rows * fy))
385                     CV_Error(Error::StsUnmatchedSizes, "invalid dsize and fx, fy!");
386
387             if ( dsize == Size() )
388                 dsize = Size(saturate_cast<int>(src.cols * fx), saturate_cast<int>(src.rows * fy));
389             else
390             {
391                 fx = (double)dsize.width / src.cols;
392                 fy = (double)dsize.height / src.rows;
393             }
394
395             dst.create(dsize, src.type());
396
397             if ( interpolation == INTER_NEAREST || interpolation == INTER_LINEAR )
398             {
399                 resize_gpu( src, dst, fx, fy, interpolation);
400                 return;
401             }
402
403             CV_Error(Error::StsUnsupportedFormat, "Non-supported interpolation method");
404         }
405
406         ////////////////////////////////////////////////////////////////////////
407         // medianFilter
408
409         void medianFilter(const oclMat &src, oclMat &dst, int m)
410         {
411             CV_Assert( m % 2 == 1 && m > 1 );
412             CV_Assert( m <= 5 || src.depth() == CV_8U );
413             CV_Assert( src.cols <= dst.cols && src.rows <= dst.rows );
414
415             if (src.data == dst.data)
416             {
417                 oclMat src1;
418                 src.copyTo(src1);
419                 return medianFilter(src1, dst, m);
420             }
421
422             int srcStep = src.step1() / src.oclchannels();
423             int dstStep = dst.step1() / dst.oclchannels();
424             int srcOffset = src.offset / src.oclchannels() / src.elemSize1();
425             int dstOffset = dst.offset / dst.oclchannels() / dst.elemSize1();
426
427             Context *clCxt = src.clCxt;
428
429             std::vector< std::pair<size_t, const void *> > args;
430             args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src.data));
431             args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst.data));
432             args.push_back( std::make_pair( sizeof(cl_int), (void *)&srcOffset));
433             args.push_back( std::make_pair( sizeof(cl_int), (void *)&dstOffset));
434             args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.cols));
435             args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.rows));
436             args.push_back( std::make_pair( sizeof(cl_int), (void *)&srcStep));
437             args.push_back( std::make_pair( sizeof(cl_int), (void *)&dstStep));
438
439             size_t globalThreads[3] = {(src.cols + 18) / 16 * 16, (src.rows + 15) / 16 * 16, 1};
440             size_t localThreads[3] = {16, 16, 1};
441
442             if (m == 3)
443             {
444                 String kernelName = "medianFilter3";
445                 openCLExecuteKernel(clCxt, &imgproc_median, kernelName, globalThreads, localThreads, args, src.oclchannels(), src.depth());
446             }
447             else if (m == 5)
448             {
449                 String kernelName = "medianFilter5";
450                 openCLExecuteKernel(clCxt, &imgproc_median, kernelName, globalThreads, localThreads, args, src.oclchannels(), src.depth());
451             }
452             else
453                 CV_Error(Error::StsBadArg, "Non-supported filter length");
454         }
455
456         ////////////////////////////////////////////////////////////////////////
457         // copyMakeBorder
458
459         void copyMakeBorder(const oclMat &src, oclMat &dst, int top, int bottom, int left, int right, int bordertype, const Scalar &scalar)
460         {
461             CV_Assert(top >= 0 && bottom >= 0 && left >= 0 && right >= 0);
462             if ((dst.cols != dst.wholecols) || (dst.rows != dst.wholerows)) //has roi
463             {
464                 if (((bordertype & cv::BORDER_ISOLATED) == 0) &&
465                         (bordertype != cv::BORDER_CONSTANT) &&
466                         (bordertype != cv::BORDER_REPLICATE))
467                 {
468                     CV_Error(Error::StsBadArg, "Unsupported border type");
469                 }
470             }
471
472             bordertype &= ~cv::BORDER_ISOLATED;
473             if (bordertype == cv::BORDER_REFLECT || bordertype == cv::BORDER_WRAP)
474             {
475                 CV_Assert((src.cols >= left) && (src.cols >= right) && (src.rows >= top) && (src.rows >= bottom));
476             }
477             else if (bordertype == cv::BORDER_REFLECT_101)
478             {
479                 CV_Assert((src.cols > left) && (src.cols > right) && (src.rows > top) && (src.rows > bottom));
480             }
481
482             dst.create(src.rows + top + bottom, src.cols + left + right, src.type());
483             int srcStep = src.step1() / src.oclchannels(),  dstStep = dst.step1() / dst.oclchannels();
484             int srcOffset = src.offset / src.elemSize(), dstOffset = dst.offset / dst.elemSize();
485             int depth = src.depth(), ochannels = src.oclchannels();
486
487             int __bordertype[] = {cv::BORDER_CONSTANT, cv::BORDER_REPLICATE, BORDER_REFLECT, BORDER_WRAP, BORDER_REFLECT_101};
488             const char *borderstr[] = {"BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", "BORDER_WRAP", "BORDER_REFLECT_101"};
489             size_t bordertype_index;
490
491             for(bordertype_index = 0; bordertype_index < sizeof(__bordertype) / sizeof(int); bordertype_index++)
492                 if (__bordertype[bordertype_index] == bordertype)
493                     break;
494
495             if (bordertype_index == sizeof(__bordertype) / sizeof(int))
496                 CV_Error(Error::StsBadArg, "unsupported border type");
497
498             String kernelName = "copymakeborder";
499             size_t localThreads[3] = {16, 16, 1};
500             size_t globalThreads[3] = { dst.cols, dst.rows, 1 };
501
502             std::vector< std::pair<size_t, const void *> > args;
503             args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src.data));
504             args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst.data));
505             args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.cols));
506             args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.rows));
507             args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.cols));
508             args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.rows));
509             args.push_back( std::make_pair( sizeof(cl_int), (void *)&srcStep));
510             args.push_back( std::make_pair( sizeof(cl_int), (void *)&srcOffset));
511             args.push_back( std::make_pair( sizeof(cl_int), (void *)&dstStep));
512             args.push_back( std::make_pair( sizeof(cl_int), (void *)&dstOffset));
513             args.push_back( std::make_pair( sizeof(cl_int), (void *)&top));
514             args.push_back( std::make_pair( sizeof(cl_int), (void *)&left));
515
516             const char * const typeMap[] = { "uchar", "char", "ushort", "short", "int", "float", "double" };
517             const char * const channelMap[] = { "", "", "2", "4", "4" };
518             std::string buildOptions = format("-D GENTYPE=%s%s -D %s",
519                                               typeMap[depth], channelMap[ochannels],
520                                               borderstr[bordertype_index]);
521
522             if (src.type() == CV_8UC1 && (dst.offset & 3) == 0 && (dst.cols & 3) == 0)
523             {
524                 kernelName = "copymakeborder_C1_D0";
525                 globalThreads[0] = dst.cols >> 2;
526             }
527
528             int cn = src.channels(), ocn = src.oclchannels();
529             int bufSize = src.elemSize1() * ocn;
530             AutoBuffer<uchar> _buf(bufSize);
531             uchar * buf = (uchar *)_buf;
532             scalarToRawData(scalar, buf, dst.type());
533             memset(buf + src.elemSize1() * cn, 0, (ocn - cn) * src.elemSize1());
534
535             args.push_back( std::make_pair( bufSize , (void *)buf ));
536
537             openCLExecuteKernel(src.clCxt, &imgproc_copymakeboder, kernelName, globalThreads,
538                                 localThreads, args, -1, -1, buildOptions.c_str());
539         }
540
541         ////////////////////////////////////////////////////////////////////////
542         // warp
543
544         namespace
545         {
546 #define F double
547
548             void convert_coeffs(F *M)
549             {
550                 double D = M[0] * M[4] - M[1] * M[3];
551                 D = D != 0 ? 1. / D : 0;
552                 double A11 = M[4] * D, A22 = M[0] * D;
553                 M[0] = A11;
554                 M[1] *= -D;
555                 M[3] *= -D;
556                 M[4] = A22;
557                 double b1 = -M[0] * M[2] - M[1] * M[5];
558                 double b2 = -M[3] * M[2] - M[4] * M[5];
559                 M[2] = b1;
560                 M[5] = b2;
561             }
562
563             double invert(double *M)
564             {
565 #define Sd(y,x) (Sd[y*3+x])
566 #define Dd(y,x) (Dd[y*3+x])
567 #define det3(m)    (m(0,0)*(m(1,1)*m(2,2) - m(1,2)*m(2,1)) -  \
568                     m(0,1)*(m(1,0)*m(2,2) - m(1,2)*m(2,0)) +  \
569                     m(0,2)*(m(1,0)*m(2,1) - m(1,1)*m(2,0)))
570                 double *Sd = M;
571                 double *Dd = M;
572                 double d = det3(Sd);
573                 double result = 0;
574                 if ( d != 0)
575                 {
576                     double t[9];
577                     result = d;
578                     d = 1. / d;
579
580                     t[0] = (Sd(1, 1) * Sd(2, 2) - Sd(1, 2) * Sd(2, 1)) * d;
581                     t[1] = (Sd(0, 2) * Sd(2, 1) - Sd(0, 1) * Sd(2, 2)) * d;
582                     t[2] = (Sd(0, 1) * Sd(1, 2) - Sd(0, 2) * Sd(1, 1)) * d;
583
584                     t[3] = (Sd(1, 2) * Sd(2, 0) - Sd(1, 0) * Sd(2, 2)) * d;
585                     t[4] = (Sd(0, 0) * Sd(2, 2) - Sd(0, 2) * Sd(2, 0)) * d;
586                     t[5] = (Sd(0, 2) * Sd(1, 0) - Sd(0, 0) * Sd(1, 2)) * d;
587
588                     t[6] = (Sd(1, 0) * Sd(2, 1) - Sd(1, 1) * Sd(2, 0)) * d;
589                     t[7] = (Sd(0, 1) * Sd(2, 0) - Sd(0, 0) * Sd(2, 1)) * d;
590                     t[8] = (Sd(0, 0) * Sd(1, 1) - Sd(0, 1) * Sd(1, 0)) * d;
591
592                     Dd(0, 0) = t[0];
593                     Dd(0, 1) = t[1];
594                     Dd(0, 2) = t[2];
595                     Dd(1, 0) = t[3];
596                     Dd(1, 1) = t[4];
597                     Dd(1, 2) = t[5];
598                     Dd(2, 0) = t[6];
599                     Dd(2, 1) = t[7];
600                     Dd(2, 2) = t[8];
601                 }
602                 return result;
603             }
604
605             void warpAffine_gpu(const oclMat &src, oclMat &dst, F coeffs[2][3], int interpolation)
606             {
607                 CV_Assert( (src.oclchannels() == dst.oclchannels()) );
608                 int srcStep = src.step1();
609                 int dstStep = dst.step1();
610                 float float_coeffs[2][3];
611                 cl_mem coeffs_cm;
612
613                 Context *clCxt = src.clCxt;
614                 String s[3] = {"NN", "Linear", "Cubic"};
615                 String kernelName = "warpAffine" + s[interpolation];
616
617                 if (src.clCxt->supportsFeature(FEATURE_CL_DOUBLE))
618                 {
619                     cl_int st;
620                     coeffs_cm = clCreateBuffer(*(cl_context*)clCxt->getOpenCLContextPtr(), CL_MEM_READ_WRITE, sizeof(F) * 2 * 3, NULL, &st );
621                     openCLVerifyCall(st);
622                     openCLSafeCall(clEnqueueWriteBuffer(*(cl_command_queue*)clCxt->getOpenCLCommandQueuePtr(), (cl_mem)coeffs_cm, 1, 0,
623                                                         sizeof(F) * 2 * 3, coeffs, 0, 0, 0));
624                 }
625                 else
626                 {
627                     cl_int st;
628                     for(int m = 0; m < 2; m++)
629                         for(int n = 0; n < 3; n++)
630                             float_coeffs[m][n] = coeffs[m][n];
631
632                     coeffs_cm = clCreateBuffer(*(cl_context*)clCxt->getOpenCLContextPtr(), CL_MEM_READ_WRITE, sizeof(float) * 2 * 3, NULL, &st );
633                     openCLSafeCall(clEnqueueWriteBuffer(*(cl_command_queue*)clCxt->getOpenCLCommandQueuePtr(), (cl_mem)coeffs_cm,
634                                                         1, 0, sizeof(float) * 2 * 3, float_coeffs, 0, 0, 0));
635
636                 }
637                 //TODO: improve this kernel
638                 size_t blkSizeX = 16, blkSizeY = 16;
639                 size_t glbSizeX;
640                 size_t cols;
641
642                 if (src.type() == CV_8UC1 && interpolation != 2)
643                 {
644                     cols = (dst.cols + dst.offset % 4 + 3) / 4;
645                     glbSizeX = cols % blkSizeX == 0 ? cols : (cols / blkSizeX + 1) * blkSizeX;
646                 }
647                 else
648                 {
649                     cols = dst.cols;
650                     glbSizeX = dst.cols % blkSizeX == 0 ? dst.cols : (dst.cols / blkSizeX + 1) * blkSizeX;
651                 }
652
653                 size_t glbSizeY = dst.rows % blkSizeY == 0 ? dst.rows : (dst.rows / blkSizeY + 1) * blkSizeY;
654                 size_t globalThreads[3] = {glbSizeX, glbSizeY, 1};
655                 size_t localThreads[3] = {blkSizeX, blkSizeY, 1};
656
657                 std::vector< std::pair<size_t, const void *> > args;
658
659                 args.push_back(std::make_pair(sizeof(cl_mem), (void *)&src.data));
660                 args.push_back(std::make_pair(sizeof(cl_mem), (void *)&dst.data));
661                 args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.cols));
662                 args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.rows));
663                 args.push_back(std::make_pair(sizeof(cl_int), (void *)&dst.cols));
664                 args.push_back(std::make_pair(sizeof(cl_int), (void *)&dst.rows));
665                 args.push_back(std::make_pair(sizeof(cl_int), (void *)&srcStep));
666                 args.push_back(std::make_pair(sizeof(cl_int), (void *)&dstStep));
667                 args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.offset));
668                 args.push_back(std::make_pair(sizeof(cl_int), (void *)&dst.offset));
669                 args.push_back(std::make_pair(sizeof(cl_mem), (void *)&coeffs_cm));
670                 args.push_back(std::make_pair(sizeof(cl_int), (void *)&cols));
671
672                 openCLExecuteKernel(clCxt, &imgproc_warpAffine, kernelName, globalThreads, localThreads, args, src.oclchannels(), src.depth());
673                 openCLSafeCall(clReleaseMemObject(coeffs_cm));
674             }
675
676             void warpPerspective_gpu(const oclMat &src, oclMat &dst, double coeffs[3][3], int interpolation)
677             {
678                 CV_Assert( (src.oclchannels() == dst.oclchannels()) );
679                 int srcStep = src.step1();
680                 int dstStep = dst.step1();
681                 float float_coeffs[3][3];
682                 cl_mem coeffs_cm;
683
684                 Context *clCxt = src.clCxt;
685                 String s[3] = {"NN", "Linear", "Cubic"};
686                 String kernelName = "warpPerspective" + s[interpolation];
687
688                 if (src.clCxt->supportsFeature(FEATURE_CL_DOUBLE))
689                 {
690                     cl_int st;
691                     coeffs_cm = clCreateBuffer(*(cl_context*)clCxt->getOpenCLContextPtr(), CL_MEM_READ_WRITE, sizeof(double) * 3 * 3, NULL, &st );
692                     openCLVerifyCall(st);
693                     openCLSafeCall(clEnqueueWriteBuffer(*(cl_command_queue*)clCxt->getOpenCLCommandQueuePtr(), (cl_mem)coeffs_cm, 1, 0,
694                                                         sizeof(double) * 3 * 3, coeffs, 0, 0, 0));
695                 }
696                 else
697                 {
698                     cl_int st;
699                     for(int m = 0; m < 3; m++)
700                         for(int n = 0; n < 3; n++)
701                             float_coeffs[m][n] = coeffs[m][n];
702
703                     coeffs_cm = clCreateBuffer(*(cl_context*)clCxt->getOpenCLContextPtr(), CL_MEM_READ_WRITE, sizeof(float) * 3 * 3, NULL, &st );
704                     openCLVerifyCall(st);
705                     openCLSafeCall(clEnqueueWriteBuffer(*(cl_command_queue*)clCxt->getOpenCLCommandQueuePtr(), (cl_mem)coeffs_cm, 1, 0,
706                                                         sizeof(float) * 3 * 3, float_coeffs, 0, 0, 0));
707                 }
708
709                 //TODO: improve this kernel
710                 size_t blkSizeX = 16, blkSizeY = 16;
711                 size_t glbSizeX;
712                 size_t cols;
713                 if (src.type() == CV_8UC1 && interpolation == 0)
714                 {
715                     cols = (dst.cols + dst.offset % 4 + 3) / 4;
716                     glbSizeX = cols % blkSizeX == 0 ? cols : (cols / blkSizeX + 1) * blkSizeX;
717                 }
718                 else
719                 {
720                     cols = dst.cols;
721                     glbSizeX = dst.cols % blkSizeX == 0 ? dst.cols : (dst.cols / blkSizeX + 1) * blkSizeX;
722                 }
723
724                 size_t glbSizeY = dst.rows % blkSizeY == 0 ? dst.rows : (dst.rows / blkSizeY + 1) * blkSizeY;
725                 size_t globalThreads[3] = {glbSizeX, glbSizeY, 1};
726                 size_t localThreads[3] = {blkSizeX, blkSizeY, 1};
727
728                 std::vector< std::pair<size_t, const void *> > args;
729
730                 args.push_back(std::make_pair(sizeof(cl_mem), (void *)&src.data));
731                 args.push_back(std::make_pair(sizeof(cl_mem), (void *)&dst.data));
732                 args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.cols));
733                 args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.rows));
734                 args.push_back(std::make_pair(sizeof(cl_int), (void *)&dst.cols));
735                 args.push_back(std::make_pair(sizeof(cl_int), (void *)&dst.rows));
736                 args.push_back(std::make_pair(sizeof(cl_int), (void *)&srcStep));
737                 args.push_back(std::make_pair(sizeof(cl_int), (void *)&dstStep));
738                 args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.offset));
739                 args.push_back(std::make_pair(sizeof(cl_int), (void *)&dst.offset));
740                 args.push_back(std::make_pair(sizeof(cl_mem), (void *)&coeffs_cm));
741                 args.push_back(std::make_pair(sizeof(cl_int), (void *)&cols));
742
743                 openCLExecuteKernel(clCxt, &imgproc_warpPerspective, kernelName, globalThreads, localThreads, args, src.oclchannels(), src.depth());
744                 openCLSafeCall(clReleaseMemObject(coeffs_cm));
745             }
746         }
747
748         void warpAffine(const oclMat &src, oclMat &dst, const Mat &M, Size dsize, int flags)
749         {
750             int interpolation = flags & INTER_MAX;
751
752             CV_Assert((src.depth() == CV_8U  || src.depth() == CV_32F) && src.oclchannels() != 2 && src.oclchannels() != 3);
753             CV_Assert(interpolation == INTER_NEAREST || interpolation == INTER_LINEAR || interpolation == INTER_CUBIC);
754
755             dst.create(dsize, src.type());
756
757             CV_Assert(M.rows == 2 && M.cols == 3);
758
759             int warpInd = (flags & WARP_INVERSE_MAP) >> 4;
760             F coeffs[2][3];
761
762             double coeffsM[2*3];
763             Mat coeffsMat(2, 3, CV_64F, (void *)coeffsM);
764             M.convertTo(coeffsMat, coeffsMat.type());
765             if (!warpInd)
766                 convert_coeffs(coeffsM);
767
768             for(int i = 0; i < 2; ++i)
769                 for(int j = 0; j < 3; ++j)
770                     coeffs[i][j] = coeffsM[i*3+j];
771
772             warpAffine_gpu(src, dst, coeffs, interpolation);
773         }
774
775         void warpPerspective(const oclMat &src, oclMat &dst, const Mat &M, Size dsize, int flags)
776         {
777             int interpolation = flags & INTER_MAX;
778
779             CV_Assert((src.depth() == CV_8U  || src.depth() == CV_32F) && src.oclchannels() != 2 && src.oclchannels() != 3);
780             CV_Assert(interpolation == INTER_NEAREST || interpolation == INTER_LINEAR || interpolation == INTER_CUBIC);
781
782             dst.create(dsize, src.type());
783
784
785             CV_Assert(M.rows == 3 && M.cols == 3);
786
787             int warpInd = (flags & WARP_INVERSE_MAP) >> 4;
788             double coeffs[3][3];
789
790             double coeffsM[3*3];
791             Mat coeffsMat(3, 3, CV_64F, (void *)coeffsM);
792             M.convertTo(coeffsMat, coeffsMat.type());
793             if (!warpInd)
794                 invert(coeffsM);
795
796             for(int i = 0; i < 3; ++i)
797                 for(int j = 0; j < 3; ++j)
798                     coeffs[i][j] = coeffsM[i*3+j];
799
800             warpPerspective_gpu(src, dst, coeffs, interpolation);
801         }
802
803         ////////////////////////////////////////////////////////////////////////
804         // integral
805
806         void integral(const oclMat &src, oclMat &sum, oclMat &sqsum)
807         {
808             CV_Assert(src.type() == CV_8UC1);
809             if (!src.clCxt->supportsFeature(ocl::FEATURE_CL_DOUBLE) && src.depth() == CV_64F)
810             {
811                 CV_Error(Error::OpenCLDoubleNotSupported, "Select device doesn't support double");
812                 return;
813             }
814
815             int vlen = 4;
816             int offset = src.offset / vlen;
817             int pre_invalid = src.offset % vlen;
818             int vcols = (pre_invalid + src.cols + vlen - 1) / vlen;
819
820             oclMat t_sum , t_sqsum;
821             int w = src.cols + 1, h = src.rows + 1;
822             int depth = src.depth() == CV_8U ? CV_32S : CV_64F;
823             int type = CV_MAKE_TYPE(depth, 1);
824
825             t_sum.create(src.cols, src.rows, type);
826             sum.create(h, w, type);
827
828             t_sqsum.create(src.cols, src.rows, CV_32FC1);
829             sqsum.create(h, w, CV_32FC1);
830
831             int sum_offset = sum.offset / vlen;
832             int sqsum_offset = sqsum.offset / vlen;
833
834             std::vector<std::pair<size_t , const void *> > args;
835             args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&src.data ));
836             args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&t_sum.data ));
837             args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&t_sqsum.data ));
838             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&offset ));
839             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&pre_invalid ));
840             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.rows ));
841             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.cols ));
842             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.step ));
843             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&t_sum.step));
844             size_t gt[3] = {((vcols + 1) / 2) * 256, 1, 1}, lt[3] = {256, 1, 1};
845             openCLExecuteKernel(src.clCxt, &imgproc_integral, "integral_cols", gt, lt, args, -1, depth);
846
847             args.clear();
848             args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&t_sum.data ));
849             args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&t_sqsum.data ));
850             args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&sum.data ));
851             args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&sqsum.data ));
852             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&t_sum.rows ));
853             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&t_sum.cols ));
854             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&t_sum.step ));
855             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&sum.step));
856             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&sqsum.step));
857             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&sum_offset));
858             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&sqsum_offset));
859             size_t gt2[3] = {t_sum.cols  * 32, 1, 1}, lt2[3] = {256, 1, 1};
860             openCLExecuteKernel(src.clCxt, &imgproc_integral, "integral_rows", gt2, lt2, args, -1, depth);
861         }
862
863         void integral(const oclMat &src, oclMat &sum)
864         {
865             CV_Assert(src.type() == CV_8UC1);
866             int vlen = 4;
867             int offset = src.offset / vlen;
868             int pre_invalid = src.offset % vlen;
869             int vcols = (pre_invalid + src.cols + vlen - 1) / vlen;
870
871             oclMat t_sum;
872             int w = src.cols + 1, h = src.rows + 1;
873             int depth = src.depth() == CV_8U ? CV_32S : CV_32F;
874             int type = CV_MAKE_TYPE(depth, 1);
875
876             t_sum.create(src.cols, src.rows, type);
877             sum.create(h, w, type);
878
879             int sum_offset = sum.offset / vlen;
880             std::vector<std::pair<size_t , const void *> > args;
881             args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&src.data ));
882             args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&t_sum.data ));
883             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&offset ));
884             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&pre_invalid ));
885             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.rows ));
886             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.cols ));
887             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.step ));
888             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&t_sum.step));
889             size_t gt[3] = {((vcols + 1) / 2) * 256, 1, 1}, lt[3] = {256, 1, 1};
890             openCLExecuteKernel(src.clCxt, &imgproc_integral_sum, "integral_sum_cols", gt, lt, args, -1, depth);
891
892             args.clear();
893             args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&t_sum.data ));
894             args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&sum.data ));
895             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&t_sum.rows ));
896             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&t_sum.cols ));
897             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&t_sum.step ));
898             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&sum.step));
899             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&sum_offset));
900             size_t gt2[3] = {t_sum.cols  * 32, 1, 1}, lt2[3] = {256, 1, 1};
901             openCLExecuteKernel(src.clCxt, &imgproc_integral_sum, "integral_sum_rows", gt2, lt2, args, -1, depth);
902         }
903
904         /////////////////////// corner //////////////////////////////
905
906         static void extractCovData(const oclMat &src, oclMat &Dx, oclMat &Dy,
907                             int blockSize, int ksize, int borderType)
908         {
909             CV_Assert(src.type() == CV_8UC1 || src.type() == CV_32FC1);
910             double scale = static_cast<double>(1 << ((ksize > 0 ? ksize : 3) - 1)) * blockSize;
911             if (ksize < 0)
912                 scale *= 2.;
913
914             if (src.depth() == CV_8U)
915             {
916                 scale *= 255.;
917                 scale = 1. / scale;
918             }
919             else
920                 scale = 1. / scale;
921
922             if (ksize > 0)
923             {
924                 Sobel(src, Dx, CV_32F, 1, 0, ksize, scale, 0, borderType);
925                 Sobel(src, Dy, CV_32F, 0, 1, ksize, scale, 0, borderType);
926             }
927             else
928             {
929                 Scharr(src, Dx, CV_32F, 1, 0, scale, 0, borderType);
930                 Scharr(src, Dy, CV_32F, 0, 1, scale, 0, borderType);
931             }
932             CV_Assert(Dx.offset == 0 && Dy.offset == 0);
933         }
934
935         static void corner_ocl(const cv::ocl::ProgramEntry* source, String kernelName, int block_size, float k, oclMat &Dx, oclMat &Dy,
936                         oclMat &dst, int border_type)
937         {
938             char borderType[30];
939             switch (border_type)
940             {
941             case cv::BORDER_CONSTANT:
942                 sprintf(borderType, "BORDER_CONSTANT");
943                 break;
944             case cv::BORDER_REFLECT101:
945                 sprintf(borderType, "BORDER_REFLECT101");
946                 break;
947             case cv::BORDER_REFLECT:
948                 sprintf(borderType, "BORDER_REFLECT");
949                 break;
950             case cv::BORDER_REPLICATE:
951                 sprintf(borderType, "BORDER_REPLICATE");
952                 break;
953             default:
954                 CV_Error(Error::StsBadFlag, "BORDER type is not supported!");
955             }
956
957             std::string buildOptions = format("-D anX=%d -D anY=%d -D ksX=%d -D ksY=%d -D %s",
958                     block_size / 2, block_size / 2, block_size, block_size, borderType);
959
960             size_t blockSizeX = 256, blockSizeY = 1;
961             size_t gSize = blockSizeX - block_size / 2 * 2;
962             size_t globalSizeX = (Dx.cols) % gSize == 0 ? Dx.cols / gSize * blockSizeX : (Dx.cols / gSize + 1) * blockSizeX;
963             size_t rows_per_thread = 2;
964             size_t globalSizeY = ((Dx.rows + rows_per_thread - 1) / rows_per_thread) % blockSizeY == 0 ?
965                                  ((Dx.rows + rows_per_thread - 1) / rows_per_thread) :
966                                  (((Dx.rows + rows_per_thread - 1) / rows_per_thread) / blockSizeY + 1) * blockSizeY;
967
968             size_t gt[3] = { globalSizeX, globalSizeY, 1 };
969             size_t lt[3]  = { blockSizeX, blockSizeY, 1 };
970             std::vector<std::pair<size_t , const void *> > args;
971             args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&Dx.data ));
972             args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&Dy.data));
973             args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dst.data));
974             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&Dx.offset ));
975             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&Dx.wholerows ));
976             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&Dx.wholecols ));
977             args.push_back( std::make_pair(sizeof(cl_int), (void *)&Dx.step));
978             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&Dy.offset ));
979             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&Dy.wholerows ));
980             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&Dy.wholecols ));
981             args.push_back( std::make_pair(sizeof(cl_int), (void *)&Dy.step));
982             args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst.offset));
983             args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst.rows));
984             args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst.cols));
985             args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst.step));
986             args.push_back( std::make_pair( sizeof(cl_float) , (void *)&k));
987             openCLExecuteKernel(dst.clCxt, source, kernelName, gt, lt, args, -1, -1, buildOptions.c_str());
988         }
989
990         void cornerHarris(const oclMat &src, oclMat &dst, int blockSize, int ksize,
991                           double k, int borderType)
992         {
993             oclMat dx, dy;
994             cornerHarris_dxdy(src, dst, dx, dy, blockSize, ksize, k, borderType);
995         }
996
997         void cornerHarris_dxdy(const oclMat &src, oclMat &dst, oclMat &dx, oclMat &dy, int blockSize, int ksize,
998                           double k, int borderType)
999         {
1000             if (!src.clCxt->supportsFeature(FEATURE_CL_DOUBLE) && src.depth() == CV_64F)
1001             {
1002                 CV_Error(Error::OpenCLDoubleNotSupported, "Select device doesn't support double");
1003                 return;
1004             }
1005
1006             CV_Assert(src.cols >= blockSize / 2 && src.rows >= blockSize / 2);
1007             CV_Assert(borderType == cv::BORDER_CONSTANT || borderType == cv::BORDER_REFLECT101 || borderType == cv::BORDER_REPLICATE
1008                       || borderType == cv::BORDER_REFLECT);
1009             extractCovData(src, dx, dy, blockSize, ksize, borderType);
1010             dst.create(src.size(), CV_32F);
1011             corner_ocl(&imgproc_calcHarris, "calcHarris", blockSize, static_cast<float>(k), dx, dy, dst, borderType);
1012         }
1013
1014         void cornerMinEigenVal(const oclMat &src, oclMat &dst, int blockSize, int ksize, int borderType)
1015         {
1016             oclMat dx, dy;
1017             cornerMinEigenVal_dxdy(src, dst, dx, dy, blockSize, ksize, borderType);
1018         }
1019
1020         void cornerMinEigenVal_dxdy(const oclMat &src, oclMat &dst, oclMat &dx, oclMat &dy, int blockSize, int ksize, int borderType)
1021         {
1022             if (!src.clCxt->supportsFeature(FEATURE_CL_DOUBLE) && src.depth() == CV_64F)
1023             {
1024                 CV_Error(Error::OpenCLDoubleNotSupported, "select device don't support double");
1025                 return;
1026             }
1027
1028             CV_Assert(src.cols >= blockSize / 2 && src.rows >= blockSize / 2);
1029             CV_Assert(borderType == cv::BORDER_CONSTANT || borderType == cv::BORDER_REFLECT101 || borderType == cv::BORDER_REPLICATE || borderType == cv::BORDER_REFLECT);
1030             extractCovData(src, dx, dy, blockSize, ksize, borderType);
1031             dst.create(src.size(), CV_32F);
1032
1033             corner_ocl(&imgproc_calcMinEigenVal, "calcMinEigenVal", blockSize, 0, dx, dy, dst, borderType);
1034         }
1035
1036         /////////////////////////////////// MeanShiftfiltering ///////////////////////////////////////////////
1037
1038         static void meanShiftFiltering_gpu(const oclMat &src, oclMat dst, int sp, int sr, int maxIter, float eps)
1039         {
1040             CV_Assert( (src.cols == dst.cols) && (src.rows == dst.rows) );
1041             CV_Assert( !(dst.step & 0x3) );
1042
1043             //Arrange the NDRange
1044             int col = src.cols, row = src.rows;
1045             int ltx = 16, lty = 8;
1046             if (src.cols % ltx != 0)
1047                 col = (col / ltx + 1) * ltx;
1048             if (src.rows % lty != 0)
1049                 row = (row / lty + 1) * lty;
1050
1051             size_t globalThreads[3] = {col, row, 1};
1052             size_t localThreads[3]  = {ltx, lty, 1};
1053
1054             //set args
1055             std::vector<std::pair<size_t , const void *> > args;
1056             args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dst.data ));
1057             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.step ));
1058             args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&src.data ));
1059             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.step ));
1060             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.offset ));
1061             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.offset ));
1062             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.cols ));
1063             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.rows ));
1064             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&sp ));
1065             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&sr ));
1066             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&maxIter ));
1067             args.push_back( std::make_pair( sizeof(cl_float) , (void *)&eps ));
1068
1069             openCLExecuteKernel(src.clCxt, &meanShift, "meanshift_kernel", globalThreads, localThreads, args, -1, -1);
1070         }
1071
1072         void meanShiftFiltering(const oclMat &src, oclMat &dst, int sp, int sr, TermCriteria criteria)
1073         {
1074             if (src.empty())
1075                 CV_Error(Error::StsBadArg, "The input image is empty");
1076
1077             if ( src.depth() != CV_8U || src.oclchannels() != 4 )
1078                 CV_Error(Error::StsUnsupportedFormat, "Only 8-bit, 4-channel images are supported");
1079
1080             dst.create( src.size(), CV_8UC4 );
1081
1082             if ( !(criteria.type & TermCriteria::MAX_ITER) )
1083                 criteria.maxCount = 5;
1084
1085             int maxIter = std::min(std::max(criteria.maxCount, 1), 100);
1086
1087             float eps;
1088             if ( !(criteria.type & TermCriteria::EPS) )
1089                 eps = 1.f;
1090             eps = (float)std::max(criteria.epsilon, 0.0);
1091
1092             meanShiftFiltering_gpu(src, dst, sp, sr, maxIter, eps);
1093         }
1094
1095         static void meanShiftProc_gpu(const oclMat &src, oclMat dstr, oclMat dstsp, int sp, int sr, int maxIter, float eps)
1096         {
1097             //sanity checks
1098             CV_Assert( (src.cols == dstr.cols) && (src.rows == dstr.rows) &&
1099                        (src.rows == dstsp.rows) && (src.cols == dstsp.cols));
1100             CV_Assert( !(dstsp.step & 0x3) );
1101
1102             //Arrange the NDRange
1103             int col = src.cols, row = src.rows;
1104             int ltx = 16, lty = 8;
1105             if (src.cols % ltx != 0)
1106                 col = (col / ltx + 1) * ltx;
1107             if (src.rows % lty != 0)
1108                 row = (row / lty + 1) * lty;
1109
1110             size_t globalThreads[3] = {col, row, 1};
1111             size_t localThreads[3]  = {ltx, lty, 1};
1112
1113             //set args
1114             std::vector<std::pair<size_t , const void *> > args;
1115             args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&src.data ));
1116             args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dstr.data ));
1117             args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dstsp.data ));
1118             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.step ));
1119             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dstr.step ));
1120             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dstsp.step ));
1121             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.offset ));
1122             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dstr.offset ));
1123             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dstsp.offset ));
1124             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dstr.cols ));
1125             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dstr.rows ));
1126             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&sp ));
1127             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&sr ));
1128             args.push_back( std::make_pair( sizeof(cl_int) , (void *)&maxIter ));
1129             args.push_back( std::make_pair( sizeof(cl_float) , (void *)&eps ));
1130
1131             openCLExecuteKernel(src.clCxt, &meanShift, "meanshiftproc_kernel", globalThreads, localThreads, args, -1, -1);
1132         }
1133
1134         void meanShiftProc(const oclMat &src, oclMat &dstr, oclMat &dstsp, int sp, int sr, TermCriteria criteria)
1135         {
1136             if (src.empty())
1137                 CV_Error(Error::StsBadArg, "The input image is empty");
1138
1139             if ( src.depth() != CV_8U || src.oclchannels() != 4 )
1140                 CV_Error(Error::StsUnsupportedFormat, "Only 8-bit, 4-channel images are supported");
1141
1142 //            if (!src.clCxt->supportsFeature(FEATURE_CL_DOUBLE))
1143 //            {
1144 //                CV_Error(Error::OpenCLDoubleNotSupportedNotSupported, "Selected device doesn't support double, so a deviation exists.\nIf the accuracy is acceptable, the error can be ignored.\n");
1145 //                return;
1146 //            }
1147
1148             dstr.create( src.size(), CV_8UC4 );
1149             dstsp.create( src.size(), CV_16SC2 );
1150
1151             if ( !(criteria.type & TermCriteria::MAX_ITER) )
1152                 criteria.maxCount = 5;
1153
1154             int maxIter = std::min(std::max(criteria.maxCount, 1), 100);
1155
1156             float eps;
1157             if ( !(criteria.type & TermCriteria::EPS) )
1158                 eps = 1.f;
1159             eps = (float)std::max(criteria.epsilon, 0.0);
1160
1161             meanShiftProc_gpu(src, dstr, dstsp, sp, sr, maxIter, eps);
1162         }
1163
1164         ///////////////////////////////////////////////////////////////////////////////////////////////////
1165         ////////////////////////////////////////////////////hist///////////////////////////////////////////////
1166         /////////////////////////////////////////////////////////////////////////////////////////////////////
1167
1168         namespace histograms
1169         {
1170             const int PARTIAL_HISTOGRAM256_COUNT = 256;
1171             const int HISTOGRAM256_BIN_COUNT = 256;
1172         }
1173         ///////////////////////////////calcHist/////////////////////////////////////////////////////////////////
1174         static void calc_sub_hist(const oclMat &mat_src, const oclMat &mat_sub_hist)
1175         {
1176             using namespace histograms;
1177
1178             int depth = mat_src.depth();
1179
1180             size_t localThreads[3]  = { HISTOGRAM256_BIN_COUNT, 1, 1 };
1181             size_t globalThreads[3] = { PARTIAL_HISTOGRAM256_COUNT *localThreads[0], 1, 1};
1182
1183             int dataWidth = 16;
1184             int dataWidth_bits = 4;
1185             int mask = dataWidth - 1;
1186
1187             int cols = mat_src.cols * mat_src.oclchannels();
1188             int src_offset = mat_src.offset;
1189             int hist_step = mat_sub_hist.step >> 2;
1190             int left_col = 0, right_col = 0;
1191
1192             if (cols >= dataWidth * 2 - 1)
1193             {
1194                 left_col = dataWidth - (src_offset & mask);
1195                 left_col &= mask;
1196                 src_offset += left_col;
1197                 cols -= left_col;
1198                 right_col = cols & mask;
1199                 cols -= right_col;
1200             }
1201             else
1202             {
1203                 left_col = cols;
1204                 right_col = 0;
1205                 cols = 0;
1206                 globalThreads[0] = 0;
1207             }
1208
1209             std::vector<std::pair<size_t , const void *> > args;
1210             if (globalThreads[0] != 0)
1211             {
1212                 int tempcols = cols >> dataWidth_bits;
1213                 int inc_x = globalThreads[0] % tempcols;
1214                 int inc_y = globalThreads[0] / tempcols;
1215                 src_offset >>= dataWidth_bits;
1216                 int src_step = mat_src.step >> dataWidth_bits;
1217                 int datacount = tempcols * mat_src.rows;
1218
1219                 args.push_back( std::make_pair( sizeof(cl_mem), (void *)&mat_src.data));
1220                 args.push_back( std::make_pair( sizeof(cl_int), (void *)&src_step));
1221                 args.push_back( std::make_pair( sizeof(cl_int), (void *)&src_offset));
1222                 args.push_back( std::make_pair( sizeof(cl_mem), (void *)&mat_sub_hist.data));
1223                 args.push_back( std::make_pair( sizeof(cl_int), (void *)&datacount));
1224                 args.push_back( std::make_pair( sizeof(cl_int), (void *)&tempcols));
1225                 args.push_back( std::make_pair( sizeof(cl_int), (void *)&inc_x));
1226                 args.push_back( std::make_pair( sizeof(cl_int), (void *)&inc_y));
1227                 args.push_back( std::make_pair( sizeof(cl_int), (void *)&hist_step));
1228
1229                 openCLExecuteKernel(mat_src.clCxt, &imgproc_histogram, "calc_sub_hist", globalThreads, localThreads, args, -1, depth);
1230             }
1231
1232             if (left_col != 0 || right_col != 0)
1233             {
1234                 src_offset = mat_src.offset;
1235                 localThreads[0] = 1;
1236                 localThreads[1] = 256;
1237                 globalThreads[0] = left_col + right_col;
1238                 globalThreads[1] = mat_src.rows;
1239
1240                 args.clear();
1241                 args.push_back( std::make_pair( sizeof(cl_mem), (void *)&mat_src.data));
1242                 args.push_back( std::make_pair( sizeof(cl_int), (void *)&mat_src.step));
1243                 args.push_back( std::make_pair( sizeof(cl_int), (void *)&src_offset));
1244                 args.push_back( std::make_pair( sizeof(cl_mem), (void *)&mat_sub_hist.data));
1245                 args.push_back( std::make_pair( sizeof(cl_int), (void *)&left_col));
1246                 args.push_back( std::make_pair( sizeof(cl_int), (void *)&cols));
1247                 args.push_back( std::make_pair( sizeof(cl_int), (void *)&mat_src.rows));
1248                 args.push_back( std::make_pair( sizeof(cl_int), (void *)&hist_step));
1249
1250                 openCLExecuteKernel(mat_src.clCxt, &imgproc_histogram, "calc_sub_hist_border", globalThreads, localThreads, args, -1, depth);
1251             }
1252         }
1253
1254         static void merge_sub_hist(const oclMat &sub_hist, oclMat &mat_hist)
1255         {
1256             using namespace histograms;
1257
1258             size_t localThreads[3]  = { 256, 1, 1 };
1259             size_t globalThreads[3] = { HISTOGRAM256_BIN_COUNT *localThreads[0], 1, 1};
1260             int src_step = sub_hist.step >> 2;
1261
1262             std::vector<std::pair<size_t , const void *> > args;
1263             args.push_back( std::make_pair( sizeof(cl_mem), (void *)&sub_hist.data));
1264             args.push_back( std::make_pair( sizeof(cl_mem), (void *)&mat_hist.data));
1265             args.push_back( std::make_pair( sizeof(cl_int), (void *)&src_step));
1266
1267             openCLExecuteKernel(sub_hist.clCxt, &imgproc_histogram, "merge_hist", globalThreads, localThreads, args, -1, -1);
1268         }
1269
1270         void calcHist(const oclMat &mat_src, oclMat &mat_hist)
1271         {
1272             using namespace histograms;
1273             CV_Assert(mat_src.type() == CV_8UC1);
1274             mat_hist.create(1, 256, CV_32SC1);
1275
1276             oclMat buf(PARTIAL_HISTOGRAM256_COUNT, HISTOGRAM256_BIN_COUNT, CV_32SC1);
1277             buf.setTo(0);
1278
1279             calc_sub_hist(mat_src, buf);
1280             merge_sub_hist(buf, mat_hist);
1281         }
1282
1283         ///////////////////////////////////equalizeHist/////////////////////////////////////////////////////
1284         void equalizeHist(const oclMat &mat_src, oclMat &mat_dst)
1285         {
1286             mat_dst.create(mat_src.rows, mat_src.cols, CV_8UC1);
1287
1288             oclMat mat_hist(1, 256, CV_32SC1);
1289
1290             calcHist(mat_src, mat_hist);
1291
1292             size_t localThreads[3] = { 256, 1, 1};
1293             size_t globalThreads[3] = { 256, 1, 1};
1294             oclMat lut(1, 256, CV_8UC1);
1295             int total = mat_src.rows * mat_src.cols;
1296
1297             std::vector<std::pair<size_t , const void *> > args;
1298             args.push_back( std::make_pair( sizeof(cl_mem), (void *)&lut.data));
1299             args.push_back( std::make_pair( sizeof(cl_mem), (void *)&mat_hist.data));
1300             args.push_back( std::make_pair( sizeof(int), (void *)&total));
1301
1302             openCLExecuteKernel(mat_src.clCxt, &imgproc_histogram, "calLUT", globalThreads, localThreads, args, -1, -1);
1303             LUT(mat_src, lut, mat_dst);
1304         }
1305
1306         ////////////////////////////////////////////////////////////////////////
1307         // CLAHE
1308         namespace clahe
1309         {
1310             static void calcLut(const oclMat &src, oclMat &dst,
1311                 const int tilesX, const int tilesY, const cv::Size tileSize,
1312                 const int clipLimit, const float lutScale)
1313             {
1314                 cl_int2 tile_size;
1315                 tile_size.s[0] = tileSize.width;
1316                 tile_size.s[1] = tileSize.height;
1317
1318                 std::vector<std::pair<size_t , const void *> > args;
1319                 args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src.data ));
1320                 args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst.data ));
1321                 args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.step ));
1322                 args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.step ));
1323                 args.push_back( std::make_pair( sizeof(cl_int2), (void *)&tile_size ));
1324                 args.push_back( std::make_pair( sizeof(cl_int), (void *)&tilesX ));
1325                 args.push_back( std::make_pair( sizeof(cl_int), (void *)&clipLimit ));
1326                 args.push_back( std::make_pair( sizeof(cl_float), (void *)&lutScale ));
1327
1328                 String kernelName = "calcLut";
1329                 size_t localThreads[3]  = { 32, 8, 1 };
1330                 size_t globalThreads[3] = { tilesX * localThreads[0], tilesY * localThreads[1], 1 };
1331                 bool is_cpu = isCpuDevice();
1332                 if (is_cpu)
1333                     openCLExecuteKernel(Context::getContext(), &imgproc_clahe, kernelName, globalThreads, localThreads, args, -1, -1, (char*)"-D CPU");
1334                 else
1335                 {
1336                     cl_kernel kernel = openCLGetKernelFromSource(Context::getContext(), &imgproc_clahe, kernelName);
1337                     int wave_size = (int)queryWaveFrontSize(kernel);
1338                     openCLSafeCall(clReleaseKernel(kernel));
1339
1340                     std::string opt = format("-D WAVE_SIZE=%d", wave_size);
1341                     openCLExecuteKernel(Context::getContext(), &imgproc_clahe, kernelName, globalThreads, localThreads, args, -1, -1, opt.c_str());
1342                 }
1343             }
1344
1345             static void transform(const oclMat &src, oclMat &dst, const oclMat &lut,
1346                 const int tilesX, const int tilesY, const cv::Size tileSize)
1347             {
1348                 cl_int2 tile_size;
1349                 tile_size.s[0] = tileSize.width;
1350                 tile_size.s[1] = tileSize.height;
1351
1352                 std::vector<std::pair<size_t , const void *> > args;
1353                 args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src.data ));
1354                 args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst.data ));
1355                 args.push_back( std::make_pair( sizeof(cl_mem), (void *)&lut.data ));
1356                 args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.step ));
1357                 args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.step ));
1358                 args.push_back( std::make_pair( sizeof(cl_int), (void *)&lut.step ));
1359                 args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.cols ));
1360                 args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.rows ));
1361                 args.push_back( std::make_pair( sizeof(cl_int2), (void *)&tile_size ));
1362                 args.push_back( std::make_pair( sizeof(cl_int), (void *)&tilesX ));
1363                 args.push_back( std::make_pair( sizeof(cl_int), (void *)&tilesY ));
1364
1365                 size_t localThreads[3]  = { 32, 8, 1 };
1366                 size_t globalThreads[3] = { src.cols, src.rows, 1 };
1367
1368                 openCLExecuteKernel(Context::getContext(), &imgproc_clahe, "transform", globalThreads, localThreads, args, -1, -1);
1369             }
1370         }
1371
1372         namespace
1373         {
1374             class CLAHE_Impl : public cv::CLAHE
1375             {
1376             public:
1377                 CLAHE_Impl(double clipLimit = 40.0, int tilesX = 8, int tilesY = 8);
1378
1379                 cv::AlgorithmInfo* info() const;
1380
1381                 void apply(cv::InputArray src, cv::OutputArray dst);
1382
1383                 void setClipLimit(double clipLimit);
1384                 double getClipLimit() const;
1385
1386                 void setTilesGridSize(cv::Size tileGridSize);
1387                 cv::Size getTilesGridSize() const;
1388
1389                 void collectGarbage();
1390
1391             private:
1392                 double clipLimit_;
1393                 int tilesX_;
1394                 int tilesY_;
1395
1396                 oclMat srcExt_;
1397                 oclMat lut_;
1398             };
1399
1400             CLAHE_Impl::CLAHE_Impl(double clipLimit, int tilesX, int tilesY) :
1401                 clipLimit_(clipLimit), tilesX_(tilesX), tilesY_(tilesY)
1402             {
1403             }
1404
1405             CV_INIT_ALGORITHM(CLAHE_Impl, "CLAHE_OCL",
1406                 obj.info()->addParam(obj, "clipLimit", obj.clipLimit_);
1407                 obj.info()->addParam(obj, "tilesX", obj.tilesX_);
1408                 obj.info()->addParam(obj, "tilesY", obj.tilesY_))
1409
1410             void CLAHE_Impl::apply(cv::InputArray src_raw, cv::OutputArray dst_raw)
1411             {
1412                 oclMat& src = getOclMatRef(src_raw);
1413                 oclMat& dst = getOclMatRef(dst_raw);
1414                 CV_Assert( src.type() == CV_8UC1 );
1415
1416                 dst.create( src.size(), src.type() );
1417
1418                 const int histSize = 256;
1419
1420                 ensureSizeIsEnough(tilesX_ * tilesY_, histSize, CV_8UC1, lut_);
1421
1422                 cv::Size tileSize;
1423                 oclMat srcForLut;
1424
1425                 if (src.cols % tilesX_ == 0 && src.rows % tilesY_ == 0)
1426                 {
1427                     tileSize = cv::Size(src.cols / tilesX_, src.rows / tilesY_);
1428                     srcForLut = src;
1429                 }
1430                 else
1431                 {
1432                     cv::ocl::copyMakeBorder(src, srcExt_, 0, tilesY_ - (src.rows % tilesY_), 0, tilesX_ - (src.cols % tilesX_), cv::BORDER_REFLECT_101, cv::Scalar());
1433
1434                     tileSize = cv::Size(srcExt_.cols / tilesX_, srcExt_.rows / tilesY_);
1435                     srcForLut = srcExt_;
1436                 }
1437
1438                 const int tileSizeTotal = tileSize.area();
1439                 const float lutScale = static_cast<float>(histSize - 1) / tileSizeTotal;
1440
1441                 int clipLimit = 0;
1442                 if (clipLimit_ > 0.0)
1443                 {
1444                     clipLimit = static_cast<int>(clipLimit_ * tileSizeTotal / histSize);
1445                     clipLimit = std::max(clipLimit, 1);
1446                 }
1447
1448                 clahe::calcLut(srcForLut, lut_, tilesX_, tilesY_, tileSize, clipLimit, lutScale);
1449                 clahe::transform(src, dst, lut_, tilesX_, tilesY_, tileSize);
1450             }
1451
1452             void CLAHE_Impl::setClipLimit(double clipLimit)
1453             {
1454                 clipLimit_ = clipLimit;
1455             }
1456
1457             double CLAHE_Impl::getClipLimit() const
1458             {
1459                 return clipLimit_;
1460             }
1461
1462             void CLAHE_Impl::setTilesGridSize(cv::Size tileGridSize)
1463             {
1464                 tilesX_ = tileGridSize.width;
1465                 tilesY_ = tileGridSize.height;
1466             }
1467
1468             cv::Size CLAHE_Impl::getTilesGridSize() const
1469             {
1470                 return cv::Size(tilesX_, tilesY_);
1471             }
1472
1473             void CLAHE_Impl::collectGarbage()
1474             {
1475                 srcExt_.release();
1476                 lut_.release();
1477             }
1478         }
1479
1480         cv::Ptr<cv::CLAHE> createCLAHE(double clipLimit, cv::Size tileGridSize)
1481         {
1482             return makePtr<CLAHE_Impl>(clipLimit, tileGridSize.width, tileGridSize.height);
1483         }
1484
1485         //////////////////////////////////bilateralFilter////////////////////////////////////////////////////
1486
1487         static void oclbilateralFilter_8u( const oclMat &src, oclMat &dst, int d,
1488                                double sigma_color, double sigma_space,
1489                                int borderType )
1490         {
1491             int cn = src.channels();
1492             int i, j, maxk, radius;
1493
1494             CV_Assert( (src.channels() == 1 || src.channels() == 3) &&
1495                        src.type() == dst.type() && src.size() == dst.size() &&
1496                        src.data != dst.data );
1497
1498             if ( sigma_color <= 0 )
1499                 sigma_color = 1;
1500             if ( sigma_space <= 0 )
1501                 sigma_space = 1;
1502
1503             double gauss_color_coeff = -0.5 / (sigma_color * sigma_color);
1504             double gauss_space_coeff = -0.5 / (sigma_space * sigma_space);
1505
1506             if ( d <= 0 )
1507                 radius = cvRound(sigma_space * 1.5);
1508             else
1509                 radius = d / 2;
1510             radius = MAX(radius, 1);
1511             d = radius * 2 + 1;
1512
1513             oclMat temp;
1514             copyMakeBorder( src, temp, radius, radius, radius, radius, borderType );
1515
1516             std::vector<float> _color_weight(cn * 256);
1517             std::vector<float> _space_weight(d * d);
1518             std::vector<int> _space_ofs(d * d);
1519             float *color_weight = &_color_weight[0];
1520             float *space_weight = &_space_weight[0];
1521             int *space_ofs = &_space_ofs[0];
1522             int dst_step_in_pixel = dst.step / dst.elemSize();
1523             int dst_offset_in_pixel = dst.offset / dst.elemSize();
1524             int temp_step_in_pixel = temp.step / temp.elemSize();
1525
1526             // initialize color-related bilateral filter coefficients
1527             for( i = 0; i < 256 * cn; i++ )
1528                 color_weight[i] = (float)std::exp(i * i * gauss_color_coeff);
1529
1530             // initialize space-related bilateral filter coefficients
1531             for( i = -radius, maxk = 0; i <= radius; i++ )
1532                 for( j = -radius; j <= radius; j++ )
1533                 {
1534                     double r = std::sqrt((double)i * i + (double)j * j);
1535                     if ( r > radius )
1536                         continue;
1537                     space_weight[maxk] = (float)std::exp(r * r * gauss_space_coeff);
1538                     space_ofs[maxk++] = (int)(i * temp_step_in_pixel + j);
1539                 }
1540
1541             oclMat oclcolor_weight(1, cn * 256, CV_32FC1, color_weight);
1542             oclMat oclspace_weight(1, d * d, CV_32FC1, space_weight);
1543             oclMat oclspace_ofs(1, d * d, CV_32SC1, space_ofs);
1544
1545             String kernelName = "bilateral";
1546             size_t localThreads[3]  = { 16, 16, 1 };
1547             size_t globalThreads[3] = { dst.cols, dst.rows, 1 };
1548
1549             if ((dst.type() == CV_8UC1) && ((dst.offset & 3) == 0) && ((dst.cols & 3) == 0))
1550             {
1551                 kernelName = "bilateral2";
1552                 globalThreads[0] = dst.cols / 4;
1553             }
1554
1555             std::vector<std::pair<size_t , const void *> > args;
1556             args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst.data ));
1557             args.push_back( std::make_pair( sizeof(cl_mem), (void *)&temp.data ));
1558             args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.rows ));
1559             args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.cols ));
1560             args.push_back( std::make_pair( sizeof(cl_int), (void *)&maxk ));
1561             args.push_back( std::make_pair( sizeof(cl_int), (void *)&radius ));
1562             args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst_step_in_pixel ));
1563             args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst_offset_in_pixel ));
1564             args.push_back( std::make_pair( sizeof(cl_int), (void *)&temp_step_in_pixel ));
1565             args.push_back( std::make_pair( sizeof(cl_int), (void *)&temp.rows ));
1566             args.push_back( std::make_pair( sizeof(cl_int), (void *)&temp.cols ));
1567             args.push_back( std::make_pair( sizeof(cl_mem), (void *)&oclcolor_weight.data ));
1568             args.push_back( std::make_pair( sizeof(cl_mem), (void *)&oclspace_weight.data ));
1569             args.push_back( std::make_pair( sizeof(cl_mem), (void *)&oclspace_ofs.data ));
1570             openCLExecuteKernel(src.clCxt, &imgproc_bilateral, kernelName, globalThreads, localThreads, args, dst.oclchannels(), dst.depth());
1571         }
1572         void bilateralFilter(const oclMat &src, oclMat &dst, int radius, double sigmaclr, double sigmaspc, int borderType)
1573         {
1574             dst.create( src.size(), src.type() );
1575             if ( src.depth() == CV_8U )
1576                 oclbilateralFilter_8u( src, dst, radius, sigmaclr, sigmaspc, borderType );
1577             else
1578                 CV_Error(Error::StsUnsupportedFormat, "Bilateral filtering is only implemented for 8uimages");
1579         }
1580
1581     }
1582 }
1583 //////////////////////////////////mulSpectrums////////////////////////////////////////////////////
1584 void cv::ocl::mulSpectrums(const oclMat &a, const oclMat &b, oclMat &c, int /*flags*/, float scale, bool conjB)
1585 {
1586     CV_Assert(a.type() == CV_32FC2);
1587     CV_Assert(b.type() == CV_32FC2);
1588
1589     c.create(a.size(), CV_32FC2);
1590
1591     size_t lt[3]  = { 16, 16, 1 };
1592     size_t gt[3]  = { a.cols, a.rows, 1 };
1593
1594     String kernelName = conjB ? "mulAndScaleSpectrumsKernel_CONJ":"mulAndScaleSpectrumsKernel";
1595
1596     std::vector<std::pair<size_t , const void *> > args;
1597     args.push_back( std::make_pair( sizeof(cl_mem), (void *)&a.data ));
1598     args.push_back( std::make_pair( sizeof(cl_mem), (void *)&b.data ));
1599     args.push_back( std::make_pair( sizeof(cl_float), (void *)&scale));
1600     args.push_back( std::make_pair( sizeof(cl_mem), (void *)&c.data ));
1601     args.push_back( std::make_pair( sizeof(cl_int), (void *)&a.cols ));
1602     args.push_back( std::make_pair( sizeof(cl_int), (void *)&a.rows));
1603     args.push_back( std::make_pair( sizeof(cl_int), (void *)&a.step ));
1604
1605     Context *clCxt = Context::getContext();
1606     openCLExecuteKernel(clCxt, &imgproc_mulAndScaleSpectrums, kernelName, gt, lt, args, -1, -1);
1607 }
1608 //////////////////////////////////convolve////////////////////////////////////////////////////
1609 // ported from CUDA module
1610 void cv::ocl::ConvolveBuf::create(Size image_size, Size templ_size)
1611 {
1612     result_size = Size(image_size.width - templ_size.width + 1,
1613                        image_size.height - templ_size.height + 1);
1614
1615     block_size = user_block_size;
1616     if (user_block_size.width == 0 || user_block_size.height == 0)
1617         block_size = estimateBlockSize(result_size, templ_size);
1618
1619     dft_size.width  = 1 << int(ceil(std::log(block_size.width + templ_size.width - 1.) / std::log(2.)));
1620     dft_size.height = 1 << int(ceil(std::log(block_size.height + templ_size.height - 1.) / std::log(2.)));
1621
1622     // CUFFT has hard-coded kernels for power-of-2 sizes (up to 8192),
1623     // see CUDA Toolkit 4.1 CUFFT Library Programming Guide
1624     //if (dft_size.width > 8192)
1625     dft_size.width = getOptimalDFTSize(block_size.width + templ_size.width - 1.);
1626     //if (dft_size.height > 8192)
1627     dft_size.height = getOptimalDFTSize(block_size.height + templ_size.height - 1.);
1628
1629     // To avoid wasting time doing small DFTs
1630     dft_size.width = std::max(dft_size.width, 512);
1631     dft_size.height = std::max(dft_size.height, 512);
1632
1633     image_block.create(dft_size, CV_32F);
1634     templ_block.create(dft_size, CV_32F);
1635     result_data.create(dft_size, CV_32F);
1636
1637     //spect_len = dft_size.height * (dft_size.width / 2 + 1);
1638     image_spect.create(dft_size.height, dft_size.width / 2 + 1, CV_32FC2);
1639     templ_spect.create(dft_size.height, dft_size.width / 2 + 1, CV_32FC2);
1640     result_spect.create(dft_size.height, dft_size.width / 2 + 1, CV_32FC2);
1641
1642     // Use maximum result matrix block size for the estimated DFT block size
1643     block_size.width = std::min(dft_size.width - templ_size.width + 1, result_size.width);
1644     block_size.height = std::min(dft_size.height - templ_size.height + 1, result_size.height);
1645 }
1646
1647 Size cv::ocl::ConvolveBuf::estimateBlockSize(Size result_size, Size /*templ_size*/)
1648 {
1649     int width = (result_size.width + 2) / 3;
1650     int height = (result_size.height + 2) / 3;
1651     width = std::min(width, result_size.width);
1652     height = std::min(height, result_size.height);
1653     return Size(width, height);
1654 }
1655
1656 static void convolve_run_fft(const oclMat &image, const oclMat &templ, oclMat &result, bool ccorr, ConvolveBuf& buf)
1657 {
1658 #if defined HAVE_CLAMDFFT
1659     CV_Assert(image.type() == CV_32F);
1660     CV_Assert(templ.type() == CV_32F);
1661
1662     buf.create(image.size(), templ.size());
1663     result.create(buf.result_size, CV_32F);
1664
1665     Size& block_size = buf.block_size;
1666     Size& dft_size = buf.dft_size;
1667
1668     oclMat& image_block = buf.image_block;
1669     oclMat& templ_block = buf.templ_block;
1670     oclMat& result_data = buf.result_data;
1671
1672     oclMat& image_spect = buf.image_spect;
1673     oclMat& templ_spect = buf.templ_spect;
1674     oclMat& result_spect = buf.result_spect;
1675
1676     oclMat templ_roi = templ;
1677     copyMakeBorder(templ_roi, templ_block, 0, templ_block.rows - templ_roi.rows, 0,
1678                    templ_block.cols - templ_roi.cols, 0, Scalar());
1679
1680     cv::ocl::dft(templ_block, templ_spect, dft_size);
1681
1682     // Process all blocks of the result matrix
1683     for (int y = 0; y < result.rows; y += block_size.height)
1684     {
1685         for (int x = 0; x < result.cols; x += block_size.width)
1686         {
1687             Size image_roi_size(std::min(x + dft_size.width, image.cols) - x,
1688                                 std::min(y + dft_size.height, image.rows) - y);
1689             Rect roi0(x, y, image_roi_size.width, image_roi_size.height);
1690
1691             oclMat image_roi(image, roi0);
1692
1693             copyMakeBorder(image_roi, image_block, 0, image_block.rows - image_roi.rows,
1694                            0, image_block.cols - image_roi.cols, 0, Scalar());
1695
1696             cv::ocl::dft(image_block, image_spect, dft_size);
1697
1698             mulSpectrums(image_spect, templ_spect, result_spect, 0,
1699                                  1.f / dft_size.area(), ccorr);
1700
1701             cv::ocl::dft(result_spect, result_data, dft_size, cv::DFT_INVERSE | cv::DFT_REAL_OUTPUT);
1702
1703             Size result_roi_size(std::min(x + block_size.width, result.cols) - x,
1704                                  std::min(y + block_size.height, result.rows) - y);
1705
1706             Rect roi1(x, y, result_roi_size.width, result_roi_size.height);
1707             Rect roi2(0, 0, result_roi_size.width, result_roi_size.height);
1708
1709             oclMat result_roi(result, roi1);
1710             oclMat result_block(result_data, roi2);
1711
1712             result_block.copyTo(result_roi);
1713         }
1714     }
1715
1716 #else
1717     CV_Error(Error::OpenCLNoAMDBlasFft, "OpenCL DFT is not implemented");
1718 #define UNUSED(x) (void)(x);
1719     UNUSED(image) UNUSED(templ) UNUSED(result) UNUSED(ccorr) UNUSED(buf)
1720 #undef UNUSED
1721 #endif
1722 }
1723
1724 static void convolve_run(const oclMat &src, const oclMat &temp1, oclMat &dst, String kernelName, const cv::ocl::ProgramEntry* source)
1725 {
1726     CV_Assert(src.depth() == CV_32FC1);
1727     CV_Assert(temp1.depth() == CV_32F);
1728     CV_Assert(temp1.cols <= 17 && temp1.rows <= 17);
1729
1730     dst.create(src.size(), src.type());
1731
1732     CV_Assert(src.cols == dst.cols && src.rows == dst.rows);
1733     CV_Assert(src.type() == dst.type());
1734
1735     Context  *clCxt = src.clCxt;
1736     int channels = dst.oclchannels();
1737     int depth = dst.depth();
1738
1739     size_t vector_length = 1;
1740     int offset_cols = ((dst.offset % dst.step) / dst.elemSize1()) & (vector_length - 1);
1741     int cols = divUp(dst.cols * channels + offset_cols, vector_length);
1742     int rows = dst.rows;
1743
1744     size_t localThreads[3]  = { 16, 16, 1 };
1745     size_t globalThreads[3] = { cols, rows, 1 };
1746
1747     std::vector<std::pair<size_t , const void *> > args;
1748     args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src.data ));
1749     args.push_back( std::make_pair( sizeof(cl_mem), (void *)&temp1.data ));
1750     args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst.data ));
1751     args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.rows ));
1752     args.push_back( std::make_pair( sizeof(cl_int), (void *)&cols ));
1753     args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.step ));
1754     args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.step ));
1755     args.push_back( std::make_pair( sizeof(cl_int), (void *)&temp1.step ));
1756     args.push_back( std::make_pair( sizeof(cl_int), (void *)&temp1.rows ));
1757     args.push_back( std::make_pair( sizeof(cl_int), (void *)&temp1.cols ));
1758
1759     openCLExecuteKernel(clCxt, source, kernelName, globalThreads, localThreads, args, -1, depth);
1760 }
1761 void cv::ocl::convolve(const oclMat &x, const oclMat &t, oclMat &y, bool ccorr)
1762 {
1763     CV_Assert(x.depth() == CV_32F);
1764     CV_Assert(t.depth() == CV_32F);
1765     y.create(x.size(), x.type());
1766     String kernelName = "convolve";
1767     if(t.cols > 17 || t.rows > 17)
1768     {
1769         ConvolveBuf buf;
1770         convolve_run_fft(x, t, y, ccorr, buf);
1771     }
1772     else
1773     {
1774         CV_Assert(ccorr == false);
1775         convolve_run(x, t, y, kernelName, &imgproc_convolve);
1776     }
1777 }
1778 void cv::ocl::convolve(const oclMat &image, const oclMat &templ, oclMat &result, bool ccorr, ConvolveBuf& buf)
1779 {
1780     result.create(image.size(), image.type());
1781     convolve_run_fft(image, templ, result, ccorr, buf);
1782 }