Repository: opencv
Issue:  HOGDescriptor/Detection produces inconsistent results between CPU and OpenCL implementations
Labels: bug,category: objdetect,affected: 3.4,category: t-api

<!--
If you have a question rather than reporting a bug please go to http://answers.opencv.org where you get much faster responses.
If you need further assistance please read [How To Contribute](https://github.com/Itseez/opencv/wiki/How_to_contribute).

This is a template helping you to create an issue which can be processed as quickly as possible. This is the bug reporting section for the OpenCV library.
-->
##### System information (version)
- OpenCV => 3.0.0
- Operating System / Platform => Debian testing
- Compiler => gcc 5.4
##### Detailed description

We have been using a custom SVM in conjunction with the HOGDescriptor. The system seems to work as intended when run on the CPU (the default code path). Since the HOG is one of the bottlenecks in our applications, we decided to try offload the computation on to the GPU by using the HOG OpenCL kernel (with the new T-API inteterface this was only a few lines of code) - however this has lead to the system no longer working. The system returns zero detections.

I've suspected it's related to the SVM and the input images. Since we aren't detecting pedestrians the ratios and image sizes are different from the default

The next step was isolating the issue in a small unit test and confirmed that the detector returns  different results between OpenCL and the CPU code.

The last step was reproducing these inconsistent results using the default SVM. After many iterations I was able to get the default HOG to output different numbers for OpenCL and the CPU code.

The attached code demonstrates it. However in the default case this seems to be an extreme edge case that's doesn't come up as readily as with our custom SVM. As you can see I rescale in the put image by the magic number 1.199009. Nonetheless I think it's directly related to our issue.

Looking and visually comparing the kernel code to the CPU code is unfortunately a bit too difficult for me, so I'm asking for the community's help with this issue.
Is this a known limitation of the OpenCV HOG OpenCL kernel?
Is this a bug?
Are there restrictions on the dimensions of the SVM and the input image?
##### Steps to reproduce

the output will read:

```
locations found by CPU: 1
first location is:  x - 349 y - 148 in: 0.28912 seconds
locations found by OCL/GPU: 0
```

You will need the input image called larroquette.png which comes with OpenCV (or OpenCV extras) and modify the imread(..) line accordingly

``` .cpp
#include <opencv2/opencv.hpp>
#include <opencv2/core/ocl.hpp>
#include <chrono>
using namespace cv;
using namespace std::chrono;

main()
{
        cv::HOGDescriptor my_hog_descriptor_on_CPU;
        std::vector<cv::Rect> found_locations_by_CPU;

        cv::HOGDescriptor my_hog_descriptor_on_GPU;
        std::vector<cv::Rect> found_locations_by_OCL;

        my_hog_descriptor_on_CPU.setSVMDetector( HOGDescriptor::getDefaultPeopleDetector() );
        my_hog_descriptor_on_GPU.setSVMDetector( HOGDescriptor::getDefaultPeopleDetector() );

        UMat color_image;
        imread( "[PATH_TO_OPENCV]/opencv-3.0.0/bin/cv/cascadeandhog/images/larroquette.png",
                1  ).copyTo(color_image);
        UMat gray_image;
        cv::cvtColor(color_image, gray_image, cv::COLOR_BGR2GRAY);

        auto  m_DownSampleRate = 1.1990036;//1.199009;
        cv::resize(gray_image, gray_image, Size(), 1/m_DownSampleRate, 1/m_DownSampleRate);

        ocl::setUseOpenCL(false);
        auto startCPU = high_resolution_clock::now();
        my_hog_descriptor_on_CPU.detectMultiScale(gray_image, found_locations_by_CPU, 0.);
        auto stopCPU = high_resolution_clock::now();

        ocl::setUseOpenCL(true);
        auto startOCL = high_resolution_clock::now();
        my_hog_descriptor_on_GPU.detectMultiScale(gray_image, found_locations_by_OCL, 0.);
        auto stopOCL = high_resolution_clock::now();

        std::cout << "locations found by CPU: " << found_locations_by_CPU.size()
                  << std::endl;
        if( !found_locations_by_CPU.empty() )
        {
          std::cout << "first location is:  x - "
                  << found_locations_by_CPU.begin()->x
                  << " y - "
                  << found_locations_by_CPU.begin()->y
                  << " in: " <<duration_cast<duration<double>>(stopCPU - startCPU).count() << " seconds"
                  << std::endl;
        }
        std::cout << "locations found by OCL/GPU: " << found_locations_by_OCL.size()
                  << std::endl;
        if( !found_locations_by_OCL.empty() )
        {
          std::cout << "first location is:  x - "
                  << found_locations_by_OCL.begin()->x
                  << " y - "
                  << found_locations_by_OCL.begin()->y
                  << " in: " <<duration_cast<duration<double>>(stopOCL - startOCL).count() << " seconds"
                  << std::endl;
        }
        return 0;
}
```