1793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/*M///////////////////////////////////////////////////////////////////////////////////////
2793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
3793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
5793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//  By downloading, copying, installing or using the software you agree to this license.
6793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//  If you do not agree to this license, do not download, install,
7793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//  copy or use the software.
8793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
9793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
10793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//                        Intel License Agreement
11793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//                For Open Source Computer Vision Library
12793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
13793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// Copyright (C) 2000, Intel Corporation, all rights reserved.
14793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// Third party copyrights are property of their respective owners.
15793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
16793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// Redistribution and use in source and binary forms, with or without modification,
17793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// are permitted provided that the following conditions are met:
18793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
19793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//   * Redistribution's of source code must retain the above copyright notice,
20793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//     this list of conditions and the following disclaimer.
21793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
22793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//   * Redistribution's in binary form must reproduce the above copyright notice,
23793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//     this list of conditions and the following disclaimer in the documentation
24793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//     and/or other materials provided with the distribution.
25793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
26793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//   * The name of Intel Corporation may not be used to endorse or promote products
27793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//     derived from this software without specific prior written permission.
28793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
29793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// This software is provided by the copyright holders and contributors "as is" and
30793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// any express or implied warranties, including, but not limited to, the implied
31793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// warranties of merchantability and fitness for a particular purpose are disclaimed.
32793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// In no event shall the Intel Corporation or contributors be liable for any direct,
33793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// indirect, incidental, special, exemplary, or consequential damages
34793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// (including, but not limited to, procurement of substitute goods or services;
35793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// loss of use, data, or profits; or business interruption) however caused
36793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// and on any theory of liability, whether in contract, strict liability,
37793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// or tort (including negligence or otherwise) arising in any way out of
38793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// the use of this software, even if advised of the possibility of such damage.
39793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
40793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//M*/
41793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
42793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "precomp.hpp"
43793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "opencl_kernels_imgproc.hpp"
44793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
45793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler////////////////////////////////////////////////// matchTemplate //////////////////////////////////////////////////////////
46793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
47793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslernamespace cv
48793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
49793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
50793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#ifdef HAVE_OPENCL
51793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
52793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/////////////////////////////////////////////////// CCORR //////////////////////////////////////////////////////////////
53793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
54793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerenum
55793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
56793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    SUM_1 = 0, SUM_2 = 1
57793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler};
58793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
59793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic bool extractFirstChannel_32F(InputArray _image, OutputArray _result, int cn)
60793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
61793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int depth = _image.depth();
62793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
63793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ocl::Device dev = ocl::Device::getDefault();
64793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int pxPerWIy = (dev.isIntel() && (dev.type() & ocl::Device::TYPE_GPU)) ? 4 : 1;
65793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
66793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ocl::Kernel k("extractFirstChannel", ocl::imgproc::match_template_oclsrc, format("-D FIRST_CHANNEL -D T1=%s -D cn=%d -D PIX_PER_WI_Y=%d",
67793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                                                            ocl::typeToStr(depth), cn, pxPerWIy));
68793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (k.empty())
69793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
70793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
71793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat image  = _image.getUMat();
72793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat result = _result.getUMat();
73793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
74793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
75793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    size_t globalsize[2] = {result.cols, (result.rows+pxPerWIy-1)/pxPerWIy};
76793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return k.args(ocl::KernelArg::ReadOnlyNoSize(image), ocl::KernelArg::WriteOnly(result)).run( 2, globalsize, NULL, false);
77793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
78793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
79793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic bool sumTemplate(InputArray _src, UMat & result)
80793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
81793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
82793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int wdepth = CV_32F, wtype = CV_MAKE_TYPE(wdepth, cn);
83793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    size_t wgs = ocl::Device::getDefault().maxWorkGroupSize();
84793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
85793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int wgs2_aligned = 1;
86793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    while (wgs2_aligned < (int)wgs)
87793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        wgs2_aligned <<= 1;
88793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    wgs2_aligned >>= 1;
89793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
90793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    char cvt[40];
91793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ocl::Kernel k("calcSum", ocl::imgproc::match_template_oclsrc,
92793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                  format("-D CALC_SUM -D T=%s -D T1=%s -D WT=%s -D cn=%d -D convertToWT=%s -D WGS=%d -D WGS2_ALIGNED=%d",
93793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                         ocl::typeToStr(type), ocl::typeToStr(depth), ocl::typeToStr(wtype), cn,
94793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                         ocl::convertTypeStr(depth, wdepth, cn, cvt),
95793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                         (int)wgs, wgs2_aligned));
96793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (k.empty())
97793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
98793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
99793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat src = _src.getUMat();
100793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    result.create(1, 1, CV_32FC1);
101793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
102793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ocl::KernelArg srcarg = ocl::KernelArg::ReadOnlyNoSize(src),
103793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            resarg = ocl::KernelArg::PtrWriteOnly(result);
104793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
105793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    k.args(srcarg, src.cols, (int)src.total(), resarg);
106793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
107793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    size_t globalsize = wgs;
108793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return k.run(1, &globalsize, &wgs, false);
109793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
110793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
111793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic bool useNaive(Size size)
112793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
113793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int dft_size = 18;
114793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return size.height < dft_size && size.width < dft_size;
115793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
116793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
117793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstruct ConvolveBuf
118793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
119793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Size result_size;
120793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Size block_size;
121793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Size user_block_size;
122793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Size dft_size;
123793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
124793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat image_spect, templ_spect, result_spect;
125793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat image_block, templ_block, result_data;
126793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
127793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    void create(Size image_size, Size templ_size);
128793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler};
129793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
130793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid ConvolveBuf::create(Size image_size, Size templ_size)
131793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
132793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    result_size = Size(image_size.width - templ_size.width + 1,
133793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                       image_size.height - templ_size.height + 1);
134793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
135793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    const double blockScale = 4.5;
136793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    const int minBlockSize = 256;
137793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
138793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    block_size.width = cvRound(result_size.width*blockScale);
139793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    block_size.width = std::max( block_size.width, minBlockSize - templ_size.width + 1 );
140793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    block_size.width = std::min( block_size.width, result_size.width );
141793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    block_size.height = cvRound(templ_size.height*blockScale);
142793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    block_size.height = std::max( block_size.height, minBlockSize - templ_size.height + 1 );
143793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    block_size.height = std::min( block_size.height, result_size.height );
144793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
145793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    dft_size.width = std::max(getOptimalDFTSize(block_size.width + templ_size.width - 1), 2);
146793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    dft_size.height = getOptimalDFTSize(block_size.height + templ_size.height - 1);
147793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if( dft_size.width <= 0 || dft_size.height <= 0 )
148793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        CV_Error( CV_StsOutOfRange, "the input arrays are too big" );
149793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
150793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    // recompute block size
151793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    block_size.width = dft_size.width - templ_size.width + 1;
152793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    block_size.width = std::min( block_size.width, result_size.width);
153793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    block_size.height = dft_size.height - templ_size.height + 1;
154793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    block_size.height = std::min( block_size.height, result_size.height );
155793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
156793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    image_block.create(dft_size, CV_32F);
157793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    templ_block.create(dft_size, CV_32F);
158793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    result_data.create(dft_size, CV_32F);
159793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
160793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    image_spect.create(dft_size.height, dft_size.width / 2 + 1, CV_32FC2);
161793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    templ_spect.create(dft_size.height, dft_size.width / 2 + 1, CV_32FC2);
162793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    result_spect.create(dft_size.height, dft_size.width / 2 + 1, CV_32FC2);
163793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
164793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    // Use maximum result matrix block size for the estimated DFT block size
165793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    block_size.width = std::min(dft_size.width - templ_size.width + 1, result_size.width);
166793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    block_size.height = std::min(dft_size.height - templ_size.height + 1, result_size.height);
167793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
168793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
169793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic bool convolve_dft(InputArray _image, InputArray _templ, OutputArray _result)
170793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
171793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ConvolveBuf buf;
172793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CV_Assert(_image.type() == CV_32F);
173793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CV_Assert(_templ.type() == CV_32F);
174793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
175793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    buf.create(_image.size(), _templ.size());
176793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    _result.create(buf.result_size, CV_32F);
177793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
178793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat image  = _image.getUMat();
179793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat templ  = _templ.getUMat();
180793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
181793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat result = _result.getUMat();
182793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
183793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Size& block_size = buf.block_size;
184793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Size& dft_size = buf.dft_size;
185793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
186793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat& image_block = buf.image_block;
187793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat& templ_block = buf.templ_block;
188793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat& result_data = buf.result_data;
189793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
190793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat& image_spect = buf.image_spect;
191793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat& templ_spect = buf.templ_spect;
192793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat& result_spect = buf.result_spect;
193793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
194793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat templ_roi = templ;
195793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    copyMakeBorder(templ_roi, templ_block, 0, templ_block.rows - templ_roi.rows, 0,
196793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                   templ_block.cols - templ_roi.cols, BORDER_ISOLATED);
197793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
198793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    dft(templ_block, templ_spect, 0, templ.rows);
199793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
200793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    // Process all blocks of the result matrix
201793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for (int y = 0; y < result.rows; y += block_size.height)
202793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
203793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        for (int x = 0; x < result.cols; x += block_size.width)
204793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
205793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            Size image_roi_size(std::min(x + dft_size.width, image.cols) - x,
206793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                std::min(y + dft_size.height, image.rows) - y);
207793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            Rect roi0(x, y, image_roi_size.width, image_roi_size.height);
208793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
209793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            UMat image_roi(image, roi0);
210793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
211793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            copyMakeBorder(image_roi, image_block, 0, image_block.rows - image_roi.rows,
212793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                           0, image_block.cols - image_roi.cols, BORDER_ISOLATED);
213793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
214793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            dft(image_block, image_spect, 0);
215793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
216793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            mulSpectrums(image_spect, templ_spect, result_spect, 0, true);
217793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
218793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            dft(result_spect, result_data, cv::DFT_INVERSE | cv::DFT_REAL_OUTPUT | cv::DFT_SCALE);
219793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
220793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            Size result_roi_size(std::min(x + block_size.width, result.cols) - x,
221793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                 std::min(y + block_size.height, result.rows) - y);
222793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
223793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            Rect roi1(x, y, result_roi_size.width, result_roi_size.height);
224793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            Rect roi2(0, 0, result_roi_size.width, result_roi_size.height);
225793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
226793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            UMat result_roi(result, roi1);
227793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            UMat result_block(result_data, roi2);
228793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
229793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            result_block.copyTo(result_roi);
230793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
231793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
232793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return true;
233793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
234793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
235793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic bool convolve_32F(InputArray _image, InputArray _templ, OutputArray _result)
236793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
237793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    _result.create(_image.rows() - _templ.rows() + 1, _image.cols() - _templ.cols() + 1, CV_32F);
238793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
239793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (_image.channels() == 1)
240793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return(convolve_dft(_image, _templ, _result));
241793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    else
242793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
243793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        UMat image = _image.getUMat();
244793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        UMat templ = _templ.getUMat();
245793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        UMat result_(image.rows-templ.rows+1,(image.cols-templ.cols+1)*image.channels(), CV_32F);
246793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        bool ok = convolve_dft(image.reshape(1), templ.reshape(1), result_);
247793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if (ok==false)
248793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            return false;
249793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        UMat result = _result.getUMat();
250793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return (extractFirstChannel_32F(result_, _result, _image.channels()));
251793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
252793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
253793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
254793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic bool matchTemplateNaive_CCORR(InputArray _image, InputArray _templ, OutputArray _result)
255793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
256793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int type = _image.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
257793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int wdepth = CV_32F, wtype = CV_MAKE_TYPE(wdepth, cn);
258793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
259793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ocl::Device dev = ocl::Device::getDefault();
260793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int pxPerWIx = (cn==1 && dev.isIntel() && (dev.type() & ocl::Device::TYPE_GPU)) ? 4 : 1;
261793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int rated_cn = cn;
262793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int wtype1 = wtype;
263793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
264793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (pxPerWIx!=1)
265793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
266793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        rated_cn = pxPerWIx;
267793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        type = CV_MAKE_TYPE(depth, rated_cn);
268793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        wtype1 = CV_MAKE_TYPE(wdepth, rated_cn);
269793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
270793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
271793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    char cvt[40];
272793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    char cvt1[40];
273793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    const char* convertToWT1 = ocl::convertTypeStr(depth, wdepth, cn, cvt);
274793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    const char* convertToWT = ocl::convertTypeStr(depth, wdepth, rated_cn, cvt1);
275793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
276793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ocl::Kernel k("matchTemplate_Naive_CCORR", ocl::imgproc::match_template_oclsrc,
277793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                  format("-D CCORR -D T=%s -D T1=%s -D WT=%s -D WT1=%s -D convertToWT=%s -D convertToWT1=%s -D cn=%d -D PIX_PER_WI_X=%d", ocl::typeToStr(type), ocl::typeToStr(depth), ocl::typeToStr(wtype1), ocl::typeToStr(wtype),
278793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                         convertToWT, convertToWT1, cn, pxPerWIx));
279793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (k.empty())
280793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
281793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
282793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat image = _image.getUMat(), templ = _templ.getUMat();
283793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    _result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32FC1);
284793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat result = _result.getUMat();
285793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
286793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    k.args(ocl::KernelArg::ReadOnlyNoSize(image), ocl::KernelArg::ReadOnly(templ),
287793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler           ocl::KernelArg::WriteOnly(result));
288793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
289793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    size_t globalsize[2] = { (result.cols+pxPerWIx-1)/pxPerWIx, result.rows};
290793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return k.run(2, globalsize, NULL, false);
291793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
292793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
293793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
294793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic bool matchTemplate_CCORR(InputArray _image, InputArray _templ, OutputArray _result)
295793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
296793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (useNaive(_templ.size()))
297793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return( matchTemplateNaive_CCORR(_image, _templ, _result));
298793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    else
299793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
300793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if(_image.depth() == CV_8U)
301793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
302793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            UMat imagef, templf;
303793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            UMat image = _image.getUMat();
304793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            UMat templ = _templ.getUMat();
305793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            image.convertTo(imagef, CV_32F);
306793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            templ.convertTo(templf, CV_32F);
307793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            return(convolve_32F(imagef, templf, _result));
308793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
309793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        else
310793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
311793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            return(convolve_32F(_image, _templ, _result));
312793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
313793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
314793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
315793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
316793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic bool matchTemplate_CCORR_NORMED(InputArray _image, InputArray _templ, OutputArray _result)
317793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
318793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    matchTemplate(_image, _templ, _result, CV_TM_CCORR);
319793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
320793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int type = _image.type(), cn = CV_MAT_CN(type);
321793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
322793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ocl::Kernel k("matchTemplate_CCORR_NORMED", ocl::imgproc::match_template_oclsrc,
323793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                  format("-D CCORR_NORMED -D T=%s -D cn=%d", ocl::typeToStr(type), cn));
324793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (k.empty())
325793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
326793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
327793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat image = _image.getUMat(), templ = _templ.getUMat();
328793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    _result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32FC1);
329793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat result = _result.getUMat();
330793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
331793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat image_sums, image_sqsums;
332793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    integral(image.reshape(1), image_sums, image_sqsums, CV_32F, CV_32F);
333793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
334793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat templ_sqsum;
335793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (!sumTemplate(templ, templ_sqsum))
336793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
337793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
338793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    k.args(ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::ReadWrite(result),
339793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler           templ.rows, templ.cols, ocl::KernelArg::PtrReadOnly(templ_sqsum));
340793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
341793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    size_t globalsize[2] = { result.cols, result.rows };
342793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return k.run(2, globalsize, NULL, false);
343793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
344793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
345793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler////////////////////////////////////// SQDIFF //////////////////////////////////////////////////////////////
346793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
347793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic bool matchTemplateNaive_SQDIFF(InputArray _image, InputArray _templ, OutputArray _result)
348793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
349793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int type = _image.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
350793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int wdepth = CV_32F, wtype = CV_MAKE_TYPE(wdepth, cn);
351793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
352793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    char cvt[40];
353793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ocl::Kernel k("matchTemplate_Naive_SQDIFF", ocl::imgproc::match_template_oclsrc,
354793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                  format("-D SQDIFF -D T=%s -D T1=%s -D WT=%s -D convertToWT=%s -D cn=%d", ocl::typeToStr(type), ocl::typeToStr(depth),
355793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                         ocl::typeToStr(wtype), ocl::convertTypeStr(depth, wdepth, cn, cvt), cn));
356793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (k.empty())
357793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
358793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
359793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat image = _image.getUMat(), templ = _templ.getUMat();
360793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    _result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32F);
361793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat result = _result.getUMat();
362793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
363793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    k.args(ocl::KernelArg::ReadOnlyNoSize(image), ocl::KernelArg::ReadOnly(templ),
364793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler           ocl::KernelArg::WriteOnly(result));
365793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
366793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    size_t globalsize[2] = { result.cols, result.rows };
367793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return k.run(2, globalsize, NULL, false);
368793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
369793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
370793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic bool matchTemplate_SQDIFF(InputArray _image, InputArray _templ, OutputArray _result)
371793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
372793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (useNaive(_templ.size()))
373793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return( matchTemplateNaive_SQDIFF(_image, _templ, _result));
374793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    else
375793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
376793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        matchTemplate(_image, _templ, _result, CV_TM_CCORR);
377793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
378793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        int type = _image.type(), cn = CV_MAT_CN(type);
379793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
380793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        ocl::Kernel k("matchTemplate_Prepared_SQDIFF", ocl::imgproc::match_template_oclsrc,
381793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                  format("-D SQDIFF_PREPARED -D T=%s -D cn=%d", ocl::typeToStr(type),  cn));
382793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if (k.empty())
383793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            return false;
384793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
385793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        UMat image = _image.getUMat(), templ = _templ.getUMat();
386793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        _result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32F);
387793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        UMat result = _result.getUMat();
388793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
389793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        UMat image_sums, image_sqsums;
390793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        integral(image.reshape(1), image_sums, image_sqsums, CV_32F, CV_32F);
391793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
392793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        UMat templ_sqsum;
393793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if (!sumTemplate(_templ, templ_sqsum))
394793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            return false;
395793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
396793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        k.args(ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::ReadWrite(result),
397793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler           templ.rows, templ.cols, ocl::KernelArg::PtrReadOnly(templ_sqsum));
398793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
399793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        size_t globalsize[2] = { result.cols, result.rows };
400793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
401793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return k.run(2, globalsize, NULL, false);
402793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
403793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
404793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
405793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic bool matchTemplate_SQDIFF_NORMED(InputArray _image, InputArray _templ, OutputArray _result)
406793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
407793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    matchTemplate(_image, _templ, _result, CV_TM_CCORR);
408793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
409793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int type = _image.type(), cn = CV_MAT_CN(type);
410793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
411793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ocl::Kernel k("matchTemplate_SQDIFF_NORMED", ocl::imgproc::match_template_oclsrc,
412793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                  format("-D SQDIFF_NORMED -D T=%s -D cn=%d", ocl::typeToStr(type),  cn));
413793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (k.empty())
414793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
415793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
416793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat image = _image.getUMat(), templ = _templ.getUMat();
417793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    _result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32F);
418793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat result = _result.getUMat();
419793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
420793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat image_sums, image_sqsums;
421793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    integral(image.reshape(1), image_sums, image_sqsums, CV_32F, CV_32F);
422793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
423793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat templ_sqsum;
424793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (!sumTemplate(_templ, templ_sqsum))
425793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
426793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
427793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    k.args(ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::ReadWrite(result),
428793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler           templ.rows, templ.cols, ocl::KernelArg::PtrReadOnly(templ_sqsum));
429793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
430793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    size_t globalsize[2] = { result.cols, result.rows };
431793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
432793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return k.run(2, globalsize, NULL, false);
433793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
434793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
435793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler///////////////////////////////////// CCOEFF /////////////////////////////////////////////////////////////////
436793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
437793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic bool matchTemplate_CCOEFF(InputArray _image, InputArray _templ, OutputArray _result)
438793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
439793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    matchTemplate(_image, _templ, _result, CV_TM_CCORR);
440793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
441793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat image_sums, temp;
442793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    integral(_image, image_sums, CV_32F);
443793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
444793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int type = image_sums.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
445793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
446793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ocl::Kernel k("matchTemplate_Prepared_CCOEFF", ocl::imgproc::match_template_oclsrc,
447793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                  format("-D CCOEFF -D T=%s -D T1=%s -D cn=%d", ocl::typeToStr(type), ocl::typeToStr(depth), cn));
448793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (k.empty())
449793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
450793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
451793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat templ  = _templ.getUMat();
452793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat result = _result.getUMat();
453793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
454793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (cn==1)
455793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
456793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        Scalar templMean = mean(templ);
457793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        float templ_sum = (float)templMean[0];
458793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
459793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::ReadWrite(result), templ.rows, templ.cols, templ_sum);
460793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
461793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    else
462793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
463793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        Vec4f templ_sum = Vec4f::all(0);
464793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        templ_sum = (Vec4f)mean(templ);
465793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
466793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::ReadWrite(result), templ.rows, templ.cols, templ_sum);    }
467793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
468793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    size_t globalsize[2] = { result.cols, result.rows };
469793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return k.run(2, globalsize, NULL, false);
470793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
471793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
472793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic bool matchTemplate_CCOEFF_NORMED(InputArray _image, InputArray _templ, OutputArray _result)
473793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
474793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    matchTemplate(_image, _templ, _result, CV_TM_CCORR);
475793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
476793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat temp, image_sums, image_sqsums;
477793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    integral(_image, image_sums, image_sqsums, CV_32F, CV_32F);
478793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
479793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int type = image_sums.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
480793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
481793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ocl::Kernel k("matchTemplate_CCOEFF_NORMED", ocl::imgproc::match_template_oclsrc,
482793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        format("-D CCOEFF_NORMED -D T=%s -D T1=%s -D cn=%d", ocl::typeToStr(type), ocl::typeToStr(depth), cn));
483793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (k.empty())
484793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
485793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
486793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat templ = _templ.getUMat();
487793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Size size = _image.size(), tsize = templ.size();
488793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    _result.create(size.height - templ.rows + 1, size.width - templ.cols + 1, CV_32F);
489793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat result = _result.getUMat();
490793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
491793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    float scale = 1.f / tsize.area();
492793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
493793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (cn == 1)
494793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
495793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        float templ_sum = (float)sum(templ)[0];
496793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
497793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        multiply(templ, templ, temp, 1, CV_32F);
498793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        float templ_sqsum = (float)sum(temp)[0];
499793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
500793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        templ_sqsum -= scale * templ_sum * templ_sum;
501793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        templ_sum   *= scale;
502793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
503793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if (templ_sqsum < DBL_EPSILON)
504793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
505793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            result = Scalar::all(1);
506793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            return true;
507793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
508793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
509793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::ReadOnlyNoSize(image_sqsums),
510793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                      ocl::KernelArg::ReadWrite(result), templ.rows, templ.cols, scale, templ_sum, templ_sqsum);
511793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
512793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    else
513793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
514793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        Vec4f templ_sum = Vec4f::all(0), templ_sqsum = Vec4f::all(0);
515793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        templ_sum = sum(templ);
516793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
517793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        multiply(templ, templ, temp, 1, CV_32F);
518793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        templ_sqsum = sum(temp);
519793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
520793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        float templ_sqsum_sum = 0;
521793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        for (int i = 0; i < cn; i ++)
522793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            templ_sqsum_sum += templ_sqsum[i] - scale * templ_sum[i] * templ_sum[i];
523793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
524793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        templ_sum *= scale;
525793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
526793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if (templ_sqsum_sum < DBL_EPSILON)
527793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
528793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            result = Scalar::all(1);
529793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            return true;
530793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
531793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
532793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::ReadOnlyNoSize(image_sqsums),
533793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                   ocl::KernelArg::ReadWrite(result), templ.rows, templ.cols, scale,
534793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                   templ_sum, templ_sqsum_sum);    }
535793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
536793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    size_t globalsize[2] = { result.cols, result.rows };
537793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return k.run(2, globalsize, NULL, false);
538793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
539793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
540793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler///////////////////////////////////////////////////////////////////////////////////////////////////////////
541793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
542793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic bool ocl_matchTemplate( InputArray _img, InputArray _templ, OutputArray _result, int method)
543793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
544793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int cn = _img.channels();
545793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
546793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (cn > 4)
547793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
548793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
549793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    typedef bool (*Caller)(InputArray _img, InputArray _templ, OutputArray _result);
550793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
551793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    static const Caller callers[] =
552793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
553793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        matchTemplate_SQDIFF, matchTemplate_SQDIFF_NORMED, matchTemplate_CCORR,
554793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        matchTemplate_CCORR_NORMED, matchTemplate_CCOEFF, matchTemplate_CCOEFF_NORMED
555793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    };
556793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    const Caller caller = callers[method];
557793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
558793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return caller(_img, _templ, _result);
559793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
560793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
561793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif
562793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
563793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#if defined HAVE_IPP
564793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
565793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslertypedef IppStatus (CV_STDCALL * ippimatchTemplate)(const void*, int, IppiSize, const void*, int, IppiSize, Ipp32f* , int , IppEnum , Ipp8u*);
566793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
567793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic bool ipp_crossCorr(const Mat& src, const Mat& tpl, Mat& dst)
568793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
569793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    IppStatus status;
570793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
571793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    IppiSize srcRoiSize = {src.cols,src.rows};
572793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    IppiSize tplRoiSize = {tpl.cols,tpl.rows};
573793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
574793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Ipp8u *pBuffer;
575793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int bufSize=0;
576793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
577793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int depth = src.depth();
578793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
579793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ippimatchTemplate ippFunc =
580793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            depth==CV_8U ? (ippimatchTemplate)ippiCrossCorrNorm_8u32f_C1R:
581793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            depth==CV_32F? (ippimatchTemplate)ippiCrossCorrNorm_32f_C1R: 0;
582793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
583793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (ippFunc==0)
584793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
585793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
586793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    IppEnum funCfg = (IppEnum)(ippAlgAuto | ippiNormNone | ippiROIValid);
587793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
588793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    status = ippiCrossCorrNormGetBufferSize(srcRoiSize, tplRoiSize, funCfg, &bufSize);
589793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if ( status < 0 )
590793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
591793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
592793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    pBuffer = ippsMalloc_8u( bufSize );
593793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
594793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    status = ippFunc(src.ptr(), (int)src.step, srcRoiSize, tpl.ptr(), (int)tpl.step, tplRoiSize, dst.ptr<Ipp32f>(), (int)dst.step, funCfg, pBuffer);
595793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
596793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ippsFree( pBuffer );
597793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return status >= 0;
598793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
599793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
600793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic bool ipp_sqrDistance(const Mat& src, const Mat& tpl, Mat& dst)
601793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
602793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    IppStatus status;
603793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
604793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    IppiSize srcRoiSize = {src.cols,src.rows};
605793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    IppiSize tplRoiSize = {tpl.cols,tpl.rows};
606793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
607793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Ipp8u *pBuffer;
608793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int bufSize=0;
609793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
610793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int depth = src.depth();
611793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
612793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ippimatchTemplate ippFunc =
613793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            depth==CV_8U ? (ippimatchTemplate)ippiSqrDistanceNorm_8u32f_C1R:
614793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            depth==CV_32F? (ippimatchTemplate)ippiSqrDistanceNorm_32f_C1R: 0;
615793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
616793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (ippFunc==0)
617793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
618793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
619793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    IppEnum funCfg = (IppEnum)(ippAlgAuto | ippiNormNone | ippiROIValid);
620793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
621793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    status = ippiSqrDistanceNormGetBufferSize(srcRoiSize, tplRoiSize, funCfg, &bufSize);
622793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if ( status < 0 )
623793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
624793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
625793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    pBuffer = ippsMalloc_8u( bufSize );
626793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
627793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    status = ippFunc(src.ptr(), (int)src.step, srcRoiSize, tpl.ptr(), (int)tpl.step, tplRoiSize, dst.ptr<Ipp32f>(), (int)dst.step, funCfg, pBuffer);
628793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
629793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ippsFree( pBuffer );
630793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return status >= 0;
631793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
632793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
633793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif
634793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
635793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid crossCorr( const Mat& img, const Mat& _templ, Mat& corr,
636793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                Size corrsize, int ctype,
637793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                Point anchor, double delta, int borderType )
638793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
639793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    const double blockScale = 4.5;
640793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    const int minBlockSize = 256;
641793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    std::vector<uchar> buf;
642793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
643793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Mat templ = _templ;
644793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int depth = img.depth(), cn = img.channels();
645793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int tdepth = templ.depth(), tcn = templ.channels();
646793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int cdepth = CV_MAT_DEPTH(ctype), ccn = CV_MAT_CN(ctype);
647793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
648793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CV_Assert( img.dims <= 2 && templ.dims <= 2 && corr.dims <= 2 );
649793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
650793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if( depth != tdepth && tdepth != std::max(CV_32F, depth) )
651793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
652793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        _templ.convertTo(templ, std::max(CV_32F, depth));
653793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        tdepth = templ.depth();
654793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
655793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
656793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CV_Assert( depth == tdepth || tdepth == CV_32F);
657793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CV_Assert( corrsize.height <= img.rows + templ.rows - 1 &&
658793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler               corrsize.width <= img.cols + templ.cols - 1 );
659793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
660793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CV_Assert( ccn == 1 || delta == 0 );
661793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
662793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    corr.create(corrsize, ctype);
663793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
664793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int maxDepth = depth > CV_8S ? CV_64F : std::max(std::max(CV_32F, tdepth), cdepth);
665793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Size blocksize, dftsize;
666793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
667793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    blocksize.width = cvRound(templ.cols*blockScale);
668793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    blocksize.width = std::max( blocksize.width, minBlockSize - templ.cols + 1 );
669793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    blocksize.width = std::min( blocksize.width, corr.cols );
670793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    blocksize.height = cvRound(templ.rows*blockScale);
671793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    blocksize.height = std::max( blocksize.height, minBlockSize - templ.rows + 1 );
672793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    blocksize.height = std::min( blocksize.height, corr.rows );
673793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
674793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    dftsize.width = std::max(getOptimalDFTSize(blocksize.width + templ.cols - 1), 2);
675793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    dftsize.height = getOptimalDFTSize(blocksize.height + templ.rows - 1);
676793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if( dftsize.width <= 0 || dftsize.height <= 0 )
677793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        CV_Error( CV_StsOutOfRange, "the input arrays are too big" );
678793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
679793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    // recompute block size
680793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    blocksize.width = dftsize.width - templ.cols + 1;
681793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    blocksize.width = MIN( blocksize.width, corr.cols );
682793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    blocksize.height = dftsize.height - templ.rows + 1;
683793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    blocksize.height = MIN( blocksize.height, corr.rows );
684793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
685793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Mat dftTempl( dftsize.height*tcn, dftsize.width, maxDepth );
686793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Mat dftImg( dftsize, maxDepth );
687793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
688793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int i, k, bufSize = 0;
689793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if( tcn > 1 && tdepth != maxDepth )
690793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        bufSize = templ.cols*templ.rows*CV_ELEM_SIZE(tdepth);
691793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
692793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if( cn > 1 && depth != maxDepth )
693793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        bufSize = std::max( bufSize, (blocksize.width + templ.cols - 1)*
694793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            (blocksize.height + templ.rows - 1)*CV_ELEM_SIZE(depth));
695793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
696793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if( (ccn > 1 || cn > 1) && cdepth != maxDepth )
697793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        bufSize = std::max( bufSize, blocksize.width*blocksize.height*CV_ELEM_SIZE(cdepth));
698793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
699793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    buf.resize(bufSize);
700793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
701793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    // compute DFT of each template plane
702793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for( k = 0; k < tcn; k++ )
703793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
704793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        int yofs = k*dftsize.height;
705793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        Mat src = templ;
706793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        Mat dst(dftTempl, Rect(0, yofs, dftsize.width, dftsize.height));
707793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        Mat dst1(dftTempl, Rect(0, yofs, templ.cols, templ.rows));
708793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
709793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if( tcn > 1 )
710793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
711793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            src = tdepth == maxDepth ? dst1 : Mat(templ.size(), tdepth, &buf[0]);
712793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            int pairs[] = {k, 0};
713793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            mixChannels(&templ, 1, &src, 1, pairs, 1);
714793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
715793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
716793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if( dst1.data != src.data )
717793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            src.convertTo(dst1, dst1.depth());
718793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
719793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if( dst.cols > templ.cols )
720793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
721793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            Mat part(dst, Range(0, templ.rows), Range(templ.cols, dst.cols));
722793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            part = Scalar::all(0);
723793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
724793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        dft(dst, dst, 0, templ.rows);
725793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
726793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
727793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int tileCountX = (corr.cols + blocksize.width - 1)/blocksize.width;
728793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int tileCountY = (corr.rows + blocksize.height - 1)/blocksize.height;
729793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int tileCount = tileCountX * tileCountY;
730793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
731793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Size wholeSize = img.size();
732793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Point roiofs(0,0);
733793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Mat img0 = img;
734793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
735793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if( !(borderType & BORDER_ISOLATED) )
736793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
737793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        img.locateROI(wholeSize, roiofs);
738793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        img0.adjustROI(roiofs.y, wholeSize.height-img.rows-roiofs.y,
739793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                       roiofs.x, wholeSize.width-img.cols-roiofs.x);
740793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
741793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    borderType |= BORDER_ISOLATED;
742793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
743793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    // calculate correlation by blocks
744793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for( i = 0; i < tileCount; i++ )
745793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
746793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        int x = (i%tileCountX)*blocksize.width;
747793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        int y = (i/tileCountX)*blocksize.height;
748793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
749793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        Size bsz(std::min(blocksize.width, corr.cols - x),
750793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 std::min(blocksize.height, corr.rows - y));
751793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        Size dsz(bsz.width + templ.cols - 1, bsz.height + templ.rows - 1);
752793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        int x0 = x - anchor.x + roiofs.x, y0 = y - anchor.y + roiofs.y;
753793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        int x1 = std::max(0, x0), y1 = std::max(0, y0);
754793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        int x2 = std::min(img0.cols, x0 + dsz.width);
755793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        int y2 = std::min(img0.rows, y0 + dsz.height);
756793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        Mat src0(img0, Range(y1, y2), Range(x1, x2));
757793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        Mat dst(dftImg, Rect(0, 0, dsz.width, dsz.height));
758793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        Mat dst1(dftImg, Rect(x1-x0, y1-y0, x2-x1, y2-y1));
759793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        Mat cdst(corr, Rect(x, y, bsz.width, bsz.height));
760793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
761793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        for( k = 0; k < cn; k++ )
762793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
763793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            Mat src = src0;
764793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            dftImg = Scalar::all(0);
765793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
766793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if( cn > 1 )
767793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            {
768793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                src = depth == maxDepth ? dst1 : Mat(y2-y1, x2-x1, depth, &buf[0]);
769793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                int pairs[] = {k, 0};
770793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                mixChannels(&src0, 1, &src, 1, pairs, 1);
771793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
772793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
773793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if( dst1.data != src.data )
774793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                src.convertTo(dst1, dst1.depth());
775793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
776793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if( x2 - x1 < dsz.width || y2 - y1 < dsz.height )
777793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                copyMakeBorder(dst1, dst, y1-y0, dst.rows-dst1.rows-(y1-y0),
778793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                               x1-x0, dst.cols-dst1.cols-(x1-x0), borderType);
779793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
780793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            dft( dftImg, dftImg, 0, dsz.height );
781793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            Mat dftTempl1(dftTempl, Rect(0, tcn > 1 ? k*dftsize.height : 0,
782793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                         dftsize.width, dftsize.height));
783793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            mulSpectrums(dftImg, dftTempl1, dftImg, 0, true);
784793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            dft( dftImg, dftImg, DFT_INVERSE + DFT_SCALE, bsz.height );
785793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
786793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            src = dftImg(Rect(0, 0, bsz.width, bsz.height));
787793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
788793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if( ccn > 1 )
789793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            {
790793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                if( cdepth != maxDepth )
791793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                {
792793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    Mat plane(bsz, cdepth, &buf[0]);
793793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    src.convertTo(plane, cdepth, 1, delta);
794793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    src = plane;
795793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                }
796793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                int pairs[] = {0, k};
797793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                mixChannels(&src, 1, &cdst, 1, pairs, 1);
798793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
799793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            else
800793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            {
801793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                if( k == 0 )
802793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    src.convertTo(cdst, cdepth, 1, delta);
803793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                else
804793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                {
805793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    if( maxDepth != cdepth )
806793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    {
807793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                        Mat plane(bsz, cdepth, &buf[0]);
808793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                        src.convertTo(plane, cdepth);
809793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                        src = plane;
810793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    }
811793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    add(src, cdst, cdst);
812793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                }
813793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
814793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
815793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
816793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
817793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
818793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void matchTemplateMask( InputArray _img, InputArray _templ, OutputArray _result, int method, InputArray _mask )
819793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
820793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int type = _img.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
821793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CV_Assert( CV_TM_SQDIFF <= method && method <= CV_TM_CCOEFF_NORMED );
822793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CV_Assert( (depth == CV_8U || depth == CV_32F) && type == _templ.type() && _img.dims() <= 2 );
823793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
824793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Mat img = _img.getMat(), templ = _templ.getMat(), mask = _mask.getMat();
825793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int ttype = templ.type(), tdepth = CV_MAT_DEPTH(ttype), tcn = CV_MAT_CN(ttype);
826793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int mtype = img.type(), mdepth = CV_MAT_DEPTH(type), mcn = CV_MAT_CN(mtype);
827793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
828793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (depth == CV_8U)
829793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
830793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        depth = CV_32F;
831793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        type = CV_MAKETYPE(CV_32F, cn);
832793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        img.convertTo(img, type, 1.0 / 255);
833793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
834793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
835793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (tdepth == CV_8U)
836793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
837793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        tdepth = CV_32F;
838793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        ttype = CV_MAKETYPE(CV_32F, tcn);
839793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        templ.convertTo(templ, ttype, 1.0 / 255);
840793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
841793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
842793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (mdepth == CV_8U)
843793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
844793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        mdepth = CV_32F;
845793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        mtype = CV_MAKETYPE(CV_32F, mcn);
846793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        compare(mask, Scalar::all(0), mask, CMP_NE);
847793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        mask.convertTo(mask, mtype, 1.0 / 255);
848793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
849793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
850793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Size corrSize(img.cols - templ.cols + 1, img.rows - templ.rows + 1);
851793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    _result.create(corrSize, CV_32F);
852793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Mat result = _result.getMat();
853793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
854793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Mat img2 = img.mul(img);
855793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Mat mask2 = mask.mul(mask);
856793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Mat mask_templ = templ.mul(mask);
857793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Scalar templMean, templSdv;
858793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
859793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    double templSum2 = 0;
860793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    meanStdDev( mask_templ, templMean, templSdv );
861793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
862793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    templSum2 = templSdv[0]*templSdv[0] + templSdv[1]*templSdv[1] + templSdv[2]*templSdv[2] + templSdv[3]*templSdv[3];
863793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    templSum2 += templMean[0]*templMean[0] + templMean[1]*templMean[1] + templMean[2]*templMean[2] + templMean[3]*templMean[3];
864793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    templSum2 *= ((double)templ.rows * templ.cols);
865793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
866793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (method == CV_TM_SQDIFF)
867793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
868793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        Mat mask2_templ = templ.mul(mask2);
869793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
870793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        Mat corr(corrSize, CV_32F);
871793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        crossCorr( img, mask2_templ, corr, corr.size(), corr.type(), Point(0,0), 0, 0 );
872793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        crossCorr( img2, mask, result, result.size(), result.type(), Point(0,0), 0, 0 );
873793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
874793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        result -= corr * 2;
875793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        result += templSum2;
876793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
877793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    else if (method == CV_TM_CCORR_NORMED)
878793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
879793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if (templSum2 < DBL_EPSILON)
880793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
881793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            result = Scalar::all(1);
882793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            return;
883793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
884793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
885793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        Mat corr(corrSize, CV_32F);
886793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        crossCorr( img2, mask2, corr, corr.size(), corr.type(), Point(0,0), 0, 0 );
887793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        crossCorr( img, mask_templ, result, result.size(), result.type(), Point(0,0), 0, 0 );
888793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
889793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        sqrt(corr, corr);
890793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        result = result.mul(1/corr);
891793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        result /= std::sqrt(templSum2);
892793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
893793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    else
894793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        CV_Error(Error::StsNotImplemented, "");
895793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
896793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
897793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
898793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler////////////////////////////////////////////////////////////////////////////////////////////////////////
899793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
900793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid cv::matchTemplate( InputArray _img, InputArray _templ, OutputArray _result, int method, InputArray _mask )
901793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
902793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (!_mask.empty())
903793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
904793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        cv::matchTemplateMask(_img, _templ, _result, method, _mask);
905793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return;
906793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
907793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
908793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int type = _img.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
909793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CV_Assert( CV_TM_SQDIFF <= method && method <= CV_TM_CCOEFF_NORMED );
910793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CV_Assert( (depth == CV_8U || depth == CV_32F) && type == _templ.type() && _img.dims() <= 2 );
911793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
912793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    bool needswap = _img.size().height < _templ.size().height || _img.size().width < _templ.size().width;
913793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (needswap)
914793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
915793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        CV_Assert(_img.size().height <= _templ.size().height && _img.size().width <= _templ.size().width);
916793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
917793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
918793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CV_OCL_RUN(_img.dims() <= 2 && _result.isUMat(),
919793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler               (!needswap ? ocl_matchTemplate(_img, _templ, _result, method) : ocl_matchTemplate(_templ, _img, _result, method)))
920793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
921793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int numType = method == CV_TM_CCORR || method == CV_TM_CCORR_NORMED ? 0 :
922793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                  method == CV_TM_CCOEFF || method == CV_TM_CCOEFF_NORMED ? 1 : 2;
923793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    bool isNormed = method == CV_TM_CCORR_NORMED ||
924793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    method == CV_TM_SQDIFF_NORMED ||
925793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    method == CV_TM_CCOEFF_NORMED;
926793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
927793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Mat img = _img.getMat(), templ = _templ.getMat();
928793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (needswap)
929793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        std::swap(img, templ);
930793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
931793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Size corrSize(img.cols - templ.cols + 1, img.rows - templ.rows + 1);
932793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    _result.create(corrSize, CV_32F);
933793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Mat result = _result.getMat();
934793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
935793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#ifdef HAVE_TEGRA_OPTIMIZATION
936793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (tegra::useTegra() && tegra::matchTemplate(img, templ, result, method))
937793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return;
938793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif
939793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
940793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#if defined HAVE_IPP
941793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    bool useIppMT = false;
942793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CV_IPP_CHECK()
943793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
944793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        useIppMT = (templ.rows < img.rows/2 && templ.cols < img.cols/2);
945793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
946793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if (method == CV_TM_SQDIFF && cn == 1 && useIppMT)
947793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
948793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if (ipp_sqrDistance(img, templ, result))
949793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            {
950793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                CV_IMPL_ADD(CV_IMPL_IPP);
951793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                return;
952793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
953793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            setIppErrorStatus();
954793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
955793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
956793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif
957793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
958793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#if defined HAVE_IPP
959793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (cn == 1 && useIppMT)
960793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
961793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if (!ipp_crossCorr(img, templ, result))
962793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
963793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            setIppErrorStatus();
964793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            crossCorr( img, templ, result, result.size(), result.type(), Point(0,0), 0, 0);
965793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
966793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        else
967793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
968793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            CV_IMPL_ADD(CV_IMPL_IPP);
969793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
970793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
971793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    else
972793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif
973793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    crossCorr( img, templ, result, result.size(), result.type(), Point(0,0), 0, 0);
974793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
975793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if( method == CV_TM_CCORR )
976793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return;
977793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
978793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    double invArea = 1./((double)templ.rows * templ.cols);
979793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
980793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Mat sum, sqsum;
981793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Scalar templMean, templSdv;
982793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    double *q0 = 0, *q1 = 0, *q2 = 0, *q3 = 0;
983793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    double templNorm = 0, templSum2 = 0;
984793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
985793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if( method == CV_TM_CCOEFF )
986793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
987793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        integral(img, sum, CV_64F);
988793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        templMean = mean(templ);
989793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
990793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    else
991793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
992793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        integral(img, sum, sqsum, CV_64F);
993793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        meanStdDev( templ, templMean, templSdv );
994793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
995793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        templNorm = templSdv[0]*templSdv[0] + templSdv[1]*templSdv[1] + templSdv[2]*templSdv[2] + templSdv[3]*templSdv[3];
996793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
997793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if( templNorm < DBL_EPSILON && method == CV_TM_CCOEFF_NORMED )
998793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
999793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            result = Scalar::all(1);
1000793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            return;
1001793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
1002793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1003793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        templSum2 = templNorm + templMean[0]*templMean[0] + templMean[1]*templMean[1] + templMean[2]*templMean[2] + templMean[3]*templMean[3];
1004793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1005793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if( numType != 1 )
1006793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
1007793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            templMean = Scalar::all(0);
1008793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            templNorm = templSum2;
1009793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
1010793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1011793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        templSum2 /= invArea;
1012793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        templNorm = std::sqrt(templNorm);
1013793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        templNorm /= std::sqrt(invArea); // care of accuracy here
1014793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1015793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        q0 = (double*)sqsum.data;
1016793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        q1 = q0 + templ.cols*cn;
1017793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        q2 = (double*)(sqsum.data + templ.rows*sqsum.step);
1018793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        q3 = q2 + templ.cols*cn;
1019793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
1020793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1021793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    double* p0 = (double*)sum.data;
1022793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    double* p1 = p0 + templ.cols*cn;
1023793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    double* p2 = (double*)(sum.data + templ.rows*sum.step);
1024793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    double* p3 = p2 + templ.cols*cn;
1025793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1026793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int sumstep = sum.data ? (int)(sum.step / sizeof(double)) : 0;
1027793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int sqstep = sqsum.data ? (int)(sqsum.step / sizeof(double)) : 0;
1028793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1029793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int i, j, k;
1030793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1031793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for( i = 0; i < result.rows; i++ )
1032793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
1033793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        float* rrow = result.ptr<float>(i);
1034793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        int idx = i * sumstep;
1035793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        int idx2 = i * sqstep;
1036793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1037793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        for( j = 0; j < result.cols; j++, idx += cn, idx2 += cn )
1038793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
1039793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            double num = rrow[j], t;
1040793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            double wndMean2 = 0, wndSum2 = 0;
1041793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1042793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if( numType == 1 )
1043793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            {
1044793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                for( k = 0; k < cn; k++ )
1045793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                {
1046793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    t = p0[idx+k] - p1[idx+k] - p2[idx+k] + p3[idx+k];
1047793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    wndMean2 += t*t;
1048793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    num -= t*templMean[k];
1049793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                }
1050793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1051793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                wndMean2 *= invArea;
1052793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
1053793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1054793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if( isNormed || numType == 2 )
1055793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            {
1056793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                for( k = 0; k < cn; k++ )
1057793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                {
1058793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    t = q0[idx2+k] - q1[idx2+k] - q2[idx2+k] + q3[idx2+k];
1059793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    wndSum2 += t;
1060793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                }
1061793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1062793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                if( numType == 2 )
1063793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                {
1064793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    num = wndSum2 - 2*num + templSum2;
1065793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    num = MAX(num, 0.);
1066793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                }
1067793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
1068793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1069793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if( isNormed )
1070793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            {
1071793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                t = std::sqrt(MAX(wndSum2 - wndMean2,0))*templNorm;
1072793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                if( fabs(num) < t )
1073793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    num /= t;
1074793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                else if( fabs(num) < t*1.125 )
1075793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    num = num > 0 ? 1 : -1;
1076793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                else
1077793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    num = method != CV_TM_SQDIFF_NORMED ? 0 : 1;
1078793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
1079793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1080793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            rrow[j] = (float)num;
1081793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
1082793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
1083793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
1084793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1085793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1086793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerCV_IMPL void
1087793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslercvMatchTemplate( const CvArr* _img, const CvArr* _templ, CvArr* _result, int method )
1088793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
1089793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    cv::Mat img = cv::cvarrToMat(_img), templ = cv::cvarrToMat(_templ),
1090793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        result = cv::cvarrToMat(_result);
1091793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CV_Assert( result.size() == cv::Size(std::abs(img.cols - templ.cols) + 1,
1092793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                         std::abs(img.rows - templ.rows) + 1) &&
1093793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler              result.type() == CV_32F );
1094793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    matchTemplate(img, templ, result, method);
1095793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
1096793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1097793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* End of file. */
1098