Repository: opencv
Issue: matchTemplate return wrong results with OpenCL
Labels: bug,category: imgproc,affected: 3.4,category: t-api

##### System information (version)
- OpenCV => 3.1
- Operating System / Platform => Windows 10 64bit
- Compiler => gcc 5.3.0
- GPU => GTX970, but same results with 660Ti and Intel's built-in
##### Detailed description

cv::matchTemplate the function with methods TM_CCOEFF_NORMED and TM_CCOEFF returns incorrect results when OpenCL is used. It corrupts the result towards the bottom right of the image. As an example - this is the input:
![img_test](https://cloud.githubusercontent.com/assets/1474290/19024104/287a1266-8905-11e6-90b3-3a197e5dce35.png)
This is the template:
![template](https://cloud.githubusercontent.com/assets/1474290/19024107/388a1764-8905-11e6-8ffe-d90e0ee6c2ba.png)
And this is the output:
![bug_out](https://cloud.githubusercontent.com/assets/1474290/19024118/62981fa6-8905-11e6-85fd-251baf2355d8.png)
While the correct output (if OpenCL is disabled via code or environment variable) is this:
![good_out](https://cloud.githubusercontent.com/assets/1474290/19024126/9116b752-8905-11e6-8edb-84f16474455c.png)

I have tried several things to find the cause:
1) Power-of-two sizes for the input and/or template. While it seems to reduce the bug in some cases (like it is gone in 512x512 input resolutions) it is still visible at others (like 1024x1024).
2) Different formats - like 32F, 8UC1 and 8UC3. Got the same bug in all of them.
3) Different templates - both loaded as images and generated from code via getGaussianKernel. There seem to be some correlation with the kernel here. Some kernels return less corrupt image or even a correct one. Like this kernel works fine:
![template](https://cloud.githubusercontent.com/assets/1474290/19024173/845a12c4-8906-11e6-9f07-a0d11948f06c.png)
4) Different matchTemplate methods. The bug is showing only with TM_CCOEFF_NORMED and TM_CCOEFF methods. It seems to work fine (at least with the current image and template) with the other four methods.
##### Steps to reproduce

``` .cpp
#include <opencv2/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/core/ocl.hpp>

int main(int argc, char* argv[]){
  cv::ocl::setUseOpenCL(true);

  cv::Mat frame_cpu, template_cpu;
  cv::UMat frame, frame_gray, frame_float;
  cv::UMat template_in, template_gray, template_float;
  cv::UMat result;

  // Prepare kernel
  int kernelSize = 13;
  double sigmaX = sqrt(8);
  double sigmaY = sqrt(8);

  cv::Mat kernelX = cv::getGaussianKernel(kernelSize, sigmaX, CV_32F); 
  cv::Mat kernelY = cv::getGaussianKernel(kernelSize, sigmaY, CV_32F); 
  cv::Mat gkernel = (1.0-kernelX*kernelY.t()*9.0);
  cv::UMat ukernel;
  gkernel.copyTo(ukernel);

  frame_cpu = cv::imread("img_test.png");
  template_cpu = cv::imread("template.png");

  frame_cpu.copyTo(frame);
  template_cpu.copyTo(template_in);

  cv::cvtColor(frame, frame_gray, cv::COLOR_BGR2GRAY);
  cv::cvtColor(template_in, template_gray, cv::COLOR_BGR2GRAY);

  frame_gray.convertTo(frame_float, CV_32F);
  template_gray.convertTo(template_float, CV_32F);

  // Either template_float or ukernel can be used as template here
  cv::matchTemplate(frame_float, template_float, result, cv::TM_CCOEFF_NORMED);

  cv::imshow("result", result);

  cv::waitKey(0);
  return 0;
}
```