• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                           License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
15 // Third party copyrights are property of their respective owners.
16 //
17 // Redistribution and use in source and binary forms, with or without modification,
18 // are permitted provided that the following conditions are met:
19 //
20 //   * Redistribution's of source code must retain the above copyright notice,
21 //     this list of conditions and the following disclaimer.
22 //
23 //   * Redistribution's in binary form must reproduce the above copyright notice,
24 //     this list of conditions and the following disclaimer in the documentation
25 //     and/or other materials provided with the distribution.
26 //
27 //   * The name of the copyright holders may not be used to endorse or promote products
28 //     derived from this software without specific prior written permission.
29 //
30 // This software is provided by the copyright holders and contributors "as is" and
31 // any express or implied warranties, including, but not limited to, the implied
32 // warranties of merchantability and fitness for a particular purpose are disclaimed.
33 // In no event shall the Intel Corporation or contributors be liable for any direct,
34 // indirect, incidental, special, exemplary, or consequential damages
35 // (including, but not limited to, procurement of substitute goods or services;
36 // loss of use, data, or profits; or business interruption) however caused
37 // and on any theory of liability, whether in contract, strict liability,
38 // or tort (including negligence or otherwise) arising in any way out of
39 // the use of this software, even if advised of the possibility of such damage.
40 //
41 //M*/
42 
43 #include "precomp.hpp"
44 #include "cascadedetect.hpp"
45 #include "opencv2/core/core_c.h"
46 #include "opencl_kernels_objdetect.hpp"
47 
48 #include <cstdio>
49 #include <iterator>
50 #include <limits>
51 
52 /****************************************************************************************\
53       The code below is implementation of HOG (Histogram-of-Oriented Gradients)
54       descriptor and object detection, introduced by Navneet Dalal and Bill Triggs.
55 
56       The computed feature vectors are compatible with the
57       INRIA Object Detection and Localization Toolkit
58       (http://pascal.inrialpes.fr/soft/olt/)
59 \****************************************************************************************/
60 
61 namespace cv
62 {
63 
64 #define NTHREADS 256
65 
66 enum {DESCR_FORMAT_COL_BY_COL, DESCR_FORMAT_ROW_BY_ROW};
67 
numPartsWithin(int size,int part_size,int stride)68 static int numPartsWithin(int size, int part_size, int stride)
69 {
70     return (size - part_size + stride) / stride;
71 }
72 
numPartsWithin(cv::Size size,cv::Size part_size,cv::Size stride)73 static Size numPartsWithin(cv::Size size, cv::Size part_size,
74                                                 cv::Size stride)
75 {
76     return Size(numPartsWithin(size.width, part_size.width, stride.width),
77         numPartsWithin(size.height, part_size.height, stride.height));
78 }
79 
getBlockHistogramSize(Size block_size,Size cell_size,int nbins)80 static size_t getBlockHistogramSize(Size block_size, Size cell_size, int nbins)
81 {
82     Size cells_per_block = Size(block_size.width / cell_size.width,
83         block_size.height / cell_size.height);
84     return (size_t)(nbins * cells_per_block.area());
85 }
86 
getDescriptorSize() const87 size_t HOGDescriptor::getDescriptorSize() const
88 {
89     CV_Assert(blockSize.width % cellSize.width == 0 &&
90         blockSize.height % cellSize.height == 0);
91     CV_Assert((winSize.width - blockSize.width) % blockStride.width == 0 &&
92         (winSize.height - blockSize.height) % blockStride.height == 0 );
93 
94     return (size_t)nbins*
95         (blockSize.width/cellSize.width)*
96         (blockSize.height/cellSize.height)*
97         ((winSize.width - blockSize.width)/blockStride.width + 1)*
98         ((winSize.height - blockSize.height)/blockStride.height + 1);
99 }
100 
getWinSigma() const101 double HOGDescriptor::getWinSigma() const
102 {
103     return winSigma >= 0 ? winSigma : (blockSize.width + blockSize.height)/8.;
104 }
105 
checkDetectorSize() const106 bool HOGDescriptor::checkDetectorSize() const
107 {
108     size_t detectorSize = svmDetector.size(), descriptorSize = getDescriptorSize();
109     return detectorSize == 0 ||
110         detectorSize == descriptorSize ||
111         detectorSize == descriptorSize + 1;
112 }
113 
setSVMDetector(InputArray _svmDetector)114 void HOGDescriptor::setSVMDetector(InputArray _svmDetector)
115 {
116     _svmDetector.getMat().convertTo(svmDetector, CV_32F);
117     CV_Assert(checkDetectorSize());
118 
119     Mat detector_reordered(1, (int)svmDetector.size(), CV_32FC1);
120 
121     size_t block_hist_size = getBlockHistogramSize(blockSize, cellSize, nbins);
122     cv::Size blocks_per_img = numPartsWithin(winSize, blockSize, blockStride);
123 
124     for (int i = 0; i < blocks_per_img.height; ++i)
125         for (int j = 0; j < blocks_per_img.width; ++j)
126         {
127             const float *src = &svmDetector[0] + (j * blocks_per_img.height + i) * block_hist_size;
128             float *dst = detector_reordered.ptr<float>() + (i * blocks_per_img.width + j) * block_hist_size;
129             for (size_t k = 0; k < block_hist_size; ++k)
130                 dst[k] = src[k];
131         }
132     size_t descriptor_size = getDescriptorSize();
133     free_coef = svmDetector.size() > descriptor_size ? svmDetector[descriptor_size] : 0;
134     detector_reordered.copyTo(oclSvmDetector);
135 }
136 
137 #define CV_TYPE_NAME_HOG_DESCRIPTOR "opencv-object-detector-hog"
138 
read(FileNode & obj)139 bool HOGDescriptor::read(FileNode& obj)
140 {
141     if( !obj.isMap() )
142         return false;
143     FileNodeIterator it = obj["winSize"].begin();
144     it >> winSize.width >> winSize.height;
145     it = obj["blockSize"].begin();
146     it >> blockSize.width >> blockSize.height;
147     it = obj["blockStride"].begin();
148     it >> blockStride.width >> blockStride.height;
149     it = obj["cellSize"].begin();
150     it >> cellSize.width >> cellSize.height;
151     obj["nbins"] >> nbins;
152     obj["derivAperture"] >> derivAperture;
153     obj["winSigma"] >> winSigma;
154     obj["histogramNormType"] >> histogramNormType;
155     obj["L2HysThreshold"] >> L2HysThreshold;
156     obj["gammaCorrection"] >> gammaCorrection;
157     obj["nlevels"] >> nlevels;
158     if (obj["signedGradient"].empty())
159         signedGradient = false;
160     else
161         obj["signedGradient"] >> signedGradient;
162 
163     FileNode vecNode = obj["SVMDetector"];
164     if( vecNode.isSeq() )
165     {
166         vecNode >> svmDetector;
167         CV_Assert(checkDetectorSize());
168     }
169     return true;
170 }
171 
write(FileStorage & fs,const String & objName) const172 void HOGDescriptor::write(FileStorage& fs, const String& objName) const
173 {
174     if( !objName.empty() )
175         fs << objName;
176 
177     fs << "{" CV_TYPE_NAME_HOG_DESCRIPTOR
178        << "winSize" << winSize
179        << "blockSize" << blockSize
180        << "blockStride" << blockStride
181        << "cellSize" << cellSize
182        << "nbins" << nbins
183        << "derivAperture" << derivAperture
184        << "winSigma" << getWinSigma()
185        << "histogramNormType" << histogramNormType
186        << "L2HysThreshold" << L2HysThreshold
187        << "gammaCorrection" << gammaCorrection
188        << "nlevels" << nlevels
189        << "signedGradient" << signedGradient;
190     if( !svmDetector.empty() )
191         fs << "SVMDetector" << svmDetector;
192     fs << "}";
193 }
194 
load(const String & filename,const String & objname)195 bool HOGDescriptor::load(const String& filename, const String& objname)
196 {
197     FileStorage fs(filename, FileStorage::READ);
198     FileNode obj = !objname.empty() ? fs[objname] : fs.getFirstTopLevelNode();
199     return read(obj);
200 }
201 
save(const String & filename,const String & objName) const202 void HOGDescriptor::save(const String& filename, const String& objName) const
203 {
204     FileStorage fs(filename, FileStorage::WRITE);
205     write(fs, !objName.empty() ? objName : FileStorage::getDefaultObjectName(filename));
206 }
207 
copyTo(HOGDescriptor & c) const208 void HOGDescriptor::copyTo(HOGDescriptor& c) const
209 {
210     c.winSize = winSize;
211     c.blockSize = blockSize;
212     c.blockStride = blockStride;
213     c.cellSize = cellSize;
214     c.nbins = nbins;
215     c.derivAperture = derivAperture;
216     c.winSigma = winSigma;
217     c.histogramNormType = histogramNormType;
218     c.L2HysThreshold = L2HysThreshold;
219     c.gammaCorrection = gammaCorrection;
220     c.svmDetector = svmDetector;
221     c.nlevels = nlevels;
222     c.signedGradient = signedGradient;
223 }
224 
computeGradient(const Mat & img,Mat & grad,Mat & qangle,Size paddingTL,Size paddingBR) const225 void HOGDescriptor::computeGradient(const Mat& img, Mat& grad, Mat& qangle,
226     Size paddingTL, Size paddingBR) const
227 {
228     CV_Assert( img.type() == CV_8U || img.type() == CV_8UC3 );
229 
230     Size gradsize(img.cols + paddingTL.width + paddingBR.width,
231         img.rows + paddingTL.height + paddingBR.height);
232     grad.create(gradsize, CV_32FC2);  // <magnitude*(1-alpha), magnitude*alpha>
233     qangle.create(gradsize, CV_8UC2); // [0..nbins-1] - quantized gradient orientation
234 
235     Size wholeSize;
236     Point roiofs;
237     img.locateROI(wholeSize, roiofs);
238 
239     int i, x, y;
240     int cn = img.channels();
241 
242     Mat_<float> _lut(1, 256);
243     const float* const lut = &_lut(0,0);
244 #if CV_SSE2
245     const int indeces[] = { 0, 1, 2, 3 };
246     __m128i idx = _mm_loadu_si128((const __m128i*)indeces);
247     __m128i ifour = _mm_set1_epi32(4);
248 
249     float* const _data = &_lut(0, 0);
250     if( gammaCorrection )
251         for( i = 0; i < 256; i += 4 )
252         {
253             _mm_storeu_ps(_data + i, _mm_sqrt_ps(_mm_cvtepi32_ps(idx)));
254             idx = _mm_add_epi32(idx, ifour);
255         }
256     else
257         for( i = 0; i < 256; i += 4 )
258         {
259             _mm_storeu_ps(_data + i, _mm_cvtepi32_ps(idx));
260             idx = _mm_add_epi32(idx, ifour);
261         }
262 #else
263     if( gammaCorrection )
264         for( i = 0; i < 256; i++ )
265             _lut(0,i) = std::sqrt((float)i);
266     else
267         for( i = 0; i < 256; i++ )
268             _lut(0,i) = (float)i;
269 #endif
270 
271     AutoBuffer<int> mapbuf(gradsize.width + gradsize.height + 4);
272     int* xmap = (int*)mapbuf + 1;
273     int* ymap = xmap + gradsize.width + 2;
274 
275     const int borderType = (int)BORDER_REFLECT_101;
276 
277     for( x = -1; x < gradsize.width + 1; x++ )
278         xmap[x] = borderInterpolate(x - paddingTL.width + roiofs.x,
279         wholeSize.width, borderType) - roiofs.x;
280     for( y = -1; y < gradsize.height + 1; y++ )
281         ymap[y] = borderInterpolate(y - paddingTL.height + roiofs.y,
282         wholeSize.height, borderType) - roiofs.y;
283 
284     // x- & y- derivatives for the whole row
285     int width = gradsize.width;
286     AutoBuffer<float> _dbuf(width*4);
287     float* const dbuf = _dbuf;
288     Mat Dx(1, width, CV_32F, dbuf);
289     Mat Dy(1, width, CV_32F, dbuf + width);
290     Mat Mag(1, width, CV_32F, dbuf + width*2);
291     Mat Angle(1, width, CV_32F, dbuf + width*3);
292 
293     if (cn == 3)
294     {
295         int end = gradsize.width + 2;
296         xmap -= 1, x = 0;
297 #if CV_SSE2
298         __m128i ithree = _mm_set1_epi32(3);
299         for ( ; x <= end - 4; x += 4)
300             _mm_storeu_si128((__m128i*)(xmap + x), _mm_mullo_epi16(ithree,
301                 _mm_loadu_si128((const __m128i*)(xmap + x))));
302 #endif
303         for ( ; x < end; ++x)
304             xmap[x] *= 3;
305         xmap += 1;
306     }
307 
308     float angleScale = signedGradient ? (float)(nbins/(2.0*CV_PI)) : (float)(nbins/CV_PI);
309     for( y = 0; y < gradsize.height; y++ )
310     {
311         const uchar* imgPtr  = img.ptr(ymap[y]);
312         //In case subimage is used ptr() generates an assert for next and prev rows
313         //(see http://code.opencv.org/issues/4149)
314         const uchar* prevPtr = img.data + img.step*ymap[y-1];
315         const uchar* nextPtr = img.data + img.step*ymap[y+1];
316 
317         float* gradPtr = grad.ptr<float>(y);
318         uchar* qanglePtr = qangle.ptr(y);
319 
320         if( cn == 1 )
321         {
322             for( x = 0; x < width; x++ )
323             {
324                 int x1 = xmap[x];
325                 dbuf[x] = (float)(lut[imgPtr[xmap[x+1]]] - lut[imgPtr[xmap[x-1]]]);
326                 dbuf[width + x] = (float)(lut[nextPtr[x1]] - lut[prevPtr[x1]]);
327             }
328         }
329         else
330         {
331             x = 0;
332 #if CV_SSE2
333             for( ; x <= width - 4; x += 4 )
334             {
335                 int x0 = xmap[x], x1 = xmap[x+1], x2 = xmap[x+2], x3 = xmap[x+3];
336                 typedef const uchar* const T;
337                 T p02 = imgPtr + xmap[x+1], p00 = imgPtr + xmap[x-1];
338                 T p12 = imgPtr + xmap[x+2], p10 = imgPtr + xmap[x];
339                 T p22 = imgPtr + xmap[x+3], p20 = p02;
340                 T p32 = imgPtr + xmap[x+4], p30 = p12;
341 
342                 __m128 _dx0 = _mm_sub_ps(_mm_set_ps(lut[p32[0]], lut[p22[0]], lut[p12[0]], lut[p02[0]]),
343                                          _mm_set_ps(lut[p30[0]], lut[p20[0]], lut[p10[0]], lut[p00[0]]));
344                 __m128 _dx1 = _mm_sub_ps(_mm_set_ps(lut[p32[1]], lut[p22[1]], lut[p12[1]], lut[p02[1]]),
345                                          _mm_set_ps(lut[p30[1]], lut[p20[1]], lut[p10[1]], lut[p00[1]]));
346                 __m128 _dx2 = _mm_sub_ps(_mm_set_ps(lut[p32[2]], lut[p22[2]], lut[p12[2]], lut[p02[2]]),
347                                          _mm_set_ps(lut[p30[2]], lut[p20[2]], lut[p10[2]], lut[p00[2]]));
348 
349                 __m128 _dy0 = _mm_sub_ps(_mm_set_ps(lut[nextPtr[x3]], lut[nextPtr[x2]], lut[nextPtr[x1]], lut[nextPtr[x0]]),
350                                          _mm_set_ps(lut[prevPtr[x3]], lut[prevPtr[x2]], lut[prevPtr[x1]], lut[prevPtr[x0]]));
351                 __m128 _dy1 = _mm_sub_ps(_mm_set_ps(lut[nextPtr[x3+1]], lut[nextPtr[x2+1]], lut[nextPtr[x1+1]], lut[nextPtr[x0+1]]),
352                                          _mm_set_ps(lut[prevPtr[x3+1]], lut[prevPtr[x2+1]], lut[prevPtr[x1+1]], lut[prevPtr[x0+1]]));
353                 __m128 _dy2 = _mm_sub_ps(_mm_set_ps(lut[nextPtr[x3+2]], lut[nextPtr[x2+2]], lut[nextPtr[x1+2]], lut[nextPtr[x0+2]]),
354                                          _mm_set_ps(lut[prevPtr[x3+2]], lut[prevPtr[x2+2]], lut[prevPtr[x1+2]], lut[prevPtr[x0+2]]));
355 
356                 __m128 _mag0 = _mm_add_ps(_mm_mul_ps(_dx0, _dx0), _mm_mul_ps(_dy0, _dy0));
357                 __m128 _mag1 = _mm_add_ps(_mm_mul_ps(_dx1, _dx1), _mm_mul_ps(_dy1, _dy1));
358                 __m128 _mag2 = _mm_add_ps(_mm_mul_ps(_dx2, _dx2), _mm_mul_ps(_dy2, _dy2));
359 
360                 __m128 mask = _mm_cmpgt_ps(_mag2, _mag1);
361                 _dx2 = _mm_or_ps(_mm_and_ps(_dx2, mask), _mm_andnot_ps(mask, _dx1));
362                 _dy2 = _mm_or_ps(_mm_and_ps(_dy2, mask), _mm_andnot_ps(mask, _dy1));
363 
364                 mask = _mm_cmpgt_ps(_mm_max_ps(_mag2, _mag1), _mag0);
365                 _dx2 = _mm_or_ps(_mm_and_ps(_dx2, mask), _mm_andnot_ps(mask, _dx0));
366                 _dy2 = _mm_or_ps(_mm_and_ps(_dy2, mask), _mm_andnot_ps(mask, _dy0));
367 
368                 _mm_storeu_ps(dbuf + x, _dx2);
369                 _mm_storeu_ps(dbuf + x + width, _dy2);
370             }
371 #endif
372             for( ; x < width; x++ )
373             {
374                 int x1 = xmap[x];
375                 float dx0, dy0, dx, dy, mag0, mag;
376                 const uchar* p2 = imgPtr + xmap[x+1];
377                 const uchar* p0 = imgPtr + xmap[x-1];
378 
379                 dx0 = lut[p2[2]] - lut[p0[2]];
380                 dy0 = lut[nextPtr[x1+2]] - lut[prevPtr[x1+2]];
381                 mag0 = dx0*dx0 + dy0*dy0;
382 
383                 dx = lut[p2[1]] - lut[p0[1]];
384                 dy = lut[nextPtr[x1+1]] - lut[prevPtr[x1+1]];
385                 mag = dx*dx + dy*dy;
386                 if( mag0 < mag )
387                 {
388                     dx0 = dx;
389                     dy0 = dy;
390                     mag0 = mag;
391                 }
392 
393                 dx = lut[p2[0]] - lut[p0[0]];
394                 dy = lut[nextPtr[x1]] - lut[prevPtr[x1]];
395                 mag = dx*dx + dy*dy;
396                 if( mag0 < mag )
397                 {
398                     dx0 = dx;
399                     dy0 = dy;
400                     mag0 = mag;
401                 }
402 
403                 dbuf[x] = dx0;
404                 dbuf[x+width] = dy0;
405             }
406         }
407 
408         // computing angles and magnidutes
409         cartToPolar( Dx, Dy, Mag, Angle, false );
410 
411         // filling the result matrix
412         x = 0;
413 #if CV_SSE2
414         __m128 fhalf = _mm_set1_ps(0.5f), fzero = _mm_setzero_ps();
415         __m128 _angleScale = _mm_set1_ps(angleScale), fone = _mm_set1_ps(1.0f);
416         __m128i ione = _mm_set1_epi32(1), _nbins = _mm_set1_epi32(nbins), izero = _mm_setzero_si128();
417 
418         for ( ; x <= width - 4; x += 4)
419         {
420             int x2 = x << 1;
421             __m128 _mag = _mm_loadu_ps(dbuf + x + (width << 1));
422             __m128 _angle = _mm_loadu_ps(dbuf + x + width * 3);
423             _angle = _mm_sub_ps(_mm_mul_ps(_angleScale, _angle), fhalf);
424 
425             __m128 sign = _mm_and_ps(fone, _mm_cmplt_ps(_angle, fzero));
426             __m128i _hidx = _mm_cvttps_epi32(_angle);
427             _hidx = _mm_sub_epi32(_hidx, _mm_cvtps_epi32(sign));
428             _angle = _mm_sub_ps(_angle, _mm_cvtepi32_ps(_hidx));
429 
430             __m128 ft0 = _mm_mul_ps(_mag, _mm_sub_ps(fone, _angle));
431             __m128 ft1 = _mm_mul_ps(_mag, _angle);
432             __m128 ft2 = _mm_unpacklo_ps(ft0, ft1);
433             __m128 ft3 = _mm_unpackhi_ps(ft0, ft1);
434 
435             _mm_storeu_ps(gradPtr + x2, ft2);
436             _mm_storeu_ps(gradPtr + x2 + 4, ft3);
437 
438             __m128i mask0 = _mm_sub_epi32(izero, _mm_srli_epi32(_hidx, 31));
439             __m128i it0 = _mm_and_si128(mask0, _nbins);
440             mask0 = _mm_cmplt_epi32(_hidx, _nbins);
441             __m128i it1 = _mm_andnot_si128(mask0, _nbins);
442             _hidx = _mm_add_epi32(_hidx, _mm_sub_epi32(it0, it1));
443 
444             it0 = _mm_packus_epi16(_mm_packs_epi32(_hidx, izero), izero);
445             _hidx = _mm_add_epi32(ione, _hidx);
446             _hidx = _mm_and_si128(_hidx, _mm_cmplt_epi32(_hidx, _nbins));
447             it1 = _mm_packus_epi16(_mm_packs_epi32(_hidx, izero), izero);
448             it0 = _mm_unpacklo_epi8(it0, it1);
449 
450             _mm_storel_epi64((__m128i*)(qanglePtr + x2), it0);
451         }
452 #endif
453         for( ; x < width; x++ )
454         {
455             float mag = dbuf[x+width*2], angle = dbuf[x+width*3]*angleScale - 0.5f;
456             int hidx = cvFloor(angle);
457             angle -= hidx;
458             gradPtr[x*2] = mag*(1.f - angle);
459             gradPtr[x*2+1] = mag*angle;
460 
461             if( hidx < 0 )
462                 hidx += nbins;
463             else if( hidx >= nbins )
464                 hidx -= nbins;
465 
466             CV_Assert( (unsigned)hidx < (unsigned)nbins );
467 
468             qanglePtr[x*2] = (uchar)hidx;
469             hidx++;
470             hidx &= hidx < nbins ? -1 : 0;
471             qanglePtr[x*2+1] = (uchar)hidx;
472         }
473     }
474 }
475 
476 struct HOGCache
477 {
478     struct BlockData
479     {
BlockDatacv::HOGCache::BlockData480         BlockData() :
481             histOfs(0), imgOffset()
482         { }
483 
484         int histOfs;
485         Point imgOffset;
486     };
487 
488     struct PixData
489     {
490         size_t gradOfs, qangleOfs;
491         int histOfs[4];
492         float histWeights[4];
493         float gradWeight;
494     };
495 
496     HOGCache();
497     HOGCache(const HOGDescriptor* descriptor,
498         const Mat& img, const Size& paddingTL, const Size& paddingBR,
499         bool useCache, const Size& cacheStride);
~HOGCachecv::HOGCache500     virtual ~HOGCache() { }
501     virtual void init(const HOGDescriptor* descriptor,
502         const Mat& img, const Size& paddingTL, const Size& paddingBR,
503         bool useCache, const Size& cacheStride);
504 
505     Size windowsInImage(const Size& imageSize, const Size& winStride) const;
506     Rect getWindow(const Size& imageSize, const Size& winStride, int idx) const;
507 
508     const float* getBlock(Point pt, float* buf);
509     virtual void normalizeBlockHistogram(float* histogram) const;
510 
511     std::vector<PixData> pixData;
512     std::vector<BlockData> blockData;
513 
514     bool useCache;
515     std::vector<int> ymaxCached;
516     Size winSize;
517     Size cacheStride;
518     Size nblocks, ncells;
519     int blockHistogramSize;
520     int count1, count2, count4;
521     Point imgoffset;
522     Mat_<float> blockCache;
523     Mat_<uchar> blockCacheFlags;
524 
525     Mat grad, qangle;
526     const HOGDescriptor* descriptor;
527 };
528 
HOGCache()529 HOGCache::HOGCache() :
530     blockHistogramSize(), count1(), count2(), count4()
531 {
532     useCache = false;
533     descriptor = 0;
534 }
535 
HOGCache(const HOGDescriptor * _descriptor,const Mat & _img,const Size & _paddingTL,const Size & _paddingBR,bool _useCache,const Size & _cacheStride)536 HOGCache::HOGCache(const HOGDescriptor* _descriptor,
537     const Mat& _img, const Size& _paddingTL, const Size& _paddingBR,
538     bool _useCache, const Size& _cacheStride)
539 {
540     init(_descriptor, _img, _paddingTL, _paddingBR, _useCache, _cacheStride);
541 }
542 
init(const HOGDescriptor * _descriptor,const Mat & _img,const Size & _paddingTL,const Size & _paddingBR,bool _useCache,const Size & _cacheStride)543 void HOGCache::init(const HOGDescriptor* _descriptor,
544     const Mat& _img, const Size& _paddingTL, const Size& _paddingBR,
545     bool _useCache, const Size& _cacheStride)
546 {
547     descriptor = _descriptor;
548     cacheStride = _cacheStride;
549     useCache = _useCache;
550 
551     descriptor->computeGradient(_img, grad, qangle, _paddingTL, _paddingBR);
552     imgoffset = _paddingTL;
553 
554     winSize = descriptor->winSize;
555     Size blockSize = descriptor->blockSize;
556     Size blockStride = descriptor->blockStride;
557     Size cellSize = descriptor->cellSize;
558     int i, j, nbins = descriptor->nbins;
559     int rawBlockSize = blockSize.width*blockSize.height;
560 
561     nblocks = Size((winSize.width - blockSize.width)/blockStride.width + 1,
562         (winSize.height - blockSize.height)/blockStride.height + 1);
563     ncells = Size(blockSize.width/cellSize.width, blockSize.height/cellSize.height);
564     blockHistogramSize = ncells.width*ncells.height*nbins;
565 
566     if( useCache )
567     {
568         Size cacheSize((grad.cols - blockSize.width)/cacheStride.width+1,
569             (winSize.height/cacheStride.height)+1);
570 
571         blockCache.create(cacheSize.height, cacheSize.width*blockHistogramSize);
572         blockCacheFlags.create(cacheSize);
573 
574         size_t cacheRows = blockCache.rows;
575         ymaxCached.resize(cacheRows);
576         for(size_t ii = 0; ii < cacheRows; ii++ )
577             ymaxCached[ii] = -1;
578     }
579 
580     Mat_<float> weights(blockSize);
581     float sigma = (float)descriptor->getWinSigma();
582     float scale = 1.f/(sigma*sigma*2);
583 
584     {
585         AutoBuffer<float> di(blockSize.height), dj(blockSize.width);
586         float* _di = (float*)di, *_dj = (float*)dj;
587         float bh = blockSize.height * 0.5f, bw = blockSize.width * 0.5f;
588 
589         i = 0;
590     #if CV_SSE2
591         const int a[] = { 0, 1, 2, 3 };
592         __m128i idx = _mm_loadu_si128((__m128i*)a);
593         __m128 _bw = _mm_set1_ps(bw), _bh = _mm_set1_ps(bh);
594         __m128i ifour = _mm_set1_epi32(4);
595 
596         for (; i <= blockSize.height - 4; i += 4)
597         {
598             __m128 t = _mm_sub_ps(_mm_cvtepi32_ps(idx), _bh);
599             t = _mm_mul_ps(t, t);
600             idx = _mm_add_epi32(idx, ifour);
601             _mm_storeu_ps(_di + i, t);
602         }
603     #endif
604         for ( ; i < blockSize.height; ++i)
605         {
606             _di[i] = i - bh;
607             _di[i] *= _di[i];
608         }
609 
610         j = 0;
611     #if CV_SSE2
612         idx = _mm_loadu_si128((__m128i*)a);
613         for (; j <= blockSize.width - 4; j += 4)
614         {
615             __m128 t = _mm_sub_ps(_mm_cvtepi32_ps(idx), _bw);
616             t = _mm_mul_ps(t, t);
617             idx = _mm_add_epi32(idx, ifour);
618             _mm_storeu_ps(_dj + j, t);
619         }
620     #endif
621         for ( ; j < blockSize.width; ++j)
622         {
623             _dj[j] = j - bw;
624             _dj[j] *= _dj[j];
625         }
626 
627         for(i = 0; i < blockSize.height; i++)
628             for(j = 0; j < blockSize.width; j++)
629                 weights(i,j) = std::exp(-(_di[i] + _dj[j])*scale);
630     }
631 
632     blockData.resize(nblocks.width*nblocks.height);
633     pixData.resize(rawBlockSize*3);
634 
635     // Initialize 2 lookup tables, pixData & blockData.
636     // Here is why:
637     //
638     // The detection algorithm runs in 4 nested loops (at each pyramid layer):
639     //  loop over the windows within the input image
640     //    loop over the blocks within each window
641     //      loop over the cells within each block
642     //        loop over the pixels in each cell
643     //
644     // As each of the loops runs over a 2-dimensional array,
645     // we could get 8(!) nested loops in total, which is very-very slow.
646     //
647     // To speed the things up, we do the following:
648     //   1. loop over windows is unrolled in the HOGDescriptor::{compute|detect} methods;
649     //         inside we compute the current search window using getWindow() method.
650     //         Yes, it involves some overhead (function call + couple of divisions),
651     //         but it's tiny in fact.
652     //   2. loop over the blocks is also unrolled. Inside we use pre-computed blockData[j]
653     //         to set up gradient and histogram pointers.
654     //   3. loops over cells and pixels in each cell are merged
655     //       (since there is no overlap between cells, each pixel in the block is processed once)
656     //      and also unrolled. Inside we use PixData[k] to access the gradient values and
657     //      update the histogram
658     //
659 
660     count1 = count2 = count4 = 0;
661     for( j = 0; j < blockSize.width; j++ )
662         for( i = 0; i < blockSize.height; i++ )
663         {
664             PixData* data = 0;
665             float cellX = (j+0.5f)/cellSize.width - 0.5f;
666             float cellY = (i+0.5f)/cellSize.height - 0.5f;
667             int icellX0 = cvFloor(cellX);
668             int icellY0 = cvFloor(cellY);
669             int icellX1 = icellX0 + 1, icellY1 = icellY0 + 1;
670             cellX -= icellX0;
671             cellY -= icellY0;
672 
673             if( (unsigned)icellX0 < (unsigned)ncells.width &&
674                (unsigned)icellX1 < (unsigned)ncells.width )
675             {
676                 if( (unsigned)icellY0 < (unsigned)ncells.height &&
677                    (unsigned)icellY1 < (unsigned)ncells.height )
678                 {
679                     data = &pixData[rawBlockSize*2 + (count4++)];
680                     data->histOfs[0] = (icellX0*ncells.height + icellY0)*nbins;
681                     data->histWeights[0] = (1.f - cellX)*(1.f - cellY);
682                     data->histOfs[1] = (icellX1*ncells.height + icellY0)*nbins;
683                     data->histWeights[1] = cellX*(1.f - cellY);
684                     data->histOfs[2] = (icellX0*ncells.height + icellY1)*nbins;
685                     data->histWeights[2] = (1.f - cellX)*cellY;
686                     data->histOfs[3] = (icellX1*ncells.height + icellY1)*nbins;
687                     data->histWeights[3] = cellX*cellY;
688                 }
689                 else
690                 {
691                     data = &pixData[rawBlockSize + (count2++)];
692                     if( (unsigned)icellY0 < (unsigned)ncells.height )
693                     {
694                         icellY1 = icellY0;
695                         cellY = 1.f - cellY;
696                     }
697                     data->histOfs[0] = (icellX0*ncells.height + icellY1)*nbins;
698                     data->histWeights[0] = (1.f - cellX)*cellY;
699                     data->histOfs[1] = (icellX1*ncells.height + icellY1)*nbins;
700                     data->histWeights[1] = cellX*cellY;
701                     data->histOfs[2] = data->histOfs[3] = 0;
702                     data->histWeights[2] = data->histWeights[3] = 0;
703                 }
704             }
705             else
706             {
707                 if( (unsigned)icellX0 < (unsigned)ncells.width )
708                 {
709                     icellX1 = icellX0;
710                     cellX = 1.f - cellX;
711                 }
712 
713                 if( (unsigned)icellY0 < (unsigned)ncells.height &&
714                    (unsigned)icellY1 < (unsigned)ncells.height )
715                 {
716                     data = &pixData[rawBlockSize + (count2++)];
717                     data->histOfs[0] = (icellX1*ncells.height + icellY0)*nbins;
718                     data->histWeights[0] = cellX*(1.f - cellY);
719                     data->histOfs[1] = (icellX1*ncells.height + icellY1)*nbins;
720                     data->histWeights[1] = cellX*cellY;
721                     data->histOfs[2] = data->histOfs[3] = 0;
722                     data->histWeights[2] = data->histWeights[3] = 0;
723                 }
724                 else
725                 {
726                     data = &pixData[count1++];
727                     if( (unsigned)icellY0 < (unsigned)ncells.height )
728                     {
729                         icellY1 = icellY0;
730                         cellY = 1.f - cellY;
731                     }
732                     data->histOfs[0] = (icellX1*ncells.height + icellY1)*nbins;
733                     data->histWeights[0] = cellX*cellY;
734                     data->histOfs[1] = data->histOfs[2] = data->histOfs[3] = 0;
735                     data->histWeights[1] = data->histWeights[2] = data->histWeights[3] = 0;
736                 }
737             }
738             data->gradOfs = (grad.cols*i + j)*2;
739             data->qangleOfs = (qangle.cols*i + j)*2;
740             data->gradWeight = weights(i,j);
741         }
742 
743     assert( count1 + count2 + count4 == rawBlockSize );
744     // defragment pixData
745     for( j = 0; j < count2; j++ )
746         pixData[j + count1] = pixData[j + rawBlockSize];
747     for( j = 0; j < count4; j++ )
748         pixData[j + count1 + count2] = pixData[j + rawBlockSize*2];
749     count2 += count1;
750     count4 += count2;
751 
752     // initialize blockData
753     for( j = 0; j < nblocks.width; j++ )
754         for( i = 0; i < nblocks.height; i++ )
755         {
756             BlockData& data = blockData[j*nblocks.height + i];
757             data.histOfs = (j*nblocks.height + i)*blockHistogramSize;
758             data.imgOffset = Point(j*blockStride.width,i*blockStride.height);
759         }
760 }
761 
getBlock(Point pt,float * buf)762 const float* HOGCache::getBlock(Point pt, float* buf)
763 {
764     float* blockHist = buf;
765     assert(descriptor != 0);
766 
767 //    Size blockSize = descriptor->blockSize;
768     pt += imgoffset;
769 
770 //    CV_Assert( (unsigned)pt.x <= (unsigned)(grad.cols - blockSize.width) &&
771 //        (unsigned)pt.y <= (unsigned)(grad.rows - blockSize.height) );
772 
773     if( useCache )
774     {
775         CV_Assert( pt.x % cacheStride.width == 0 &&
776                    pt.y % cacheStride.height == 0 );
777         Point cacheIdx(pt.x/cacheStride.width,
778                        (pt.y/cacheStride.height) % blockCache.rows);
779         if( pt.y != ymaxCached[cacheIdx.y] )
780         {
781             Mat_<uchar> cacheRow = blockCacheFlags.row(cacheIdx.y);
782             cacheRow = (uchar)0;
783             ymaxCached[cacheIdx.y] = pt.y;
784         }
785 
786         blockHist = &blockCache[cacheIdx.y][cacheIdx.x*blockHistogramSize];
787         uchar& computedFlag = blockCacheFlags(cacheIdx.y, cacheIdx.x);
788         if( computedFlag != 0 )
789             return blockHist;
790         computedFlag = (uchar)1; // set it at once, before actual computing
791     }
792 
793     int k, C1 = count1, C2 = count2, C4 = count4;
794     const float* gradPtr = grad.ptr<float>(pt.y) + pt.x*2;
795     const uchar* qanglePtr = qangle.ptr(pt.y) + pt.x*2;
796 
797 //    CV_Assert( blockHist != 0 );
798     memset(blockHist, 0, sizeof(float) * blockHistogramSize);
799 
800     const PixData* _pixData = &pixData[0];
801 
802     for( k = 0; k < C1; k++ )
803     {
804         const PixData& pk = _pixData[k];
805         const float* const a = gradPtr + pk.gradOfs;
806         float w = pk.gradWeight*pk.histWeights[0];
807         const uchar* h = qanglePtr + pk.qangleOfs;
808         int h0 = h[0], h1 = h[1];
809 
810         float* hist = blockHist + pk.histOfs[0];
811         float t0 = hist[h0] + a[0]*w;
812         float t1 = hist[h1] + a[1]*w;
813         hist[h0] = t0; hist[h1] = t1;
814     }
815 
816 #if CV_SSE2
817     float hist0[4], hist1[4];
818     for( ; k < C2; k++ )
819     {
820         const PixData& pk = _pixData[k];
821         const float* const a = gradPtr + pk.gradOfs;
822         const uchar* const h = qanglePtr + pk.qangleOfs;
823         int h0 = h[0], h1 = h[1];
824 
825         __m128 _a0 = _mm_set1_ps(a[0]), _a1 = _mm_set1_ps(a[1]);
826         __m128 _w = _mm_mul_ps(_mm_set1_ps(pk.gradWeight), _mm_loadu_ps(pk.histWeights));
827         __m128 _t0 = _mm_mul_ps(_a0, _w), _t1 = _mm_mul_ps(_a1, _w);
828 
829         _mm_storeu_ps(hist0, _t0);
830         _mm_storeu_ps(hist1, _t1);
831 
832         float* hist = blockHist + pk.histOfs[0];
833         float t0 = hist[h0] + hist0[0];
834         float t1 = hist[h1] + hist1[0];
835         hist[h0] = t0; hist[h1] = t1;
836 
837         hist = blockHist + pk.histOfs[1];
838         t0 = hist[h0] + hist0[1];
839         t1 = hist[h1] + hist1[1];
840         hist[h0] = t0; hist[h1] = t1;
841     }
842 #else
843     for( ; k < C2; k++ )
844     {
845         const PixData& pk = _pixData[k];
846         const float* const a = gradPtr + pk.gradOfs;
847         float w, t0, t1, a0 = a[0], a1 = a[1];
848         const uchar* const h = qanglePtr + pk.qangleOfs;
849         int h0 = h[0], h1 = h[1];
850 
851         float* hist = blockHist + pk.histOfs[0];
852         w = pk.gradWeight*pk.histWeights[0];
853         t0 = hist[h0] + a0*w;
854         t1 = hist[h1] + a1*w;
855         hist[h0] = t0; hist[h1] = t1;
856 
857         hist = blockHist + pk.histOfs[1];
858         w = pk.gradWeight*pk.histWeights[1];
859         t0 = hist[h0] + a0*w;
860         t1 = hist[h1] + a1*w;
861         hist[h0] = t0; hist[h1] = t1;
862     }
863 #endif
864 
865 #if CV_SSE2
866     for( ; k < C4; k++ )
867     {
868         const PixData& pk = _pixData[k];
869         const float* const a = gradPtr + pk.gradOfs;
870         const uchar* const h = qanglePtr + pk.qangleOfs;
871         int h0 = h[0], h1 = h[1];
872 
873         __m128 _a0 = _mm_set1_ps(a[0]), _a1 = _mm_set1_ps(a[1]);
874         __m128 _w = _mm_mul_ps(_mm_set1_ps(pk.gradWeight), _mm_loadu_ps(pk.histWeights));
875         __m128 _t0 = _mm_mul_ps(_a0, _w), _t1 = _mm_mul_ps(_a1, _w);
876 
877         _mm_storeu_ps(hist0, _t0);
878         _mm_storeu_ps(hist1, _t1);
879 
880         float* hist = blockHist + pk.histOfs[0];
881         float t0 = hist[h0] + hist0[0];
882         float t1 = hist[h1] + hist1[0];
883         hist[h0] = t0; hist[h1] = t1;
884 
885         hist = blockHist + pk.histOfs[1];
886         t0 = hist[h0] + hist0[1];
887         t1 = hist[h1] + hist1[1];
888         hist[h0] = t0; hist[h1] = t1;
889 
890         hist = blockHist + pk.histOfs[2];
891         t0 = hist[h0] + hist0[2];
892         t1 = hist[h1] + hist1[2];
893         hist[h0] = t0; hist[h1] = t1;
894 
895         hist = blockHist + pk.histOfs[3];
896         t0 = hist[h0] + hist0[3];
897         t1 = hist[h1] + hist1[3];
898         hist[h0] = t0; hist[h1] = t1;
899 
900 //        __m128 _hist0 = _mm_set_ps((blockHist + pk.histOfs[3])[h0], (blockHist + pk.histOfs[2])[h0],
901 //            (blockHist + pk.histOfs[1])[h0], (blockHist + pk.histOfs[0])[h0]);
902 //        __m128 _hist1 = _mm_set_ps((blockHist + pk.histOfs[3])[h1], (blockHist + pk.histOfs[2])[h1],
903 //            (blockHist + pk.histOfs[1])[h1], (blockHist + pk.histOfs[0])[h1]);
904 //
905 //        _hist0 = _mm_add_ps(_t0, _hist0);
906 //        _hist1 = _mm_add_ps(_t1, _hist1);
907 //
908 //        _mm_storeu_ps(hist0, _hist0);
909 //        _mm_storeu_ps(hist1, _hist1);
910 //
911 //        (pk.histOfs[0] + blockHist)[h0] = hist0[0];
912 //        (pk.histOfs[1] + blockHist)[h0] = hist0[1];
913 //        (pk.histOfs[2] + blockHist)[h0] = hist0[2];
914 //        (pk.histOfs[3] + blockHist)[h0] = hist0[3];
915 //
916 //        (pk.histOfs[0] + blockHist)[h1] = hist1[0];
917 //        (pk.histOfs[1] + blockHist)[h1] = hist1[1];
918 //        (pk.histOfs[2] + blockHist)[h1] = hist1[2];
919 //        (pk.histOfs[3] + blockHist)[h1] = hist1[3];
920     }
921 #else
922     for( ; k < C4; k++ )
923     {
924         const PixData& pk = _pixData[k];
925         const float* a = gradPtr + pk.gradOfs;
926         float w, t0, t1, a0 = a[0], a1 = a[1];
927         const uchar* h = qanglePtr + pk.qangleOfs;
928         int h0 = h[0], h1 = h[1];
929 
930         float* hist = blockHist + pk.histOfs[0];
931         w = pk.gradWeight*pk.histWeights[0];
932         t0 = hist[h0] + a0*w;
933         t1 = hist[h1] + a1*w;
934         hist[h0] = t0; hist[h1] = t1;
935 
936         hist = blockHist + pk.histOfs[1];
937         w = pk.gradWeight*pk.histWeights[1];
938         t0 = hist[h0] + a0*w;
939         t1 = hist[h1] + a1*w;
940         hist[h0] = t0; hist[h1] = t1;
941 
942         hist = blockHist + pk.histOfs[2];
943         w = pk.gradWeight*pk.histWeights[2];
944         t0 = hist[h0] + a0*w;
945         t1 = hist[h1] + a1*w;
946         hist[h0] = t0; hist[h1] = t1;
947 
948         hist = blockHist + pk.histOfs[3];
949         w = pk.gradWeight*pk.histWeights[3];
950         t0 = hist[h0] + a0*w;
951         t1 = hist[h1] + a1*w;
952         hist[h0] = t0; hist[h1] = t1;
953     }
954 #endif
955 
956     normalizeBlockHistogram(blockHist);
957 
958     return blockHist;
959 }
960 
normalizeBlockHistogram(float * _hist) const961 void HOGCache::normalizeBlockHistogram(float* _hist) const
962 {
963     float* hist = &_hist[0], sum = 0.0f, partSum[4];
964     size_t i = 0, sz = blockHistogramSize;
965 
966 #if CV_SSE2
967     __m128 p0 = _mm_loadu_ps(hist);
968     __m128 s = _mm_mul_ps(p0, p0);
969 
970     for (i = 4; i <= sz - 4; i += 4)
971     {
972         p0 = _mm_loadu_ps(hist + i);
973         s = _mm_add_ps(s, _mm_mul_ps(p0, p0));
974     }
975     _mm_storeu_ps(partSum, s);
976 #else
977     partSum[0] = 0.0f;
978     partSum[1] = 0.0f;
979     partSum[2] = 0.0f;
980     partSum[3] = 0.0f;
981     for ( ; i <= sz - 4; i += 4)
982     {
983         partSum[0] += hist[i] * hist[i];
984         partSum[1] += hist[i+1] * hist[i+1];
985         partSum[2] += hist[i+2] * hist[i+2];
986         partSum[3] += hist[i+3] * hist[i+3];
987     }
988 #endif
989     float t0 = partSum[0] + partSum[1];
990     float t1 = partSum[2] + partSum[3];
991     sum = t0 + t1;
992     for ( ; i < sz; ++i)
993         sum += hist[i]*hist[i];
994 
995     float scale = 1.f/(std::sqrt(sum)+sz*0.1f), thresh = (float)descriptor->L2HysThreshold;
996     i = 0, sum = 0.0f;
997 
998 #if CV_SSE2
999     __m128 _scale = _mm_set1_ps(scale);
1000     static __m128 _threshold = _mm_set1_ps(thresh);
1001 
1002     __m128 p = _mm_mul_ps(_scale, _mm_loadu_ps(hist));
1003     p = _mm_min_ps(p, _threshold);
1004     s = _mm_mul_ps(p, p);
1005     _mm_storeu_ps(hist, p);
1006 
1007     for(i = 4 ; i <= sz - 4; i += 4)
1008     {
1009         p = _mm_loadu_ps(hist + i);
1010         p = _mm_mul_ps(p, _scale);
1011         p = _mm_min_ps(p, _threshold);
1012         s = _mm_add_ps(s, _mm_mul_ps(p, p));
1013         _mm_storeu_ps(hist + i, p);
1014     }
1015 
1016     _mm_storeu_ps(partSum, s);
1017 #else
1018     partSum[0] = 0.0f;
1019     partSum[1] = 0.0f;
1020     partSum[2] = 0.0f;
1021     partSum[3] = 0.0f;
1022     for( ; i <= sz - 4; i += 4)
1023     {
1024         hist[i] = std::min(hist[i]*scale, thresh);
1025         hist[i+1] = std::min(hist[i+1]*scale, thresh);
1026         hist[i+2] = std::min(hist[i+2]*scale, thresh);
1027         hist[i+3] = std::min(hist[i+3]*scale, thresh);
1028         partSum[0] += hist[i]*hist[i];
1029         partSum[1] += hist[i+1]*hist[i+1];
1030         partSum[2] += hist[i+2]*hist[i+2];
1031         partSum[3] += hist[i+3]*hist[i+3];
1032     }
1033 #endif
1034     t0 = partSum[0] + partSum[1];
1035     t1 = partSum[2] + partSum[3];
1036     sum = t0 + t1;
1037     for( ; i < sz; ++i)
1038     {
1039         hist[i] = std::min(hist[i]*scale, thresh);
1040         sum += hist[i]*hist[i];
1041     }
1042 
1043     scale = 1.f/(std::sqrt(sum)+1e-3f), i = 0;
1044 #if CV_SSE2
1045     __m128 _scale2 = _mm_set1_ps(scale);
1046     for ( ; i <= sz - 4; i += 4)
1047     {
1048         __m128 t = _mm_mul_ps(_scale2, _mm_loadu_ps(hist + i));
1049         _mm_storeu_ps(hist + i, t);
1050     }
1051 #endif
1052     for ( ; i < sz; ++i)
1053         hist[i] *= scale;
1054 }
1055 
windowsInImage(const Size & imageSize,const Size & winStride) const1056 Size HOGCache::windowsInImage(const Size& imageSize, const Size& winStride) const
1057 {
1058     return Size((imageSize.width - winSize.width)/winStride.width + 1,
1059         (imageSize.height - winSize.height)/winStride.height + 1);
1060 }
1061 
getWindow(const Size & imageSize,const Size & winStride,int idx) const1062 Rect HOGCache::getWindow(const Size& imageSize, const Size& winStride, int idx) const
1063 {
1064     int nwindowsX = (imageSize.width - winSize.width)/winStride.width + 1;
1065     int y = idx / nwindowsX;
1066     int x = idx - nwindowsX*y;
1067     return Rect( x*winStride.width, y*winStride.height, winSize.width, winSize.height );
1068 }
1069 
gcd(int a,int b)1070 static inline int gcd(int a, int b)
1071 {
1072     if( a < b )
1073         std::swap(a, b);
1074     while( b > 0 )
1075     {
1076         int r = a % b;
1077         a = b;
1078         b = r;
1079     }
1080     return a;
1081 }
1082 
1083 #ifdef HAVE_OPENCL
1084 
ocl_compute_gradients_8UC1(int height,int width,InputArray _img,float angle_scale,UMat grad,UMat qangle,bool correct_gamma,int nbins)1085 static bool ocl_compute_gradients_8UC1(int height, int width, InputArray _img, float angle_scale,
1086                                        UMat grad, UMat qangle, bool correct_gamma, int nbins)
1087 {
1088     ocl::Kernel k("compute_gradients_8UC1_kernel", ocl::objdetect::objdetect_hog_oclsrc);
1089     if(k.empty())
1090         return false;
1091 
1092     UMat img = _img.getUMat();
1093 
1094     size_t localThreads[3] = { NTHREADS, 1, 1 };
1095     size_t globalThreads[3] = { width, height, 1 };
1096     char correctGamma = (correct_gamma) ? 1 : 0;
1097     int grad_quadstep = (int)grad.step >> 3;
1098     int qangle_elem_size = CV_ELEM_SIZE1(qangle.type());
1099     int qangle_step = (int)qangle.step / (2 * qangle_elem_size);
1100 
1101     int idx = 0;
1102     idx = k.set(idx, height);
1103     idx = k.set(idx, width);
1104     idx = k.set(idx, (int)img.step1());
1105     idx = k.set(idx, grad_quadstep);
1106     idx = k.set(idx, qangle_step);
1107     idx = k.set(idx, ocl::KernelArg::PtrReadOnly(img));
1108     idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(grad));
1109     idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(qangle));
1110     idx = k.set(idx, angle_scale);
1111     idx = k.set(idx, correctGamma);
1112     idx = k.set(idx, nbins);
1113 
1114     return k.run(2, globalThreads, localThreads, false);
1115 }
1116 
ocl_computeGradient(InputArray img,UMat grad,UMat qangle,int nbins,Size effect_size,bool gamma_correction,bool signedGradient)1117 static bool ocl_computeGradient(InputArray img, UMat grad, UMat qangle, int nbins, Size effect_size, bool gamma_correction, bool signedGradient)
1118 {
1119     float angleScale = signedGradient ? (float)(nbins/(2.0*CV_PI)) : (float)(nbins/CV_PI);
1120 
1121     return ocl_compute_gradients_8UC1(effect_size.height, effect_size.width, img,
1122          angleScale, grad, qangle, gamma_correction, nbins);
1123 }
1124 
1125 #define CELL_WIDTH 8
1126 #define CELL_HEIGHT 8
1127 #define CELLS_PER_BLOCK_X 2
1128 #define CELLS_PER_BLOCK_Y 2
1129 
ocl_compute_hists(int nbins,int block_stride_x,int block_stride_y,int height,int width,UMat grad,UMat qangle,UMat gauss_w_lut,UMat block_hists,size_t block_hist_size)1130 static bool ocl_compute_hists(int nbins, int block_stride_x, int block_stride_y, int height, int width,
1131                               UMat grad, UMat qangle, UMat gauss_w_lut, UMat block_hists, size_t block_hist_size)
1132 {
1133     ocl::Kernel k("compute_hists_lut_kernel", ocl::objdetect::objdetect_hog_oclsrc);
1134     if(k.empty())
1135         return false;
1136     bool is_cpu = cv::ocl::Device::getDefault().type() == cv::ocl::Device::TYPE_CPU;
1137     cv::String opts;
1138     if(is_cpu)
1139        opts = "-D CPU ";
1140     else
1141         opts = cv::format("-D WAVE_SIZE=%d", k.preferedWorkGroupSizeMultiple());
1142     k.create("compute_hists_lut_kernel", ocl::objdetect::objdetect_hog_oclsrc, opts);
1143     if(k.empty())
1144         return false;
1145 
1146     int img_block_width = (width - CELLS_PER_BLOCK_X * CELL_WIDTH + block_stride_x)/block_stride_x;
1147     int img_block_height = (height - CELLS_PER_BLOCK_Y * CELL_HEIGHT + block_stride_y)/block_stride_y;
1148     int blocks_total = img_block_width * img_block_height;
1149 
1150     int qangle_elem_size = CV_ELEM_SIZE1(qangle.type());
1151     int grad_quadstep = (int)grad.step >> 2;
1152     int qangle_step = (int)qangle.step / qangle_elem_size;
1153 
1154     int blocks_in_group = 4;
1155     size_t localThreads[3] = { blocks_in_group * 24, 2, 1 };
1156     size_t globalThreads[3] = {((img_block_width * img_block_height + blocks_in_group - 1)/blocks_in_group) * localThreads[0], 2, 1 };
1157 
1158     int hists_size = (nbins * CELLS_PER_BLOCK_X * CELLS_PER_BLOCK_Y * 12) * sizeof(float);
1159     int final_hists_size = (nbins * CELLS_PER_BLOCK_X * CELLS_PER_BLOCK_Y) * sizeof(float);
1160 
1161     int smem = (hists_size + final_hists_size) * blocks_in_group;
1162 
1163     int idx = 0;
1164     idx = k.set(idx, block_stride_x);
1165     idx = k.set(idx, block_stride_y);
1166     idx = k.set(idx, nbins);
1167     idx = k.set(idx, (int)block_hist_size);
1168     idx = k.set(idx, img_block_width);
1169     idx = k.set(idx, blocks_in_group);
1170     idx = k.set(idx, blocks_total);
1171     idx = k.set(idx, grad_quadstep);
1172     idx = k.set(idx, qangle_step);
1173     idx = k.set(idx, ocl::KernelArg::PtrReadOnly(grad));
1174     idx = k.set(idx, ocl::KernelArg::PtrReadOnly(qangle));
1175     idx = k.set(idx, ocl::KernelArg::PtrReadOnly(gauss_w_lut));
1176     idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(block_hists));
1177     idx = k.set(idx, (void*)NULL, (size_t)smem);
1178 
1179     return k.run(2, globalThreads, localThreads, false);
1180 }
1181 
power_2up(unsigned int n)1182 static int power_2up(unsigned int n)
1183 {
1184     for(unsigned int i = 1; i<=1024; i<<=1)
1185         if(n < i)
1186             return i;
1187     return -1; // Input is too big
1188 }
1189 
ocl_normalize_hists(int nbins,int block_stride_x,int block_stride_y,int height,int width,UMat block_hists,float threshold)1190 static bool ocl_normalize_hists(int nbins, int block_stride_x, int block_stride_y,
1191                                 int height, int width, UMat block_hists, float threshold)
1192 {
1193     int block_hist_size = nbins * CELLS_PER_BLOCK_X * CELLS_PER_BLOCK_Y;
1194     int img_block_width = (width - CELLS_PER_BLOCK_X * CELL_WIDTH + block_stride_x)
1195         / block_stride_x;
1196     int img_block_height = (height - CELLS_PER_BLOCK_Y * CELL_HEIGHT + block_stride_y)
1197         / block_stride_y;
1198     int nthreads;
1199     size_t globalThreads[3] = { 1, 1, 1  };
1200     size_t localThreads[3] = { 1, 1, 1  };
1201 
1202     int idx = 0;
1203     bool is_cpu = cv::ocl::Device::getDefault().type() == cv::ocl::Device::TYPE_CPU;
1204     cv::String opts;
1205     ocl::Kernel k;
1206     if ( nbins == 9 )
1207     {
1208         k.create("normalize_hists_36_kernel", ocl::objdetect::objdetect_hog_oclsrc, "");
1209         if(k.empty())
1210             return false;
1211         if(is_cpu)
1212            opts = "-D CPU ";
1213         else
1214             opts = cv::format("-D WAVE_SIZE=%d", k.preferedWorkGroupSizeMultiple());
1215         k.create("normalize_hists_36_kernel", ocl::objdetect::objdetect_hog_oclsrc, opts);
1216         if(k.empty())
1217             return false;
1218 
1219         int blocks_in_group = NTHREADS / block_hist_size;
1220         nthreads = blocks_in_group * block_hist_size;
1221         int num_groups = (img_block_width * img_block_height + blocks_in_group - 1)/blocks_in_group;
1222         globalThreads[0] = nthreads * num_groups;
1223         localThreads[0] = nthreads;
1224     }
1225     else
1226     {
1227         k.create("normalize_hists_kernel", ocl::objdetect::objdetect_hog_oclsrc, "");
1228         if(k.empty())
1229             return false;
1230         if(is_cpu)
1231            opts = "-D CPU ";
1232         else
1233             opts = cv::format("-D WAVE_SIZE=%d", k.preferedWorkGroupSizeMultiple());
1234         k.create("normalize_hists_kernel", ocl::objdetect::objdetect_hog_oclsrc, opts);
1235         if(k.empty())
1236             return false;
1237 
1238         nthreads = power_2up(block_hist_size);
1239         globalThreads[0] = img_block_width * nthreads;
1240         globalThreads[1] = img_block_height;
1241         localThreads[0] = nthreads;
1242 
1243         if ((nthreads < 32) || (nthreads > 512) )
1244             return false;
1245 
1246         idx = k.set(idx, nthreads);
1247         idx = k.set(idx, block_hist_size);
1248         idx = k.set(idx, img_block_width);
1249     }
1250     idx = k.set(idx, ocl::KernelArg::PtrReadWrite(block_hists));
1251     idx = k.set(idx, threshold);
1252     idx = k.set(idx, (void*)NULL,  nthreads * sizeof(float));
1253 
1254     return k.run(2, globalThreads, localThreads, false);
1255 }
1256 
ocl_extract_descrs_by_rows(int win_height,int win_width,int block_stride_y,int block_stride_x,int win_stride_y,int win_stride_x,int height,int width,UMat block_hists,UMat descriptors,int block_hist_size,int descr_size,int descr_width)1257 static bool ocl_extract_descrs_by_rows(int win_height, int win_width, int block_stride_y, int block_stride_x, int win_stride_y, int win_stride_x,
1258                                        int height, int width, UMat block_hists, UMat descriptors,
1259                                        int block_hist_size, int descr_size, int descr_width)
1260 {
1261     ocl::Kernel k("extract_descrs_by_rows_kernel", ocl::objdetect::objdetect_hog_oclsrc);
1262     if(k.empty())
1263         return false;
1264 
1265     int win_block_stride_x = win_stride_x / block_stride_x;
1266     int win_block_stride_y = win_stride_y / block_stride_y;
1267     int img_win_width = (width - win_width + win_stride_x) / win_stride_x;
1268     int img_win_height = (height - win_height + win_stride_y) / win_stride_y;
1269     int img_block_width = (width - CELLS_PER_BLOCK_X * CELL_WIDTH + block_stride_x) /
1270         block_stride_x;
1271 
1272     int descriptors_quadstep = (int)descriptors.step >> 2;
1273 
1274     size_t globalThreads[3] = { img_win_width * NTHREADS, img_win_height, 1 };
1275     size_t localThreads[3] = { NTHREADS, 1, 1 };
1276 
1277     int idx = 0;
1278     idx = k.set(idx, block_hist_size);
1279     idx = k.set(idx, descriptors_quadstep);
1280     idx = k.set(idx, descr_size);
1281     idx = k.set(idx, descr_width);
1282     idx = k.set(idx, img_block_width);
1283     idx = k.set(idx, win_block_stride_x);
1284     idx = k.set(idx, win_block_stride_y);
1285     idx = k.set(idx, ocl::KernelArg::PtrReadOnly(block_hists));
1286     idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(descriptors));
1287 
1288     return k.run(2, globalThreads, localThreads, false);
1289 }
1290 
ocl_extract_descrs_by_cols(int win_height,int win_width,int block_stride_y,int block_stride_x,int win_stride_y,int win_stride_x,int height,int width,UMat block_hists,UMat descriptors,int block_hist_size,int descr_size,int nblocks_win_x,int nblocks_win_y)1291 static bool ocl_extract_descrs_by_cols(int win_height, int win_width, int block_stride_y, int block_stride_x, int win_stride_y, int win_stride_x,
1292                                        int height, int width, UMat block_hists, UMat descriptors,
1293                                        int block_hist_size, int descr_size, int nblocks_win_x, int nblocks_win_y)
1294 {
1295     ocl::Kernel k("extract_descrs_by_cols_kernel", ocl::objdetect::objdetect_hog_oclsrc);
1296     if(k.empty())
1297         return false;
1298 
1299     int win_block_stride_x = win_stride_x / block_stride_x;
1300     int win_block_stride_y = win_stride_y / block_stride_y;
1301     int img_win_width = (width - win_width + win_stride_x) / win_stride_x;
1302     int img_win_height = (height - win_height + win_stride_y) / win_stride_y;
1303     int img_block_width = (width - CELLS_PER_BLOCK_X * CELL_WIDTH + block_stride_x) /
1304         block_stride_x;
1305 
1306     int descriptors_quadstep = (int)descriptors.step >> 2;
1307 
1308     size_t globalThreads[3] = { img_win_width * NTHREADS, img_win_height, 1 };
1309     size_t localThreads[3] = { NTHREADS, 1, 1 };
1310 
1311     int idx = 0;
1312     idx = k.set(idx, block_hist_size);
1313     idx = k.set(idx, descriptors_quadstep);
1314     idx = k.set(idx, descr_size);
1315     idx = k.set(idx, nblocks_win_x);
1316     idx = k.set(idx, nblocks_win_y);
1317     idx = k.set(idx, img_block_width);
1318     idx = k.set(idx, win_block_stride_x);
1319     idx = k.set(idx, win_block_stride_y);
1320     idx = k.set(idx, ocl::KernelArg::PtrReadOnly(block_hists));
1321     idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(descriptors));
1322 
1323     return k.run(2, globalThreads, localThreads, false);
1324 }
1325 
ocl_compute(InputArray _img,Size win_stride,std::vector<float> & _descriptors,int descr_format,Size blockSize,Size cellSize,int nbins,Size blockStride,Size winSize,float sigma,bool gammaCorrection,double L2HysThreshold,bool signedGradient)1326 static bool ocl_compute(InputArray _img, Size win_stride, std::vector<float>& _descriptors, int descr_format, Size blockSize,
1327                         Size cellSize, int nbins, Size blockStride, Size winSize, float sigma, bool gammaCorrection, double L2HysThreshold, bool signedGradient)
1328 {
1329     Size imgSize = _img.size();
1330     Size effect_size = imgSize;
1331 
1332     UMat grad(imgSize, CV_32FC2);
1333     int qangle_type = ocl::Device::getDefault().isIntel() ? CV_32SC2 : CV_8UC2;
1334     UMat qangle(imgSize, qangle_type);
1335 
1336     const size_t block_hist_size = getBlockHistogramSize(blockSize, cellSize, nbins);
1337     const Size blocks_per_img = numPartsWithin(imgSize, blockSize, blockStride);
1338     UMat block_hists(1, static_cast<int>(block_hist_size * blocks_per_img.area()) + 256, CV_32F);
1339 
1340     Size wins_per_img = numPartsWithin(imgSize, winSize, win_stride);
1341     UMat labels(1, wins_per_img.area(), CV_8U);
1342 
1343     float scale = 1.f / (2.f * sigma * sigma);
1344     Mat gaussian_lut(1, 512, CV_32FC1);
1345     int idx = 0;
1346     for(int i=-8; i<8; i++)
1347         for(int j=-8; j<8; j++)
1348             gaussian_lut.at<float>(idx++) = std::exp(-(j * j + i * i) * scale);
1349     for(int i=-8; i<8; i++)
1350         for(int j=-8; j<8; j++)
1351             gaussian_lut.at<float>(idx++) = (8.f - fabs(j + 0.5f)) * (8.f - fabs(i + 0.5f)) / 64.f;
1352 
1353     if(!ocl_computeGradient(_img, grad, qangle, nbins, effect_size, gammaCorrection, signedGradient))
1354         return false;
1355 
1356     UMat gauss_w_lut;
1357     gaussian_lut.copyTo(gauss_w_lut);
1358     if(!ocl_compute_hists(nbins, blockStride.width, blockStride.height, effect_size.height,
1359         effect_size.width, grad, qangle, gauss_w_lut, block_hists, block_hist_size))
1360         return false;
1361 
1362     if(!ocl_normalize_hists(nbins, blockStride.width, blockStride.height, effect_size.height,
1363         effect_size.width, block_hists, (float)L2HysThreshold))
1364         return false;
1365 
1366     Size blocks_per_win = numPartsWithin(winSize, blockSize, blockStride);
1367     wins_per_img = numPartsWithin(effect_size, winSize, win_stride);
1368 
1369     int descr_size = blocks_per_win.area()*(int)block_hist_size;
1370     int descr_width = (int)block_hist_size*blocks_per_win.width;
1371 
1372     UMat descriptors(wins_per_img.area(), static_cast<int>(blocks_per_win.area() * block_hist_size), CV_32F);
1373     switch (descr_format)
1374     {
1375     case DESCR_FORMAT_ROW_BY_ROW:
1376         if(!ocl_extract_descrs_by_rows(winSize.height, winSize.width,
1377             blockStride.height, blockStride.width, win_stride.height, win_stride.width, effect_size.height,
1378             effect_size.width, block_hists, descriptors, (int)block_hist_size, descr_size, descr_width))
1379             return false;
1380         break;
1381     case DESCR_FORMAT_COL_BY_COL:
1382         if(!ocl_extract_descrs_by_cols(winSize.height, winSize.width,
1383             blockStride.height, blockStride.width, win_stride.height, win_stride.width, effect_size.height, effect_size.width,
1384             block_hists, descriptors, (int)block_hist_size, descr_size, blocks_per_win.width, blocks_per_win.height))
1385             return false;
1386         break;
1387     default:
1388         return false;
1389     }
1390     descriptors.reshape(1, (int)descriptors.total()).getMat(ACCESS_READ).copyTo(_descriptors);
1391     return true;
1392 }
1393 #endif //HAVE_OPENCL
1394 
compute(InputArray _img,std::vector<float> & descriptors,Size winStride,Size padding,const std::vector<Point> & locations) const1395 void HOGDescriptor::compute(InputArray _img, std::vector<float>& descriptors,
1396     Size winStride, Size padding, const std::vector<Point>& locations) const
1397 {
1398     if( winStride == Size() )
1399         winStride = cellSize;
1400     Size cacheStride(gcd(winStride.width, blockStride.width),
1401                      gcd(winStride.height, blockStride.height));
1402 
1403     Size imgSize = _img.size();
1404 
1405     size_t nwindows = locations.size();
1406     padding.width = (int)alignSize(std::max(padding.width, 0), cacheStride.width);
1407     padding.height = (int)alignSize(std::max(padding.height, 0), cacheStride.height);
1408     Size paddedImgSize(imgSize.width + padding.width*2, imgSize.height + padding.height*2);
1409 
1410     CV_OCL_RUN(_img.dims() <= 2 && _img.type() == CV_8UC1 && _img.isUMat(),
1411         ocl_compute(_img, winStride, descriptors, DESCR_FORMAT_COL_BY_COL, blockSize,
1412         cellSize, nbins, blockStride, winSize, (float)getWinSigma(), gammaCorrection, L2HysThreshold, signedGradient))
1413 
1414     Mat img = _img.getMat();
1415     HOGCache cache(this, img, padding, padding, nwindows == 0, cacheStride);
1416 
1417     if( !nwindows )
1418         nwindows = cache.windowsInImage(paddedImgSize, winStride).area();
1419 
1420     const HOGCache::BlockData* blockData = &cache.blockData[0];
1421 
1422     int nblocks = cache.nblocks.area();
1423     int blockHistogramSize = cache.blockHistogramSize;
1424     size_t dsize = getDescriptorSize();
1425     descriptors.resize(dsize*nwindows);
1426 
1427     // for each window
1428     for( size_t i = 0; i < nwindows; i++ )
1429     {
1430         float* descriptor = &descriptors[i*dsize];
1431 
1432         Point pt0;
1433         if( !locations.empty() )
1434         {
1435             pt0 = locations[i];
1436             if( pt0.x < -padding.width || pt0.x > img.cols + padding.width - winSize.width ||
1437                 pt0.y < -padding.height || pt0.y > img.rows + padding.height - winSize.height )
1438                 continue;
1439         }
1440         else
1441         {
1442             pt0 = cache.getWindow(paddedImgSize, winStride, (int)i).tl() - Point(padding);
1443 //            CV_Assert(pt0.x % cacheStride.width == 0 && pt0.y % cacheStride.height == 0);
1444         }
1445 
1446         for( int j = 0; j < nblocks; j++ )
1447         {
1448             const HOGCache::BlockData& bj = blockData[j];
1449             Point pt = pt0 + bj.imgOffset;
1450 
1451             float* dst = descriptor + bj.histOfs;
1452             const float* src = cache.getBlock(pt, dst);
1453             if( src != dst )
1454                 memcpy(dst, src, blockHistogramSize * sizeof(float));
1455         }
1456     }
1457 }
1458 
detect(const Mat & img,std::vector<Point> & hits,std::vector<double> & weights,double hitThreshold,Size winStride,Size padding,const std::vector<Point> & locations) const1459 void HOGDescriptor::detect(const Mat& img,
1460     std::vector<Point>& hits, std::vector<double>& weights, double hitThreshold,
1461     Size winStride, Size padding, const std::vector<Point>& locations) const
1462 {
1463     hits.clear();
1464     weights.clear();
1465     if( svmDetector.empty() )
1466         return;
1467 
1468     if( winStride == Size() )
1469         winStride = cellSize;
1470     Size cacheStride(gcd(winStride.width, blockStride.width),
1471         gcd(winStride.height, blockStride.height));
1472 
1473     size_t nwindows = locations.size();
1474     padding.width = (int)alignSize(std::max(padding.width, 0), cacheStride.width);
1475     padding.height = (int)alignSize(std::max(padding.height, 0), cacheStride.height);
1476     Size paddedImgSize(img.cols + padding.width*2, img.rows + padding.height*2);
1477 
1478     HOGCache cache(this, img, padding, padding, nwindows == 0, cacheStride);
1479 
1480     if( !nwindows )
1481         nwindows = cache.windowsInImage(paddedImgSize, winStride).area();
1482 
1483     const HOGCache::BlockData* blockData = &cache.blockData[0];
1484 
1485     int nblocks = cache.nblocks.area();
1486     int blockHistogramSize = cache.blockHistogramSize;
1487     size_t dsize = getDescriptorSize();
1488 
1489     double rho = svmDetector.size() > dsize ? svmDetector[dsize] : 0;
1490     std::vector<float> blockHist(blockHistogramSize);
1491 
1492 #if CV_SSE2
1493     float partSum[4];
1494 #endif
1495 
1496     for( size_t i = 0; i < nwindows; i++ )
1497     {
1498         Point pt0;
1499         if( !locations.empty() )
1500         {
1501             pt0 = locations[i];
1502             if( pt0.x < -padding.width || pt0.x > img.cols + padding.width - winSize.width ||
1503                     pt0.y < -padding.height || pt0.y > img.rows + padding.height - winSize.height )
1504                 continue;
1505         }
1506         else
1507         {
1508             pt0 = cache.getWindow(paddedImgSize, winStride, (int)i).tl() - Point(padding);
1509             CV_Assert(pt0.x % cacheStride.width == 0 && pt0.y % cacheStride.height == 0);
1510         }
1511         double s = rho;
1512         const float* svmVec = &svmDetector[0];
1513 
1514         int j, k;
1515         for( j = 0; j < nblocks; j++, svmVec += blockHistogramSize )
1516         {
1517             const HOGCache::BlockData& bj = blockData[j];
1518             Point pt = pt0 + bj.imgOffset;
1519 
1520             const float* vec = cache.getBlock(pt, &blockHist[0]);
1521 #if CV_SSE2
1522             __m128 _vec = _mm_loadu_ps(vec);
1523             __m128 _svmVec = _mm_loadu_ps(svmVec);
1524             __m128 sum = _mm_mul_ps(_svmVec, _vec);
1525 
1526             for( k = 4; k <= blockHistogramSize - 4; k += 4 )
1527             {
1528                 _vec = _mm_loadu_ps(vec + k);
1529                 _svmVec = _mm_loadu_ps(svmVec + k);
1530 
1531                 sum = _mm_add_ps(sum, _mm_mul_ps(_vec, _svmVec));
1532             }
1533 
1534             _mm_storeu_ps(partSum, sum);
1535             double t0 = partSum[0] + partSum[1];
1536             double t1 = partSum[2] + partSum[3];
1537             s += t0 + t1;
1538 #else
1539             for( k = 0; k <= blockHistogramSize - 4; k += 4 )
1540                 s += vec[k]*svmVec[k] + vec[k+1]*svmVec[k+1] +
1541                     vec[k+2]*svmVec[k+2] + vec[k+3]*svmVec[k+3];
1542 #endif
1543             for( ; k < blockHistogramSize; k++ )
1544                 s += vec[k]*svmVec[k];
1545         }
1546         if( s >= hitThreshold )
1547         {
1548             hits.push_back(pt0);
1549             weights.push_back(s);
1550         }
1551     }
1552 }
1553 
detect(const Mat & img,std::vector<Point> & hits,double hitThreshold,Size winStride,Size padding,const std::vector<Point> & locations) const1554 void HOGDescriptor::detect(const Mat& img, std::vector<Point>& hits, double hitThreshold,
1555     Size winStride, Size padding, const std::vector<Point>& locations) const
1556 {
1557     std::vector<double> weightsV;
1558     detect(img, hits, weightsV, hitThreshold, winStride, padding, locations);
1559 }
1560 
1561 class HOGInvoker :
1562     public ParallelLoopBody
1563 {
1564 public:
HOGInvoker(const HOGDescriptor * _hog,const Mat & _img,double _hitThreshold,const Size & _winStride,const Size & _padding,const double * _levelScale,std::vector<Rect> * _vec,Mutex * _mtx,std::vector<double> * _weights=0,std::vector<double> * _scales=0)1565     HOGInvoker( const HOGDescriptor* _hog, const Mat& _img,
1566         double _hitThreshold, const Size& _winStride, const Size& _padding,
1567         const double* _levelScale, std::vector<Rect> * _vec, Mutex* _mtx,
1568         std::vector<double>* _weights=0, std::vector<double>* _scales=0 )
1569     {
1570         hog = _hog;
1571         img = _img;
1572         hitThreshold = _hitThreshold;
1573         winStride = _winStride;
1574         padding = _padding;
1575         levelScale = _levelScale;
1576         vec = _vec;
1577         weights = _weights;
1578         scales = _scales;
1579         mtx = _mtx;
1580     }
1581 
operator ()(const Range & range) const1582     void operator()( const Range& range ) const
1583     {
1584         int i, i1 = range.start, i2 = range.end;
1585         double minScale = i1 > 0 ? levelScale[i1] : i2 > 1 ? levelScale[i1+1] : std::max(img.cols, img.rows);
1586         Size maxSz(cvCeil(img.cols/minScale), cvCeil(img.rows/minScale));
1587         Mat smallerImgBuf(maxSz, img.type());
1588         std::vector<Point> locations;
1589         std::vector<double> hitsWeights;
1590 
1591         for( i = i1; i < i2; i++ )
1592         {
1593             double scale = levelScale[i];
1594             Size sz(cvRound(img.cols/scale), cvRound(img.rows/scale));
1595             Mat smallerImg(sz, img.type(), smallerImgBuf.ptr());
1596             if( sz == img.size() )
1597                 smallerImg = Mat(sz, img.type(), img.data, img.step);
1598             else
1599                 resize(img, smallerImg, sz);
1600             hog->detect(smallerImg, locations, hitsWeights, hitThreshold, winStride, padding);
1601             Size scaledWinSize = Size(cvRound(hog->winSize.width*scale), cvRound(hog->winSize.height*scale));
1602 
1603             mtx->lock();
1604             for( size_t j = 0; j < locations.size(); j++ )
1605             {
1606                 vec->push_back(Rect(cvRound(locations[j].x*scale),
1607                                     cvRound(locations[j].y*scale),
1608                                     scaledWinSize.width, scaledWinSize.height));
1609                 if (scales)
1610                     scales->push_back(scale);
1611             }
1612             mtx->unlock();
1613 
1614             if (weights && (!hitsWeights.empty()))
1615             {
1616                 mtx->lock();
1617                 for (size_t j = 0; j < locations.size(); j++)
1618                     weights->push_back(hitsWeights[j]);
1619                 mtx->unlock();
1620             }
1621         }
1622     }
1623 
1624 private:
1625     const HOGDescriptor* hog;
1626     Mat img;
1627     double hitThreshold;
1628     Size winStride;
1629     Size padding;
1630     const double* levelScale;
1631     std::vector<Rect>* vec;
1632     std::vector<double>* weights;
1633     std::vector<double>* scales;
1634     Mutex* mtx;
1635 };
1636 
1637 #ifdef HAVE_OPENCL
1638 
ocl_classify_hists(int win_height,int win_width,int block_stride_y,int block_stride_x,int win_stride_y,int win_stride_x,int height,int width,const UMat & block_hists,UMat detector,float free_coef,float threshold,UMat & labels,Size descr_size,int block_hist_size)1639 static bool ocl_classify_hists(int win_height, int win_width, int block_stride_y, int block_stride_x,
1640                                int win_stride_y, int win_stride_x, int height, int width,
1641                                const UMat& block_hists, UMat detector,
1642                                float free_coef, float threshold, UMat& labels, Size descr_size, int block_hist_size)
1643 {
1644     int nthreads;
1645     bool is_cpu = cv::ocl::Device::getDefault().type() == cv::ocl::Device::TYPE_CPU;
1646     cv::String opts;
1647 
1648     ocl::Kernel k;
1649     int idx = 0;
1650     switch (descr_size.width)
1651     {
1652     case 180:
1653         nthreads = 180;
1654         k.create("classify_hists_180_kernel", ocl::objdetect::objdetect_hog_oclsrc, "");
1655         if(k.empty())
1656             return false;
1657         if(is_cpu)
1658            opts = "-D CPU ";
1659         else
1660             opts = cv::format("-D WAVE_SIZE=%d", k.preferedWorkGroupSizeMultiple());
1661         k.create("classify_hists_180_kernel", ocl::objdetect::objdetect_hog_oclsrc, opts);
1662         if(k.empty())
1663             return false;
1664         idx = k.set(idx, descr_size.width);
1665         idx = k.set(idx, descr_size.height);
1666         break;
1667 
1668     case 252:
1669         nthreads = 256;
1670         k.create("classify_hists_252_kernel", ocl::objdetect::objdetect_hog_oclsrc, "");
1671         if(k.empty())
1672             return false;
1673         if(is_cpu)
1674            opts = "-D CPU ";
1675         else
1676             opts = cv::format("-D WAVE_SIZE=%d", k.preferedWorkGroupSizeMultiple());
1677         k.create("classify_hists_252_kernel", ocl::objdetect::objdetect_hog_oclsrc, opts);
1678         if(k.empty())
1679             return false;
1680         idx = k.set(idx, descr_size.width);
1681         idx = k.set(idx, descr_size.height);
1682         break;
1683 
1684     default:
1685         nthreads = 256;
1686         k.create("classify_hists_kernel", ocl::objdetect::objdetect_hog_oclsrc, "");
1687         if(k.empty())
1688             return false;
1689         if(is_cpu)
1690            opts = "-D CPU ";
1691         else
1692             opts = cv::format("-D WAVE_SIZE=%d", k.preferedWorkGroupSizeMultiple());
1693         k.create("classify_hists_kernel", ocl::objdetect::objdetect_hog_oclsrc, opts);
1694         if(k.empty())
1695             return false;
1696         idx = k.set(idx, descr_size.area());
1697         idx = k.set(idx, descr_size.height);
1698     }
1699 
1700     int win_block_stride_x = win_stride_x / block_stride_x;
1701     int win_block_stride_y = win_stride_y / block_stride_y;
1702     int img_win_width = (width - win_width + win_stride_x) / win_stride_x;
1703     int img_win_height = (height - win_height + win_stride_y) / win_stride_y;
1704     int img_block_width = (width - CELLS_PER_BLOCK_X * CELL_WIDTH + block_stride_x) /
1705         block_stride_x;
1706 
1707     size_t globalThreads[3] = { img_win_width * nthreads, img_win_height, 1 };
1708     size_t localThreads[3] = { nthreads, 1, 1 };
1709 
1710     idx = k.set(idx, block_hist_size);
1711     idx = k.set(idx, img_win_width);
1712     idx = k.set(idx, img_block_width);
1713     idx = k.set(idx, win_block_stride_x);
1714     idx = k.set(idx, win_block_stride_y);
1715     idx = k.set(idx, ocl::KernelArg::PtrReadOnly(block_hists));
1716     idx = k.set(idx, ocl::KernelArg::PtrReadOnly(detector));
1717     idx = k.set(idx, free_coef);
1718     idx = k.set(idx, threshold);
1719     idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(labels));
1720 
1721     return k.run(2, globalThreads, localThreads, false);
1722 }
1723 
ocl_detect(InputArray img,std::vector<Point> & hits,double hit_threshold,Size win_stride,const UMat & oclSvmDetector,Size blockSize,Size cellSize,int nbins,Size blockStride,Size winSize,bool gammaCorrection,double L2HysThreshold,float sigma,float free_coef,bool signedGradient)1724 static bool ocl_detect(InputArray img, std::vector<Point> &hits, double hit_threshold, Size win_stride,
1725                        const UMat& oclSvmDetector, Size blockSize, Size cellSize, int nbins, Size blockStride, Size winSize,
1726                        bool gammaCorrection, double L2HysThreshold, float sigma, float free_coef, bool signedGradient)
1727 {
1728     hits.clear();
1729     if (oclSvmDetector.empty())
1730         return false;
1731 
1732     Size imgSize = img.size();
1733     Size effect_size = imgSize;
1734     UMat grad(imgSize, CV_32FC2);
1735     int qangle_type = ocl::Device::getDefault().isIntel() ? CV_32SC2 : CV_8UC2;
1736     UMat qangle(imgSize, qangle_type);
1737 
1738     const size_t block_hist_size = getBlockHistogramSize(blockSize, cellSize, nbins);
1739     const Size blocks_per_img = numPartsWithin(imgSize, blockSize, blockStride);
1740     UMat block_hists(1, static_cast<int>(block_hist_size * blocks_per_img.area()) + 256, CV_32F);
1741 
1742     Size wins_per_img = numPartsWithin(imgSize, winSize, win_stride);
1743     UMat labels(1, wins_per_img.area(), CV_8U);
1744 
1745     float scale = 1.f / (2.f * sigma * sigma);
1746     Mat gaussian_lut(1, 512, CV_32FC1);
1747     int idx = 0;
1748     for(int i=-8; i<8; i++)
1749         for(int j=-8; j<8; j++)
1750             gaussian_lut.at<float>(idx++) = std::exp(-(j * j + i * i) * scale);
1751     for(int i=-8; i<8; i++)
1752         for(int j=-8; j<8; j++)
1753             gaussian_lut.at<float>(idx++) = (8.f - fabs(j + 0.5f)) * (8.f - fabs(i + 0.5f)) / 64.f;
1754 
1755     if(!ocl_computeGradient(img, grad, qangle, nbins, effect_size, gammaCorrection, signedGradient))
1756         return false;
1757 
1758     UMat gauss_w_lut;
1759     gaussian_lut.copyTo(gauss_w_lut);
1760     if(!ocl_compute_hists(nbins, blockStride.width, blockStride.height, effect_size.height,
1761         effect_size.width, grad, qangle, gauss_w_lut, block_hists, block_hist_size))
1762         return false;
1763 
1764     if(!ocl_normalize_hists(nbins, blockStride.width, blockStride.height, effect_size.height,
1765         effect_size.width, block_hists, (float)L2HysThreshold))
1766         return false;
1767 
1768     Size blocks_per_win = numPartsWithin(winSize, blockSize, blockStride);
1769 
1770     Size descr_size((int)block_hist_size*blocks_per_win.width, blocks_per_win.height);
1771 
1772     if(!ocl_classify_hists(winSize.height, winSize.width, blockStride.height,
1773         blockStride.width, win_stride.height, win_stride.width,
1774         effect_size.height, effect_size.width, block_hists, oclSvmDetector,
1775         free_coef, (float)hit_threshold, labels, descr_size, (int)block_hist_size))
1776         return false;
1777 
1778     Mat labels_host = labels.getMat(ACCESS_READ);
1779     unsigned char *vec = labels_host.ptr();
1780     for (int i = 0; i < wins_per_img.area(); i++)
1781     {
1782         int y = i / wins_per_img.width;
1783         int x = i - wins_per_img.width * y;
1784         if (vec[i])
1785         {
1786             hits.push_back(Point(x * win_stride.width, y * win_stride.height));
1787         }
1788     }
1789     return true;
1790 }
1791 
ocl_detectMultiScale(InputArray _img,std::vector<Rect> & found_locations,std::vector<double> & level_scale,double hit_threshold,Size win_stride,double group_threshold,const UMat & oclSvmDetector,Size blockSize,Size cellSize,int nbins,Size blockStride,Size winSize,bool gammaCorrection,double L2HysThreshold,float sigma,float free_coef,bool signedGradient)1792 static bool ocl_detectMultiScale(InputArray _img, std::vector<Rect> &found_locations, std::vector<double>& level_scale,
1793                                               double hit_threshold, Size win_stride, double group_threshold,
1794                                               const UMat& oclSvmDetector, Size blockSize, Size cellSize,
1795                                               int nbins, Size blockStride, Size winSize, bool gammaCorrection,
1796                                               double L2HysThreshold, float sigma, float free_coef, bool signedGradient)
1797 {
1798     std::vector<Rect> all_candidates;
1799     std::vector<Point> locations;
1800     UMat image_scale;
1801     Size imgSize = _img.size();
1802     image_scale.create(imgSize, _img.type());
1803 
1804     for (size_t i = 0; i<level_scale.size() ; i++)
1805     {
1806         double scale = level_scale[i];
1807         Size effect_size = Size(cvRound(imgSize.width / scale), cvRound(imgSize.height / scale));
1808         if (effect_size == imgSize)
1809         {
1810             if(!ocl_detect(_img, locations, hit_threshold, win_stride, oclSvmDetector, blockSize, cellSize, nbins,
1811                 blockStride, winSize, gammaCorrection, L2HysThreshold, sigma, free_coef, signedGradient))
1812                 return false;
1813         }
1814         else
1815         {
1816             resize(_img, image_scale, effect_size);
1817             if(!ocl_detect(image_scale, locations, hit_threshold, win_stride, oclSvmDetector, blockSize, cellSize, nbins,
1818                 blockStride, winSize, gammaCorrection, L2HysThreshold, sigma, free_coef, signedGradient))
1819                 return false;
1820         }
1821         Size scaled_win_size(cvRound(winSize.width * scale),
1822             cvRound(winSize.height * scale));
1823         for (size_t j = 0; j < locations.size(); j++)
1824             all_candidates.push_back(Rect(Point2d(locations[j]) * scale, scaled_win_size));
1825     }
1826     found_locations.assign(all_candidates.begin(), all_candidates.end());
1827     groupRectangles(found_locations, (int)group_threshold, 0.2);
1828     clipObjects(imgSize, found_locations, 0, 0);
1829 
1830     return true;
1831 }
1832 #endif //HAVE_OPENCL
1833 
detectMultiScale(InputArray _img,std::vector<Rect> & foundLocations,std::vector<double> & foundWeights,double hitThreshold,Size winStride,Size padding,double scale0,double finalThreshold,bool useMeanshiftGrouping) const1834 void HOGDescriptor::detectMultiScale(
1835     InputArray _img, std::vector<Rect>& foundLocations, std::vector<double>& foundWeights,
1836     double hitThreshold, Size winStride, Size padding,
1837     double scale0, double finalThreshold, bool useMeanshiftGrouping) const
1838 {
1839     double scale = 1.;
1840     int levels = 0;
1841 
1842     Size imgSize = _img.size();
1843     std::vector<double> levelScale;
1844     for( levels = 0; levels < nlevels; levels++ )
1845     {
1846         levelScale.push_back(scale);
1847         if( cvRound(imgSize.width/scale) < winSize.width ||
1848             cvRound(imgSize.height/scale) < winSize.height ||
1849                 scale0 <= 1 )
1850             break;
1851         scale *= scale0;
1852     }
1853     levels = std::max(levels, 1);
1854     levelScale.resize(levels);
1855 
1856     if(winStride == Size())
1857         winStride = blockStride;
1858 
1859     CV_OCL_RUN(_img.dims() <= 2 && _img.type() == CV_8UC1 && scale0 > 1 && winStride.width % blockStride.width == 0 &&
1860         winStride.height % blockStride.height == 0 && padding == Size(0,0) && _img.isUMat(),
1861         ocl_detectMultiScale(_img, foundLocations, levelScale, hitThreshold, winStride, finalThreshold, oclSvmDetector,
1862         blockSize, cellSize, nbins, blockStride, winSize, gammaCorrection, L2HysThreshold, (float)getWinSigma(), free_coef, signedGradient));
1863 
1864     std::vector<Rect> allCandidates;
1865     std::vector<double> tempScales;
1866     std::vector<double> tempWeights;
1867     std::vector<double> foundScales;
1868 
1869     Mutex mtx;
1870     Mat img = _img.getMat();
1871     Range range(0, (int)levelScale.size());
1872     HOGInvoker invoker(this, img, hitThreshold, winStride, padding, &levelScale[0], &allCandidates, &mtx, &tempWeights, &tempScales);
1873     parallel_for_(range, invoker);
1874 
1875     std::copy(tempScales.begin(), tempScales.end(), back_inserter(foundScales));
1876     foundLocations.clear();
1877     std::copy(allCandidates.begin(), allCandidates.end(), back_inserter(foundLocations));
1878     foundWeights.clear();
1879     std::copy(tempWeights.begin(), tempWeights.end(), back_inserter(foundWeights));
1880 
1881     if ( useMeanshiftGrouping )
1882         groupRectangles_meanshift(foundLocations, foundWeights, foundScales, finalThreshold, winSize);
1883     else
1884         groupRectangles(foundLocations, foundWeights, (int)finalThreshold, 0.2);
1885     clipObjects(imgSize, foundLocations, 0, &foundWeights);
1886 }
1887 
detectMultiScale(InputArray img,std::vector<Rect> & foundLocations,double hitThreshold,Size winStride,Size padding,double scale0,double finalThreshold,bool useMeanshiftGrouping) const1888 void HOGDescriptor::detectMultiScale(InputArray img, std::vector<Rect>& foundLocations,
1889     double hitThreshold, Size winStride, Size padding,
1890     double scale0, double finalThreshold, bool useMeanshiftGrouping) const
1891 {
1892     std::vector<double> foundWeights;
1893     detectMultiScale(img, foundLocations, foundWeights, hitThreshold, winStride,
1894                 padding, scale0, finalThreshold, useMeanshiftGrouping);
1895 }
1896 
1897 template<typename _ClsName> struct RTTIImpl
1898 {
1899 public:
isInstancecv::RTTIImpl1900     static int isInstance(const void* ptr)
1901     {
1902         static _ClsName dummy;
1903         static void* dummyp = &dummy;
1904         union
1905         {
1906             const void* p;
1907             const void** pp;
1908         } a, b;
1909         a.p = dummyp;
1910         b.p = ptr;
1911         return *a.pp == *b.pp;
1912     }
releasecv::RTTIImpl1913     static void release(void** dbptr)
1914     {
1915         if(dbptr && *dbptr)
1916         {
1917             delete (_ClsName*)*dbptr;
1918             *dbptr = 0;
1919         }
1920     }
readcv::RTTIImpl1921     static void* read(CvFileStorage* fs, CvFileNode* n)
1922     {
1923         FileNode fn(fs, n);
1924         _ClsName* obj = new _ClsName;
1925         if(obj->read(fn))
1926             return obj;
1927         delete obj;
1928         return 0;
1929     }
1930 
writecv::RTTIImpl1931     static void write(CvFileStorage* _fs, const char* name, const void* ptr, CvAttrList)
1932     {
1933         if(ptr && _fs)
1934         {
1935             FileStorage fs(_fs, false);
1936             ((const _ClsName*)ptr)->write(fs, String(name));
1937         }
1938     }
1939 
clonecv::RTTIImpl1940     static void* clone(const void* ptr)
1941     {
1942         if(!ptr)
1943             return 0;
1944         return new _ClsName(*(const _ClsName*)ptr);
1945     }
1946 };
1947 
1948 typedef RTTIImpl<HOGDescriptor> HOGRTTI;
1949 
1950 CvType hog_type( CV_TYPE_NAME_HOG_DESCRIPTOR, HOGRTTI::isInstance,
1951     HOGRTTI::release, HOGRTTI::read, HOGRTTI::write, HOGRTTI::clone);
1952 
getDefaultPeopleDetector()1953 std::vector<float> HOGDescriptor::getDefaultPeopleDetector()
1954 {
1955     static const float detector[] = {
1956         0.05359386f, -0.14721455f, -0.05532170f, 0.05077307f,
1957         0.11547081f, -0.04268804f, 0.04635834f, -0.05468199f, 0.08232084f,
1958         0.10424068f, -0.02294518f, 0.01108519f, 0.01378693f, 0.11193510f,
1959         0.01268418f, 0.08528346f, -0.06309239f, 0.13054633f, 0.08100729f,
1960         -0.05209739f, -0.04315529f, 0.09341384f, 0.11035026f, -0.07596218f,
1961         -0.05517511f, -0.04465296f, 0.02947334f, 0.04555536f,
1962         -3.55954492e-003f, 0.07818956f, 0.07730991f, 0.07890715f, 0.06222893f,
1963         0.09001380f, -0.03574381f, 0.03414327f, 0.05677258f, -0.04773581f,
1964         0.03746637f, -0.03521175f, 0.06955440f, -0.03849038f, 0.01052293f,
1965         0.01736112f, 0.10867710f, 0.08748853f, 3.29739624e-003f, 0.10907028f,
1966         0.07913758f, 0.10393070f, 0.02091867f, 0.11594022f, 0.13182420f,
1967         0.09879354f, 0.05362710f, -0.06745391f, -7.01260753e-003f,
1968         5.24702156e-003f, 0.03236255f, 0.01407916f, 0.02207983f, 0.02537322f,
1969         0.04547948f, 0.07200756f, 0.03129894f, -0.06274468f, 0.02107014f,
1970         0.06035208f, 0.08636236f, 4.53164103e-003f, 0.02193363f, 0.02309801f,
1971         0.05568166f, -0.02645093f, 0.04448695f, 0.02837519f, 0.08975694f,
1972         0.04461516f, 0.08975355f, 0.07514391f, 0.02306982f, 0.10410084f,
1973         0.06368385f, 0.05943464f, 4.58420580e-003f, 0.05220337f, 0.06675851f,
1974         0.08358569f, 0.06712101f, 0.06559004f, -0.03930482f, -9.15936660e-003f,
1975         -0.05897915f, 0.02816453f, 0.05032348f, 0.06780671f, 0.03377650f,
1976         -6.09417039e-004f, -0.01795146f, -0.03083684f, -0.01302475f,
1977         -0.02972313f, 7.88706727e-003f, -0.03525961f, -2.50397739e-003f,
1978         0.05245084f, 0.11791293f, -0.02167498f, 0.05299332f, 0.06640524f,
1979         0.05190265f, -8.27316567e-003f, 0.03033127f, 0.05842173f,
1980         -4.01050318e-003f, -6.25105947e-003f, 0.05862958f, -0.02465461f,
1981         0.05546781f, -0.08228195f, -0.07234028f, 0.04640540f, -0.01308254f,
1982         -0.02506191f, 0.03100746f, -0.04665651f, -0.04591486f, 0.02949927f,
1983         0.06035462f, 0.02244646f, -0.01698639f, 0.01040041f, 0.01131170f,
1984         0.05419579f, -0.02130277f, -0.04321722f, -0.03665198f, 0.01126490f,
1985         -0.02606488f, -0.02228328f, -0.02255680f, -0.03427236f,
1986         -7.75165204e-003f, -0.06195229f, 8.21638294e-003f, 0.09535975f,
1987         -0.03709979f, -0.06942501f, 0.14579427f, -0.05448192f, -0.02055904f,
1988         0.05747357f, 0.02781788f, -0.07077577f, -0.05178314f, -0.10429011f,
1989         -0.11235505f, 0.07529039f, -0.07559302f, -0.08786739f, 0.02983843f,
1990         0.02667585f, 0.01382199f, -0.01797496f, -0.03141199f, -0.02098101f,
1991         0.09029204f, 0.04955018f, 0.13718739f, 0.11379953f, 1.80019124e-003f,
1992         -0.04577610f, -1.11108483e-003f, -0.09470536f, -0.11596080f,
1993         0.04489342f, 0.01784211f, 3.06850672e-003f, 0.10781866f,
1994         3.36498418e-003f, -0.10842580f, -0.07436839f, -0.10535070f,
1995         -0.01866805f, 0.16057891f, -5.07316366e-003f, -0.04295658f,
1996         -5.90488780e-003f, 8.82003549e-003f, -0.01492646f, -0.05029279f,
1997         -0.12875880f, 8.78831954e-004f, -0.01297184f, -0.07592774f,
1998         -0.02668831f, -6.93787413e-004f, 0.02406698f, -0.01773298f,
1999         -0.03855745f, -0.05877856f, 0.03259695f, 0.12826584f, 0.06292590f,
2000         -4.10733931e-003f, 0.10996531f, 0.01332991f, 0.02088735f, 0.04037504f,
2001         -0.05210760f, 0.07760046f, 0.06399347f, -0.05751930f, -0.10053057f,
2002         0.07505023f, -0.02139782f, 0.01796176f, 2.34400877e-003f, -0.04208319f,
2003         0.07355055f, 0.05093350f, -0.02996780f, -0.02219072f, 0.03355330f,
2004         0.04418742f, -0.05580705f, -0.05037573f, -0.04548179f, 0.01379514f,
2005         0.02150671f, -0.02194211f, -0.13682702f, 0.05464972f, 0.01608082f,
2006         0.05309116f, 0.04701022f, 1.33690401e-003f, 0.07575664f, 0.09625306f,
2007         8.92647635e-003f, -0.02819123f, 0.10866830f, -0.03439325f,
2008         -0.07092371f, -0.06004780f, -0.02712298f, -7.07467366e-003f,
2009         -0.01637020f, 0.01336790f, -0.10313606f, 0.04906582f, -0.05732445f,
2010         -0.02731079f, 0.01042235f, -0.08340668f, 0.03686501f, 0.06108340f,
2011         0.01322748f, -0.07809529f, 0.03774724f, -0.03413248f, -0.06096525f,
2012         -0.04212124f, -0.07982176f, -1.25973229e-003f, -0.03045501f,
2013         -0.01236493f, -0.06312395f, 0.04789570f, -0.04602066f, 0.08576570f,
2014         0.02521080f, 0.02988098f, 0.10314583f, 0.07060035f, 0.04520544f,
2015         -0.04426654f, 0.13146530f, 0.08386490f, 0.02164590f, -2.12280243e-003f,
2016         -0.03686353f, -0.02074944f, -0.03829959f, -0.01530596f, 0.02689708f,
2017         0.11867401f, -0.06043470f, -0.02785023f, -0.04775074f, 0.04878745f,
2018         0.06350956f, 0.03494788f, 0.01467400f, 1.17890188e-003f, 0.04379614f,
2019         2.03681854e-003f, -0.03958609f, -0.01072688f, 6.43705716e-003f,
2020         0.02996500f, -0.03418507f, -0.01960307f, -0.01219154f,
2021         -4.37000440e-003f, -0.02549453f, 0.02646318f, -0.01632513f,
2022         6.46516960e-003f, -0.01929734f, 4.78711911e-003f, 0.04962371f,
2023         0.03809111f, 0.07265724f, 0.05758125f, -0.03741554f, 0.01648608f,
2024         -8.45285598e-003f, 0.03996826f, -0.08185477f, 0.02638875f,
2025         -0.04026615f, -0.02744674f, -0.04071517f, 1.05096330e-003f,
2026         -0.04741232f, -0.06733172f, 8.70434940e-003f, -0.02192543f,
2027         1.35350740e-003f, -0.03056974f, -0.02975521f, -0.02887780f,
2028         -0.01210713f, -0.04828526f, -0.09066251f, -0.09969629f, -0.03665164f,
2029         -8.88111943e-004f, -0.06826669f, -0.01866150f, -0.03627640f,
2030         -0.01408288f, 0.01874239f, -0.02075835f, 0.09145175f, -0.03547291f,
2031         0.05396780f, 0.04198981f, 0.01301925f, -0.03384354f, -0.12201976f,
2032         0.06830920f, -0.03715654f, 9.55848210e-003f, 5.05685573e-003f,
2033         0.05659294f, 3.90764466e-003f, 0.02808490f, -0.05518097f, -0.03711621f,
2034         -0.02835565f, -0.04420464f, -0.01031947f, 0.01883466f,
2035         -8.49525444e-003f, -0.09419250f, -0.01269387f, -0.02133371f,
2036         -0.10190815f, -0.07844430f, 2.43644323e-003f, -4.09610150e-003f,
2037         0.01202551f, -0.06452291f, -0.10593818f, -0.02464746f, -0.02199699f,
2038         -0.07401930f, 0.07285886f, 8.87513801e-004f, 9.97662079e-003f,
2039         8.46779719e-003f, 0.03730333f, -0.02905126f, 0.03573337f, -0.04393689f,
2040         -0.12014472f, 0.03176554f, -2.76015815e-003f, 0.10824566f, 0.05090732f,
2041         -3.30179278e-003f, -0.05123822f, 5.04784798e-003f, -0.05664124f,
2042         -5.99415926e-003f, -0.05341901f, -0.01221393f, 0.01291318f,
2043         9.91760660e-003f, -7.56987557e-003f, -0.06193124f, -2.24549137e-003f,
2044         0.01987562f, -0.02018840f, -0.06975540f, -0.06601523f, -0.03349112f,
2045         -0.08910118f, -0.03371435f, -0.07406893f, -0.02248047f, -0.06159951f,
2046         2.77751544e-003f, -0.05723337f, -0.04792468f, 0.07518548f,
2047         2.77279224e-003f, 0.04211938f, 0.03100502f, 0.05278448f, 0.03954679f,
2048         -0.03006846f, -0.03851741f, -0.02792403f, -0.02875333f, 0.01531280f,
2049         0.02186953f, -0.01989829f, 2.50679464e-003f, -0.10258728f,
2050         -0.04785743f, -0.02887216f, 3.85063468e-003f, 0.01112236f,
2051         8.29218887e-003f, -0.04822981f, -0.04503597f, -0.03713100f,
2052         -0.06988008f, -0.11002295f, -2.69209221e-003f, 1.85383670e-003f,
2053         -0.05921049f, -0.06105053f, -0.08458050f, -0.04527602f,
2054         8.90329306e-004f, -0.05875023f, -2.68602883e-003f, -0.01591195f,
2055         0.03631859f, 0.05493166f, 0.07300330f, 5.53333294e-003f, 0.06400407f,
2056         0.01847740f, -5.76280477e-003f, -0.03210877f, 4.25160583e-003f,
2057         0.01166520f, -1.44864211e-003f, 0.02253744f, -0.03367080f, 0.06983195f,
2058         -4.22323542e-003f, -8.89401045e-003f, -0.07943393f, 0.05199728f,
2059         0.06065201f, 0.04133492f, 1.44032843e-003f, -0.09585235f, -0.03964731f,
2060         0.04232114f, 0.01750465f, -0.04487902f, -7.59733608e-003f, 0.02011171f,
2061         0.04673622f, 0.09011173f, -0.07869188f, -0.04682482f, -0.05080139f,
2062         -3.99383716e-003f, -0.05346331f, 0.01085723f, -0.03599333f,
2063         -0.07097908f, 0.03551549f, 0.02680387f, 0.03471529f, 0.01790393f,
2064         0.05471273f, 9.62048303e-003f, -0.03180215f, 0.05864431f, 0.02330614f,
2065         0.01633144f, -0.05616681f, -0.10245429f, -0.08302189f, 0.07291322f,
2066         -0.01972590f, -0.02619633f, -0.02485327f, -0.04627592f,
2067         1.48853404e-003f, 0.05514185f, -0.01270860f, -0.01948900f, 0.06373586f,
2068         0.05002292f, -0.03009798f, 8.76216311e-003f, -0.02474238f,
2069         -0.05504891f, 1.74034527e-003f, -0.03333667f, 0.01524987f, 0.11663762f,
2070         -1.32344989e-003f, -0.06608453f, 0.05687166f, -6.89525274e-004f,
2071         -0.04402352f, 0.09450210f, -0.04222684f, -0.05360983f, 0.01779531f,
2072         0.02561388f, -0.11075410f, -8.77790991e-003f, -0.01099504f,
2073         -0.10380266f, 0.03103457f, -0.02105741f, -0.07371717f, 0.05146710f,
2074         0.10581432f, -0.08617968f, -0.02892107f, 0.01092199f, 0.14551543f,
2075         -2.24320893e-003f, -0.05818033f, -0.07390742f, 0.05701261f,
2076         0.12937020f, -0.04986651f, 0.10182415f, 0.05028650f, 0.12515625f,
2077         0.09175041f, 0.06404983f, 0.01523394f, 0.09460562f, 0.06106631f,
2078         -0.14266998f, -0.02926703f, 0.02762171f, 0.02164151f,
2079         -9.58488265e-004f, -0.04231362f, -0.09866509f, 0.04322244f,
2080         0.05872034f, -0.04838847f, 0.06319253f, 0.02443798f, -0.03606876f,
2081         9.38737206e-003f, 0.04289991f, -0.01027411f, 0.08156885f, 0.08751175f,
2082         -0.13191354f, 8.16054735e-003f, -0.01452161f, 0.02952677f, 0.03615945f,
2083         -2.09128903e-003f, 0.02246693f, 0.09623287f, 0.09412123f, -0.02924758f,
2084         -0.07815186f, -0.02203079f, -2.02566991e-003f, 0.01094733f,
2085         -0.01442332f, 0.02838561f, 0.11882371f, 7.28798332e-003f, -0.10345965f,
2086         0.07561217f, -0.02049661f, 4.44177445e-003f, 0.01609347f, -0.04893158f,
2087         -0.08758243f, -7.67420698e-003f, 0.08862378f, 0.06098121f, 0.06565887f,
2088         7.32981879e-003f, 0.03558407f, -0.03874352f, -0.02490055f,
2089         -0.06771075f, 0.09939223f, -0.01066077f, 0.01382995f, -0.07289080f,
2090         7.47184316e-003f, 0.10621431f, -0.02878659f, 0.02383525f, -0.03274646f,
2091         0.02137008f, 0.03837290f, 0.02450992f, -0.04296818f, -0.02895143f,
2092         0.05327370f, 0.01499020f, 0.04998732f, 0.12938657f, 0.09391870f,
2093         0.04292390f, -0.03359194f, -0.06809492f, 0.01125796f, 0.17290455f,
2094         -0.03430733f, -0.06255233f, -0.01813114f, 0.11726857f, -0.06127599f,
2095         -0.08677909f, -0.03429872f, 0.04684938f, 0.08161420f, 0.03538774f,
2096         0.01833884f, 0.11321855f, 0.03261845f, -0.04826299f, 0.01752407f,
2097         -0.01796414f, -0.10464549f, -3.30041884e-003f, 2.29343961e-004f,
2098         0.01457292f, -0.02132982f, -0.02602923f, -9.87351313e-003f,
2099         0.04273872f, -0.02103316f, -0.07994065f, 0.02614958f, -0.02111666f,
2100         -0.06964913f, -0.13453490f, -0.06861878f, -6.09341264e-003f,
2101         0.08251446f, 0.15612499f, 2.46531400e-003f, 8.88424646e-003f,
2102         -0.04152999f, 0.02054853f, 0.05277953f, -0.03087788f, 0.02817579f,
2103         0.13939077f, 0.07641046f, -0.03627627f, -0.03015098f, -0.04041540f,
2104         -0.01360690f, -0.06227205f, -0.02738223f, 0.13577610f, 0.15235767f,
2105         -0.05392922f, -0.11175954f, 0.02157129f, 0.01146481f, -0.05264937f,
2106         -0.06595174f, -0.02749175f, 0.11812254f, 0.17404149f, -0.06137035f,
2107         -0.11003478f, -0.01351621f, -0.01745916f, -0.08577441f, -0.04469909f,
2108         -0.06106115f, 0.10559758f, 0.20806813f, -0.09174948f, 7.09621934e-004f,
2109         0.03579374f, 0.07215115f, 0.02221742f, 0.01827742f, -7.90785067e-003f,
2110         0.01489554f, 0.14519960f, -0.06425831f, 0.02990399f, -1.80181325e-003f,
2111         -0.01401528f, -0.04171134f, -3.70530109e-003f, -0.09090481f,
2112         0.09520713f, 0.08845516f, -0.02651753f, -0.03016730f, 0.02562448f,
2113         0.03563816f, -0.03817881f, 0.01433385f, 0.02256983f, 0.02872120f,
2114         0.01001934f, -0.06332260f, 0.04338406f, 0.07001807f, -0.04705722f,
2115         -0.07318907f, 0.02630457f, 0.03106382f, 0.06648342f, 0.10913180f,
2116         -0.01630815f, 0.02910308f, 0.02895109f, 0.08040254f, 0.06969310f,
2117         0.06797734f, 6.08639978e-003f, 4.16588830e-003f, 0.08926726f,
2118         -0.03123648f, 0.02700146f, 0.01168734f, -0.01631594f, 4.61015804e-003f,
2119         8.51359498e-003f, -0.03544224f, 0.03571994f, 4.29766066e-003f,
2120         -0.01970077f, -8.79793242e-003f, 0.09607988f, 0.01544222f,
2121         -0.03923707f, 0.07308586f, 0.06061262f, 1.31683104e-004f,
2122         -7.98222050e-003f, 0.02399261f, -0.06084389f, -0.02743429f,
2123         -0.05475523f, -0.04131311f, 0.03559756f, 0.03055342f, 0.02981433f,
2124         0.14860515f, 0.01766787f, 0.02945257f, 0.04898238f, 0.01026922f,
2125         0.02811658f, 0.08267091f, 0.02732154f, -0.01237693f, 0.11760156f,
2126         0.03802063f, -0.03309754f, 5.24957618e-003f, -0.02460510f, 0.02691451f,
2127         0.05399988f, -0.10133506f, 0.06385437f, -0.01818005f, 0.02259503f,
2128         0.03573135f, 0.01042848f, -0.04153402f, -0.04043029f, 0.01643575f,
2129         0.08326677f, 4.61383024e-004f, -0.05308095f, -0.08536223f,
2130         -1.61011645e-003f, -0.02163720f, -0.01783352f, 0.03859637f,
2131         0.08498885f, -0.01725216f, 0.08625131f, 0.10995087f, 0.09177644f,
2132         0.08498347f, 0.07646490f, 0.05580502f, 0.02693516f, 0.09996913f,
2133         0.09070327f, 0.06667200f, 0.05873008f, -0.02247842f, 0.07772321f,
2134         0.12408436f, 0.12629253f, -8.41997913e-004f, 0.01477783f, 0.09165990f,
2135         -2.98401713e-003f, -0.06466447f, -0.07057302f, 2.09516948e-004f,
2136         0.02210209f, -0.02158809f, -0.08602506f, -0.02284836f,
2137         4.01876355e-003f, 9.56660323e-003f, -0.02073978f, -0.04635138f,
2138         -7.59423291e-003f, -0.01377393f, -0.04559359f, -0.13284740f,
2139         -0.08671406f, -0.03654395f, 0.01142869f, 0.03287891f, -0.04392983f,
2140         0.06142959f, 0.17710890f, 0.10385257f, 0.01329137f, 0.10067633f,
2141         0.12450829f, -0.04476709f, 0.09049144f, 0.04589312f, 0.11167907f,
2142         0.08587538f, 0.04767583f, 1.67188141e-003f, 0.02359802f, -0.03808852f,
2143         0.03126272f, -0.01919029f, -0.05698918f, -0.02365112f, -0.06519032f,
2144         -0.05599358f, -0.07097308f, -0.03301812f, -0.04719102f, -0.02566297f,
2145         0.01324074f, -0.09230672f, -0.05518232f, -0.04712864f, -0.03380903f,
2146         -0.06719479f, 0.01183908f, -0.09326738f, 0.01642865f, 0.03789867f,
2147         -6.61567831e-003f, 0.07796386f, 0.07246574f, 0.04706347f, -0.02523437f,
2148         -0.01696830f, -0.08068866f, 0.06030888f, 0.10527060f, -0.06611756f,
2149         0.02977346f, 0.02621830f, 0.01913855f, -0.08479366f, -0.06322418f,
2150         -0.13570616f, -0.07644490f, 9.31900274e-003f, -0.08095149f,
2151         -0.10197903f, -0.05204025f, 0.01413151f, -0.07800411f, -0.01885122f,
2152         -0.07509381f, -0.10136326f, -0.05212355f, -0.09944065f,
2153         -1.33606605e-003f, -0.06342617f, -0.04178550f, -0.12373723f,
2154         -0.02832736f, -0.06057501f, 0.05830070f, 0.07604282f, -0.06462587f,
2155         8.02447461e-003f, 0.11580125f, 0.12332212f, 0.01978462f,
2156         -2.72378162e-003f, 0.05850752f, -0.04674481f, 0.05148062f,
2157         -2.62542837e-003f, 0.11253355f, 0.09893716f, 0.09785093f, -0.04659257f,
2158         -0.01102429f, -0.07002308f, 0.03088913f, -0.02565549f, -0.07671449f,
2159         3.17443861e-003f, -0.10783514f, -0.02314270f, -0.11089555f,
2160         -0.01024768f, 0.03116021f, -0.04964825f, 0.02281825f, 5.50005678e-003f,
2161         -0.08427856f, -0.14685495f, -0.07719755f, -0.13342668f, -0.04525511f,
2162         -0.09914210f, 0.02588859f, 0.03469279f, 0.04664020f, 0.11688190f,
2163         0.09647275f, 0.10857815f, -0.01448726f, 0.04299758f, -0.06763151f,
2164         1.33257592e-003f, 0.14331576f, 0.07574340f, 0.09166205f, 0.05674926f,
2165         0.11325553f, -0.01106494f, 0.02062161f, -0.11484840f, -0.07492137f,
2166         -0.02864293f, -0.01275638f, -0.06946032f, -0.10101652f, -0.04113498f,
2167         -0.02214783f, -0.01273942f, -0.07480393f, -0.10556041f, -0.07622112f,
2168         -0.09988393f, -0.11453961f, -0.12073903f, -0.09412795f, -0.07146588f,
2169         -0.04054537f, -0.06127083f, 0.04221122f, 0.07688113f, 0.04099256f,
2170         0.12663734f, 0.14683802f, 0.21761774f, 0.12525328f, 0.18431792f,
2171         -1.66402373e-003f, 2.37777247e-003f, 0.01445475f, 0.03509416f,
2172         0.02654697f, 0.01716739f, 0.05374011f, 0.02944174f, 0.11323927f,
2173         -0.01485456f, -0.01611330f, -1.85554172e-003f, -0.01708549f,
2174         -0.05435753f, -0.05302101f, 0.05260378f, -0.03582945f,
2175         -3.42867890e-004f, 1.36076682e-003f, -0.04436073f, -0.04228432f,
2176         0.03281291f, -0.05480836f, -0.10197772f, -0.07206279f, -0.10741059f,
2177         -0.02366946f, 0.10278475f, -2.74783419e-003f, -0.03242477f,
2178         0.02308955f, 0.02835869f, 0.10348799f, 0.19580358f, 0.10252027f,
2179         0.08039929f, 0.05525554f, -0.13250865f, -0.14395352f, 3.13586881e-003f,
2180         -0.03387071f, 8.94669443e-003f, 0.05406157f, -4.97324532e-003f,
2181         -0.01189114f, 2.82919413e-004f, -0.03901557f, -0.04898705f,
2182         0.02164520f, -0.01382906f, -0.01850416f, 0.01869347f, -0.02450060f,
2183         0.02291678f, 0.08196463f, 0.03309153f, -0.10629974f, 0.02473924f,
2184         0.05344394f, -0.02404823f, -0.03243643f, -5.55244600e-003f,
2185         -0.08009996f, 0.02811539f, 0.04235742f, 0.01859004f, 0.04902123f,
2186         -0.01438252f, -0.01526853f, 0.02044195f, -0.05008660f, 0.04244113f,
2187         0.07611816f, 0.04950470f, -0.06020549f, -4.26026015e-003f, 0.13133512f,
2188         -0.01438738f, -0.01958807f, -0.04044152f, -0.12425045f,
2189         2.84353318e-003f, -0.05042776f, -0.09121484f, 7.34345755e-003f,
2190         0.09388847f, 0.11800314f, 4.72295098e-003f, 4.44378285e-003f,
2191         -0.07984917f, -0.03613737f, 0.04490915f, -0.02246483f, 0.04681071f,
2192         0.05240871f, 0.02157206f, -0.04603431f, -0.01197929f, -0.02748779f,
2193         0.13621049f, 0.08812155f, -0.07802048f, 4.86458559e-003f, -0.01598836f,
2194         0.01024450f, -0.03463517f, -0.02304239f, -0.08692665f, 0.06655128f,
2195         0.05785803f, -0.12640759f, 0.02307472f, 0.07337402f, 0.07525434f,
2196         0.04943763f, -0.02241034f, -0.09978238f, 0.14487994f, -0.06570521f,
2197         -0.07855482f, 0.02830222f, -5.29603509e-004f, -0.04669895f,
2198         -0.11822784f, -0.12246452f, -0.15365660f, -0.02969127f, 0.08078201f,
2199         0.13512598f, 0.11505685f, 0.04740673f, 0.01376022f, -0.05852978f,
2200         -0.01537809f, -0.05541119f, 0.02491065f, -0.02870786f, 0.02760978f,
2201         0.23836176f, 0.22347429f, 0.10306466f, -0.06919070f, -0.10132039f,
2202         -0.20198342f, -0.05040560f, 0.27163076f, 0.36987007f, 0.34540465f,
2203         0.29095781f, 0.05649706f, 0.04125737f, 0.07505883f, -0.02737836f,
2204         -8.43431335e-003f, 0.07368195f, 0.01653876f, -0.09402955f,
2205         -0.09574359f, 0.01474337f, -0.07128561f, -0.03460737f, 0.11438941f,
2206         0.13752601f, -0.06385452f, -0.06310338f, 8.19548313e-003f, 0.11622470f,
2207         5.05133113e-003f, -0.07602754f, 0.06695660f, 0.25723928f, 0.09037900f,
2208         0.28826267f, 0.13165380f, -0.05312614f, -0.02137198f, -0.03442232f,
2209         -0.06255679f, 0.03899667f, 0.18391028f, 0.26016650f, 0.03374462f,
2210         0.01860465f, 0.19077586f, 0.18160543f, 3.43634398e-003f, -0.03036782f,
2211         0.19683038f, 0.35378191f, 0.24968483f, -0.03222649f, 0.28972381f,
2212         0.43091634f, 0.30778357f, 0.02335266f, -0.09877399f, -6.85245218e-003f,
2213         0.08945240f, -0.08150686f, 0.02792493f, 0.24806842f, 0.17338486f,
2214         0.06231801f, -0.10432383f, -0.16653322f, -0.13197899f, -0.08531576f,
2215         -0.19271527f, -0.13536365f, 0.22240199f, 0.39219588f, 0.26597717f,
2216         -0.01231649f, 0.01016179f, 0.13379875f, 0.12018334f, -0.04852953f,
2217         -0.07915270f, 0.07036012f, 3.87723115e-003f, -0.06126805f,
2218         -0.15015170f, -0.11406515f, -0.08556531f, -0.07429333f, -0.16115491f,
2219         0.13214062f, 0.25691369f, 0.05697750f, 0.06861912f, -6.02903729e-003f,
2220         -7.94562511e-003f, 0.04799571f, 0.06695165f, -0.01926842f, 0.06206308f,
2221         0.13450983f, -0.06381495f, -2.98370165e-003f, -0.03482971f,
2222         7.53991678e-003f, 0.03895611f, 0.11464261f, 0.01669971f,
2223         8.27818643e-003f, -7.49160210e-003f, -0.11712562f, -0.10650621f,
2224         -0.10353880f, -0.04994106f, -7.65618810e-004f, 0.03023767f,
2225         -0.04759270f, -0.07302686f, -0.05825012f, -0.13156348f, -0.10639747f,
2226         -0.19393684f, -0.09973683f, -0.07918908f, 4.63177625e-004f,
2227         -6.61382044e-004f, 0.15853868f, 0.08561199f, -0.07660093f,
2228         -0.08015265f, -0.06164073f, 0.01882577f, -7.29908410e-004f,
2229         0.06840892f, 0.03843764f, 0.20274927f, 0.22028814f, -5.26101235e-003f,
2230         0.01452435f, -0.06331623f, 0.02865064f, 0.05673740f, 0.12171564f,
2231         0.03837196f, 0.03555467f, -0.02662914f, -0.10280123f, -0.06526285f,
2232         -0.11066351f, -0.08988424f, -0.10103678f, 8.10526591e-003f,
2233         5.95238712e-003f, 0.02617721f, -0.01705742f, -0.10897956f,
2234         -0.08004991f, -0.11271993f, -0.06185647f, -0.06103712f, 0.01597041f,
2235         -0.05923606f, 0.09410726f, 0.22858568f, 0.03263380f, 0.06772990f,
2236         -0.09003516f, 0.01017870f, 0.01931688f, 0.08628357f, -0.01430009f,
2237         0.10954945f, 0.16612452f, -0.02434544f, -0.03310068f, -0.04236627f,
2238         0.01212392f, -6.15046406e-003f, 0.06954194f, 0.03015283f, 0.01787957f,
2239         0.02781667f, -0.05561153f, -8.96244217e-003f, -0.04971489f,
2240         0.07510284f, 0.01775282f, 0.05889897f, -0.07981427f, 0.03647643f,
2241         -3.73833324e-003f, -0.08894575f, -0.06429435f, -0.08068276f,
2242         0.03567704f, -0.07131936f, -7.21910037e-003f, -0.09566668f,
2243         0.17886090f, 0.14911725f, 0.02070032f, -0.05017120f, -0.04992622f,
2244         0.01570143f, -0.09906903f, 0.06456193f, 0.15329507f, 0.18820767f,
2245         0.11689861f, -0.01178513f, -0.02225163f, -0.01905318f, 0.10271224f,
2246         -7.27029052e-003f, 0.11664233f, 0.14796902f, 0.07771893f, 0.02400013f,
2247         -0.05361797f, -0.01972888f, 0.01376177f, 0.06740040f, -0.06525395f,
2248         0.05726178f, -0.02404981f, -0.14018567f, -0.02074987f, -0.04621970f,
2249         -0.04688627f, -0.01842059f, 0.07722727f, -0.04852883f, 0.01529004f,
2250         -0.19639495f, 0.10817073f, 0.03795860f, -0.09435206f, -0.07984378f,
2251         -0.03383440f, 0.11081333f, 0.02237366f, 0.12703256f, 0.21613893f,
2252         0.02918790f, 4.66472283e-003f, -0.10274266f, -0.04854131f,
2253         -3.46305710e-003f, 0.08652268f, 0.02251546f, 0.09636052f, 0.17180754f,
2254         -0.09272388f, 4.59174305e-004f, -0.11723048f, -0.12210111f,
2255         -0.15547538f, 0.07218186f, -0.05297846f, 0.03779940f, 0.05150875f,
2256         -0.03802310f, 0.03870645f, -0.15250699f, -0.08696499f, -0.02021560f,
2257         0.04118926f, -0.15177974f, 0.01577647f, 0.10249301f, 7.50041893e-003f,
2258         0.01721806f, -0.06828983f, -0.02397596f, -0.06598977f, -0.04317593f,
2259         -0.08064980f, 6.66632550e-003f, 0.03333484f, 0.07093620f, 0.08231064f,
2260         -0.06577903f, -0.06698844f, -0.06984019f, -0.06508023f, -0.14145090f,
2261         -0.02393239f, 0.06485303f, 8.83263443e-003f, 0.09251080f, -0.07557579f,
2262         -0.05067699f, -0.09798748f, -0.06703258f, -0.14056294f, 0.03245994f,
2263         0.12554143f, 0.01761621f, 0.12980327f, -0.04081950f, -0.11906909f,
2264         -0.14813015f, -0.08376863f, -0.12200681f, 0.04988137f, 0.05424247f,
2265         -3.90952639e-003f, 0.03255733f, -0.12717837f, -0.07461493f,
2266         -0.05703964f, -0.01736189f, -0.08026433f, -0.05433894f, -0.01719359f,
2267         0.02886275f, 0.01772653f, -0.09163518f, 3.57789593e-003f, -0.10129993f,
2268         -0.02653764f, -0.08131415f, -0.03847986f, -7.62157550e-004f,
2269         0.06486648f, 0.19675669f, -0.04919156f, -0.07059129f, -0.04857785f,
2270         -0.01042383f, -0.08328653f, 0.03660302f, -0.03696846f, 0.04969259f,
2271         0.08241162f, -0.12514858f, -0.06122676f, -0.03750202f,
2272         6.52989605e-003f, -0.10247213f, 0.02568346f, 4.51781414e-003f,
2273         -0.03734229f, -0.01131264f, -0.05412074f, 8.89345480e-004f,
2274         -0.12388977f, -0.05959237f, -0.12418608f, -0.06151643f, -0.07310260f,
2275         0.02441575f, 0.07023528f, -0.07548289f, -7.57147965e-004f,
2276         -0.09061348f, -0.08112976f, -0.06920306f, 9.54394229e-003f,
2277         -0.01219902f, 1.21273217e-003f, -8.88989680e-003f, -0.08309301f,
2278         -0.04552661f, -0.10739882f, -0.05691034f, -0.13928030f, 0.09027749f,
2279         0.15123098f, 0.03175976f, 0.17763577f, 3.29913251e-004f, 0.05151888f,
2280         -0.09844074f, -0.09475287f, -0.08571247f, 0.16241577f, 0.19336018f,
2281         8.57454538e-003f, 0.11474732f, -0.01493934f, 0.03352379f, -0.08966240f,
2282         -0.02322310f, 0.02663568f, 0.05448750f, -0.03536883f, -0.07210463f,
2283         -0.06807277f, -0.03121621f, -0.05932408f, -0.17282860f, -0.15873498f,
2284         -0.04956378f, 0.01603377f, -0.12385946f, 0.13878587f, 0.21468069f,
2285         0.13510075f, 0.20992437f, 0.08845878f, 0.08104013f, 0.03754176f,
2286         0.12173114f, 0.11103114f, 0.10643122f, 0.13941477f, 0.11640384f,
2287         0.14786847f, 0.01218238f, 0.01160753f, 0.03547940f, 0.08794311f,
2288         -0.01695384f, -0.07692261f, -0.08236158f, 6.79194089e-003f,
2289         -0.02458403f, 0.13022894f, 0.10953187f, 0.09857773f, 0.04735930f,
2290         -0.04353498f, -0.15173385f, -0.17904443f, -0.10450364f, -0.13418166f,
2291         -0.06633098f, -0.03170381f, -0.06839000f, -0.11350126f, -0.06983913f,
2292         0.19083543f, 0.17604128f, 0.07730632f, 0.10022651f, 0.36428109f,
2293         0.28291923f, 0.12688625f, 0.15942036f, 0.14064661f, -0.11201853f,
2294         -0.13969108f, -0.09088077f, -0.14107047f, 0.05117374f,
2295         -2.63348082e-003f, -0.10794610f, -0.09715455f, -0.05284977f,
2296         0.01565668f, 0.05031200f, 0.07021113f, -0.02963028f, 0.01766960f,
2297         0.08333644f, -0.03211382f, 4.90096770e-003f, 0.05186674f, -0.05045737f,
2298         -0.09624767f, -0.02525997f, 0.06916669f, 0.01213916f, 0.05333899f,
2299         -0.03443280f, -0.10055527f, -0.06291115f, 5.42851724e-003f,
2300         -6.30360236e-003f, 0.02270257f, -0.01769792f, 0.03273688f, 0.07746078f,
2301         7.77099328e-003f, 0.05041346f, 0.01648103f, -0.02321534f, -0.09930186f,
2302         -0.02293853f, 0.02034990f, -0.08324204f, 0.08510064f, -0.03732836f,
2303         -0.06465405f, -0.06086946f, 0.13680504f, -0.11469388f, -0.03896406f,
2304         -0.07142810f, 2.67581246e-003f, -0.03639632f, -0.09849060f,
2305         -0.11014334f, 0.17489147f, 0.17610909f, -0.16091567f, -0.07248894f,
2306         0.01567141f, 0.23742996f, 0.07552249f, -0.06270349f, -0.07303379f,
2307         0.25442186f, 0.16903116f, -0.08168741f, -0.05913896f, -0.03954096f,
2308         6.81776879e-003f, -0.05615319f, -0.07303037f, -0.12176382f,
2309         0.12385108f, 0.22084464f, -0.05543206f, -0.03310431f, 0.05731593f,
2310         0.19481890f, 0.04016430f, -0.06480758f, -0.12353460f, 0.18733442f,
2311         -0.09631214f, -0.11192076f, 0.12404587f, 0.15671748f, 0.19256128f,
2312         0.10895617f, 0.03391477f, -0.13032004f, -0.05626907f, -0.09025607f,
2313         0.23485197f, 0.27812332f, 0.26725492f, 0.07255980f, 0.16565137f,
2314         0.22388470f, 0.07441066f, -0.21003133f, -0.08075339f, -0.15031935f,
2315         0.07023834f, 0.10872041f, 0.18156518f, 0.20037253f, 0.13571967f,
2316         -0.11915682f, -0.11131983f, -0.18878011f, 0.06074620f, 0.20578890f,
2317         0.12413109f, 0.03930207f, 0.29176015f, 0.29502738f, 0.27856228f,
2318         -0.01803601f, 0.16646385f, 0.19268319f, 0.01900682f, 0.06026287f,
2319         2.35868432e-003f, 0.01558199f, 0.02707230f, 0.11383014f, 0.12103992f,
2320         0.03907350f, 0.04637353f, 0.09020995f, 0.11919726f, -3.63007211e-003f,
2321         0.02220155f, 0.10336831f, 0.17351882f, 0.12259731f, 0.18983354f,
2322         0.15736865f, 0.01160725f, -0.01690723f, -9.69582412e-004f, 0.07213813f,
2323         0.01161613f, 0.17864859f, 0.24486147f, 0.18208991f, 0.20177495f,
2324         0.05972528f, -8.93934630e-003f, -0.02316955f, 0.14436610f, 0.14114498f,
2325         0.05520950f, 0.06353590f, -0.19124921f, 0.10174713f, 0.29414919f,
2326         0.26448128f, 0.09344960f, 0.15284036f, 0.19797507f, 0.11369792f,
2327         -0.12722753f, -0.21396367f, -0.02008235f, -0.06566695f, -0.01662150f,
2328         -0.03937003f, 0.04778343f, 0.05017274f, -0.02299062f, -0.20208496f,
2329         -0.06395898f, 0.13721776f, 0.22544557f, 0.14888357f, 0.08687132f,
2330         0.27088094f, 0.32206613f, 0.09782200f, -0.18523243f, -0.17232181f,
2331         -0.01041531f, 0.04008654f, 0.04199702f, -0.08081299f, -0.03755421f,
2332         -0.04809646f, -0.05222081f, -0.21709201f, -0.06622940f, 0.02945281f,
2333         -0.04600435f, -0.05256077f, -0.08432942f, 0.02848100f, 0.03490564f,
2334         8.28621630e-003f, -0.11051246f, -0.11210597f, -0.01998289f,
2335         -0.05369405f, -0.08869293f, -0.18799506f, -0.05436598f, -0.05011634f,
2336         -0.05419716f, -0.06151857f, -0.10827805f, 0.04346735f, 0.04016083f,
2337         0.01520820f, -0.12173316f, -0.04880285f, -0.01101406f, 0.03250847f,
2338         -0.06009551f, -0.03082932f, -0.02295134f, -0.06856834f, -0.08775249f,
2339         -0.23793389f, -0.09174541f, -0.05538322f, -0.04321031f, -0.11874759f,
2340         -0.04221844f, -0.06070468f, 0.01194489f, 0.02608565f, -0.03892140f,
2341         -0.01643151f, -0.02602034f, -0.01305472f, 0.03920100f, -0.06514261f,
2342         0.01126918f, -6.27710763e-003f, -0.02720047f, -0.11133634f,
2343         0.03300330f, 0.02398472f, 0.04079665f, -0.10564448f, 0.05966159f,
2344         0.01195221f, -0.03179441f, -0.01692590f, -0.06177841f, 0.01841576f,
2345         -5.51078189e-003f, -0.06821765f, -0.03191888f, -0.09545476f,
2346         0.03030550f, -0.04896152f, -0.02914624f, -0.13283344f, -0.04783419f,
2347         6.07836898e-003f, -0.01449538f, -0.13358212f, -0.09687774f,
2348         -0.02813793f, 0.01213498f, 0.06650011f, -0.02039067f, 0.13356198f,
2349         0.05986415f, -9.12760664e-003f, -0.18780160f, -0.11992817f,
2350         -0.06342237f, 0.01229534f, 0.07143231f, 0.10713009f, 0.11085765f,
2351         0.06569190f, -0.02956399f, -0.16288325f, -0.13993549f, -0.01292515f,
2352         0.03833013f, 0.09130384f, -0.05086257f, 0.05617329f, -0.03896667f,
2353         -0.06282311f, -0.11490010f, -0.14264110f, -0.04530499f, 0.01598189f,
2354         0.09167797f, 0.08663294f, 0.04885277f, -0.05741219f, -0.07565769f,
2355         -0.17136464f, -0.02619422f, -0.02477579f, 0.02679587f, 0.11621952f,
2356         0.08788391f, 0.15520640f, 0.04709549f, 0.04504483f, -0.10214074f,
2357         -0.12293372f, -0.04820546f, -0.05484834f, 0.05473754f, 0.07346445f,
2358         0.05577277f, -0.08209965f, 0.03462975f, -0.20962234f, -0.09324598f,
2359         3.79481679e-003f, 0.03617633f, 0.16742408f, 0.07058107f, 0.10204960f,
2360         -0.06795346f, 3.22807301e-003f, -0.12589309f, -0.17496960f,
2361         0.02078314f, -0.07694324f, 0.12184640f, 0.08997164f, 0.04793497f,
2362         -0.11383379f, -0.08046359f, -0.25716835f, -0.08080962f,
2363         6.80711539e-003f, -0.02930280f, -3.04938294e-003f, -0.11106286f,
2364         -0.04628860f, -0.07821649f, 7.70127494e-003f, -0.10247706f,
2365         1.21042714e-003f, 0.20573859f, -0.03241005f, 8.42972286e-003f,
2366         0.01946464f, -0.01197973f, -0.14579976f, 0.04233614f,
2367         -4.14096704e-003f, -0.06866436f, -0.02431862f, -0.13529138f,
2368         1.25891645e-003f, -0.11425111f, -0.04303651f, -0.01694815f,
2369         0.05720210f, -0.16040207f, 0.02772896f, 0.05498345f, -0.15010567f,
2370         0.01450866f, 0.02350303f, -0.04301004f, -0.04951802f, 0.21702233f,
2371         -0.03159155f, -0.01963303f, 0.18232647f, -0.03263875f,
2372         -2.88476888e-003f, 0.01587562f, -1.94303901e-003f, -0.07789494f,
2373         0.04674156f, -6.25576358e-003f, 0.08925962f, 0.21353747f, 0.01254677f,
2374         -0.06999976f, -0.05931328f, -0.01884327f, -0.04306272f, 0.11794136f,
2375         0.03842728f, -0.03907030f, 0.05636114f, -0.09766009f, -0.02104000f,
2376         8.72711372e-003f, -0.02736877f, -0.05112274f, 0.16996814f, 0.02955785f,
2377         0.02094014f, 0.08414304f, -0.03335762f, -0.03617457f, -0.05808248f,
2378         -0.08872101f, 0.02927705f, 0.27077839f, 0.06075108f, 0.07478261f,
2379         0.15282831f, -0.03908454f, -0.05101782f, -9.51998029e-003f,
2380         -0.03272416f, -0.08735625f, 0.07633440f, -0.07185312f, 0.13841286f,
2381         0.07812646f, -0.12901451f, -0.05488589f, -0.05644578f, -0.03290703f,
2382         -0.11184757f, 0.03751570f, -0.05978153f, -0.09155276f, 0.05657315f,
2383         -0.04328186f, -0.03047933f, -0.01413135f, -0.10181040f, -0.01384013f,
2384         0.20132534f, -0.01536873f, -0.07641169f, 0.05906778f, -0.07833145f,
2385         -0.01523801f, -0.07502609f, -0.09461885f, -0.15013233f, 0.16050665f,
2386         0.09021381f, 0.08473236f, 0.03386267f, -0.09147339f, -0.09170618f,
2387         -0.08498498f, -0.05119187f, -0.10431040f, 0.01041618f, -0.03064913f,
2388         0.09340212f, 0.06448522f, -0.03881054f, -0.04985436f, -0.14794017f,
2389         -0.05200112f, -0.02144495f, 0.04000821f, 0.12420804f, -0.01851651f,
2390         -0.04116732f, -0.11951703f, -0.04879033f, -0.08722515f, -0.08454733f,
2391         -0.10549165f, 0.11251976f, 0.10766345f, 0.19201984f, 0.06128913f,
2392         -0.02734615f, -0.08834923f, -0.16999826f, -0.03548348f,
2393         -5.36092324e-003f, 0.08297954f, 0.07226378f, 0.04194529f, 0.04668673f,
2394         8.73902347e-003f, 0.06980139f, 0.05652480f, 0.05879445f, 0.02477076f,
2395         0.02451423f, 0.12433673f, 0.05600227f, 0.06886370f, 0.03863076f,
2396         0.07459056f, 0.02264139f, 0.01495469f, 0.06344220f, 0.06945208f,
2397         0.02931899f, 0.11719371f, 0.04527427f, 0.03248192f, 2.08271481e-003f,
2398         0.02044626f, 0.11403449f, 0.04303892f, 0.06444661f, 0.04959024f,
2399         0.08174094f, 0.09240247f, 0.04894639f, 0.02252937f, -0.01652530f,
2400         0.07587013f, 0.06064249f, 0.13954395f, 0.02772832f, 0.07093039f,
2401         0.08501238f, 0.01701301f, 0.09055722f, 0.33421436f, 0.20163782f,
2402         0.09821030f, 0.07951369f, 0.08695120f, -0.12757730f, -0.13865978f,
2403         -0.06610068f, -0.10985506f, 0.03406816f, -0.01116336f, -0.07281768f,
2404         -0.13525715f, -0.12844718f, 0.08956250f, 0.09171610f, 0.10092317f,
2405         0.23385370f, 0.34489515f, 0.09901748f, 0.02002922f, 0.12335990f,
2406         0.07606190f, -0.14899330f, -0.15634622f, -0.06494618f, -0.01760547f,
2407         0.03404277f, -0.13208845f, -0.12101169f, -0.18294574f, -0.16560709f,
2408         0.02183887f, -0.02752613f, 0.01813638f, 0.02000757f, 0.01319924f,
2409         0.08030242f, 0.01220535f, 2.98233377e-003f, -0.01307070f, 0.05970297f,
2410         -0.05345284f, -0.03381982f, -9.87543724e-003f, -0.06869387f,
2411         0.03956730f, -0.03108176f, -0.05732809f, 0.02172386f, 0.04159765f,
2412         2.62783933e-003f, 0.04813229f, 0.09358983f, -8.18389002e-003f,
2413         0.01724574f, -0.02547474f, -0.04967288f, -0.02390376f, 0.06640504f,
2414         -0.06306566f, 0.01137518f, 0.05589378f, -0.08237787f, 0.02455001f,
2415         -0.03059422f, -0.08953978f, 0.06851497f, 0.07190268f, -0.07610799f,
2416         7.87237938e-003f, -7.85830803e-003f, 0.06006952f, -0.01126728f,
2417         -2.85743061e-003f, -0.04772895f, 0.01884944f, 0.15005857f,
2418         -0.06268821f, -0.01989072f, 0.01138399f, 0.08760451f, 0.03879007f,
2419         -9.66926850e-003f, -0.08012961f, 0.06414555f, -0.01362950f,
2420         -0.09135523f, 0.01755159f, 0.04459474f, 0.09650917f, 0.05219948f,
2421         -2.19440833e-003f, -0.07037939f, -0.01599054f, 0.13103317f,
2422         -0.02492603f, -0.01032540f, -0.02903307f, 0.04489160f, 0.05148086f,
2423         0.01858173f, -0.02919228f, 0.08299296f, -0.04590359f, -0.15745632f,
2424         -0.09068198f, -0.02972453f, 0.12985018f, 0.22320485f, 0.24261914f,
2425         0.03642650f, -0.05506422f, 2.67413049e-003f, -0.03834032f, 0.06449424f,
2426         0.03834866f, 0.03816991f, 0.25039271f, 0.34212017f, 0.32433882f,
2427         0.18824573f, -0.08599839f, -0.17599408f, -0.15317015f, -0.09913155f,
2428         -0.02856072f, -0.05304699f, -1.06437842e-003f, -0.06641813f,
2429         -0.07509298f, 0.01463361f, -0.07551918f, -0.04510373f,
2430         -8.44620075e-003f, 0.01772176f, 0.04068235f, 0.20295307f, 0.15719447f,
2431         0.05712103f, 0.26296997f, 0.14657754f, 0.01547317f, -0.05052776f,
2432         -0.03881342f, -0.01437883f, -0.04930177f, 0.11719568f, 0.24098417f,
2433         0.26468599f, 0.31698579f, 0.10103608f, -0.01096375f, -0.01367013f,
2434         0.17104232f, 0.20065314f, 2.67622480e-003f, -0.01190034f, 0.18301608f,
2435         0.09459770f, -0.06357619f, -0.06473801f, 0.01377906f, -0.10032775f,
2436         -0.06388740f, 3.80393048e-003f, 0.06206078f, 0.10349120f, 0.26804337f,
2437         8.17918684e-003f, -0.02314351f, 9.34422202e-003f, 0.09198381f,
2438         0.03681326f, -8.77339672e-003f, -0.09662418f, -0.02715708f,
2439         0.13503517f, 0.08962728f, -6.57071499e-003f, -0.03201199f, 0.28510824f,
2440         0.32095715f, 0.18512695f, -0.14230858f, -0.14048551f, -0.07181299f,
2441         -0.08575408f, -0.08661680f, -0.17416079f, 7.54326640e-004f,
2442         0.05601677f, 0.13585392f, -0.04960437f, -0.07708392f, 0.10676333f,
2443         -0.04407546f, -0.07209078f, 0.03663663f, 0.28949317f, 0.41127121f,
2444         0.27431169f, -0.06900328f, -0.21474190f, -0.15578632f, -0.19555484f,
2445         -0.15209621f, -0.11269179f, 0.07416003f, 0.18991330f, 0.26858172f,
2446         0.01952259f, 0.01017922f, 0.02159843f, -4.95165400e-003f, -0.04368168f,
2447         -0.12721671f, -0.06673957f, -0.11275250f, 0.04413409f, 0.05578312f,
2448         0.03896771f, 0.03566417f, -0.05871816f, -0.07388090f, -0.17965563f,
2449         -0.08570268f, -0.15273231f, -0.06022318f, -0.06999847f,
2450         -6.81510568e-003f, 0.06294262f, -6.54901436e-004f, -0.01128654f,
2451         -0.02289657f, 0.04849290f, 0.04140804f, 0.23681939f, 0.14545733f,
2452         0.01989965f, 0.12032662f, 3.87463090e-003f, -6.02597650e-003f,
2453         -0.05919775f, -0.03067224f, -0.07787777f, 0.10834727f, 0.02153730f,
2454         0.02765649f, 0.03975543f, -0.12182906f, -0.04900113f, -0.09940100f,
2455         -0.06453611f, -0.13757215f, -0.03721382f, 0.02827376f, -0.04351249f,
2456         0.01907038f, -0.10284120f, -0.05671160f, -0.10760647f, -0.09624009f,
2457         -0.09565596f, -0.01303654f, 0.03080539f, 0.01416511f, 0.05846142f,
2458         -5.42971538e-003f, 0.06221476f, -0.03320325f, -0.06791797f,
2459         -0.05791342f, 0.12851369f, 0.14990346f, 0.03634374f, 0.14262885f,
2460         0.04330391f, 0.05032569f, -0.05631914f, 0.01606137f, 0.04387223f,
2461         0.22344995f, 0.15722635f, -0.04693628f, 0.03006579f, -2.52882647e-003f,
2462         0.05717621f, -0.07529724f, -0.02848588f, -0.06868757f,
2463         -4.51729307e-003f, 0.06466042f, -0.05935378f, -0.04704857f,
2464         -0.07363959f, 0.04843248f, -0.13421375f, -0.09789340f, -0.10255270f,
2465         0.03509852f, 0.04751543f, -0.03822323f, 0.09740467f, 0.04762916f,
2466         0.03940146f, -0.08283259f, 0.09552965f, 0.05038739f, 0.21258622f,
2467         0.09646992f, 0.03241193f, 0.05167701f, 0.04614570f, 0.04330090f,
2468         -0.02671840f, -0.06259909f, -0.02301898f, 0.18829170f, 0.10522786f,
2469         0.04313190f, 0.01670948f, -0.08421925f, 0.05911417f, -0.10582602f,
2470         -0.04855484f, -0.08373898f, 0.07775915f, 0.03723533f, -0.12047344f,
2471         4.86345543e-003f, -0.10520902f, 0.06571782f, -0.07528137f,
2472         -0.03245651f, -0.09869066f, -0.02917477f, -0.18293270f, 0.14810945f,
2473         9.24033765e-003f, -0.04354914f, 0.02266885f, -0.11872729f,
2474         -0.04016589f, 0.02830229f, 0.22539048f, 0.20565644f, 0.16701797f,
2475         0.09019924f, 0.01300652f, 0.09760600f, -0.03675831f, -0.01935448f,
2476         -0.06894835f, 0.08077277f, 0.19047537f, 0.11312226f, 0.04106043f,
2477         -0.11187182f, 0.04312806f, -0.18548580f, -0.11287174f, -0.08794551f,
2478         0.02078281f, -0.15295486f, 0.11806386f, -0.01103218f, -0.15971117f,
2479         0.02153538f, -0.05232147f, -0.10835317f, -0.13910367f, 0.05920752f,
2480         -0.10122602f, 0.20174250f, 0.09105796f, -0.01881348f, 0.09559010f,
2481         -0.03725745f, -0.09442931f, -0.09763174f, 0.05854454f, 0.08287182f,
2482         0.12919849f, 0.08594352f, -2.49806582e-003f, 0.02398440f,
2483         5.67950122e-003f, -0.06296340f, -0.12993270f, 0.03855852f, 0.05186560f,
2484         0.10839908f, -0.03380463f, -0.12654832f, -0.05399339f, -0.07456800f,
2485         -0.04736232f, -0.10164231f, 0.07496139f, 0.08125214f, 0.07656177f,
2486         -0.04999603f, -0.12823077f, -0.07692395f, -0.11317524f, -0.09118655f,
2487         -0.05695669f, 0.10477209f, 0.07468581f, 0.01630048f, -8.00961629e-003f,
2488         -0.06582128f, -0.04019095f, -0.04682907f, -0.01907842f, -0.10997720f,
2489         0.04911406f, 0.02931030f, 0.04197735f, -0.05773980f, -0.09670641f,
2490         -0.03594951f, -0.03402121f, -0.07149299f, -0.10566200f, 0.10601286f,
2491         0.06340689f, -0.01518632f, -5.96402306e-003f, -0.07628012f,
2492         -3.52779147e-003f, -0.02683854f, -0.10265494f, -0.02680815f,
2493         0.16338381f, 0.03103515f, 0.02296976f, 0.01624348f, -0.10831620f,
2494         -0.02314233f, -0.04789969f, -0.05530700f, -0.06461314f, 0.10494506f,
2495         0.04642856f, -0.07592955f, -0.06197905f, -0.09042154f, -0.01445521f,
2496         -0.04297818f, -0.11262015f, -0.11430512f, 0.03174541f, -0.03677487f,
2497         -0.02963996f, -0.06610169f, -0.13292049f, -0.07059067f, -0.08444111f,
2498         -0.02640536f, -0.07136250f, 0.04559967f, 0.01459980f, 0.17989251f,
2499         0.04435328f, -0.12464730f, -0.02871115f, -0.10752209f, -0.03393742f,
2500         -0.03791408f, 0.02548251f, 0.01956050f, 0.19245651f, 0.13963254f,
2501         -0.05904696f, -0.07424626f, -0.10411884f, 1.54176133e-003f,
2502         0.01797429f, 0.13025844f, 0.04547642f, -0.05710349f, -0.10697161f,
2503         -0.13489437f, -0.06515755f, -0.06406886f, -4.08572936e-003f,
2504         -0.01336483f, 0.04368737f, -0.11259720f, -0.05701635f, -0.06469971f,
2505         -0.08346602f, -0.04166770f, -0.05795543f, -0.08247511f, -0.05742628f,
2506         0.08452254f, -0.03350224f, 0.13980860f, 0.13252275f, 0.07589617f,
2507         0.07539988f, 0.12155797f, 0.19087289f, 0.15050751f, 0.21250245f,
2508         0.14206800f, 0.01298489f, 0.07450245f, 0.06559097f, 0.01700557f,
2509         0.04512971f, 0.16950700f, 0.10261577f, 0.16389982f, 0.05505059f,
2510         -0.03453077f, 0.08622462f, 0.07935954f, 0.03976260f, 0.02036091f,
2511         3.95744899e-003f, 0.03267065f, 0.15235919f, 0.01297494f, -0.08109194f,
2512         0.01407558f, 4.40693414e-003f, -0.15157418f, -0.11390478f,
2513         -0.07487597f, -7.81322457e-003f, -0.02749545f, -0.10181408f,
2514         0.13755716f, 0.14007211f, 0.13482562f, 0.27517235f, 0.34251109f,
2515         0.07639657f, 0.07268607f, 0.19823882f, 0.16135791f, -0.04186463f,
2516         -0.12784107f, -0.09846287f, 0.03169041f, 0.10974082f, -0.15051922f,
2517         -0.08916726f, -0.07138767f, -0.04153349f, 6.25418453e-003f,
2518         0.01266654f, 0.10533249f, 0.12749144f, 0.15148053f, 0.01498513f,
2519         0.06305949f, -0.01247123f, -0.08778401f, -0.08551880f, -0.11955146f,
2520         -0.08493572f, -0.02901620f, -0.02394859f, -0.13427313f, -0.11053200f,
2521         -0.14413260f, -0.15203285f, 0.03972760f, -3.72127310e-004f,
2522         -0.04200919f, 0.06105104f, 0.01904975f, -0.01106191f,
2523         -7.27445772e-003f, -0.01520341f, 1.10228511e-003f, -0.04949187f,
2524         -0.08013099f, 5.72071038e-003f, 0.08415454f, -0.06523152f, 0.03664081f,
2525         -0.02673042f, -0.12066154f, -0.03702074f, 0.06006580f, 0.01628682f,
2526         -6.17772620e-003f, 0.08192339f, -3.41629819e-003f, 0.02870512f,
2527         0.05807141f, 0.04959986f, 0.04618251f, -0.04901629f, -0.10579574f,
2528         0.02274442f, 0.12070961f, 2.23597488e-003f, 0.09831765f, -0.03019848f,
2529         -0.11181970f, -0.04961075f, 0.02498928f, -0.03714991f, -0.01619653f,
2530         0.02643486f, -7.62964319e-003f, -0.02882290f, -0.06242594f,
2531         -0.08439861f, 0.07220893f, 0.07263952f, 0.01561574f, 0.03091968f,
2532         0.01708712f, -0.03797151f, -3.18561122e-003f, 0.01624021f,
2533         -0.02828573f, 0.11284444f, -1.32280716e-003f, -0.07784860f,
2534         -0.07209100f, 0.03372242f, 0.12154529f, 0.02278104f, -0.05275500f,
2535         -0.01918484f, 0.12989293f, 0.05424401f, 0.02333086f, 0.04029022f,
2536         0.12392918f, 0.09495489f, 0.09190340f, 0.07935889f, 8.76816828e-003f,
2537         0.17148446f, -8.51302687e-003f, -0.08011249f, -0.06796283f,
2538         0.04884845f, 0.01112272f, -0.07835306f, -1.14811445e-003f,
2539         -0.03440760f, 0.02845243f, 0.07695542f, -0.07069533f, -0.01151784f,
2540         -8.53884313e-003f, -0.01662786f, -0.04163864f, 0.05400505f,
2541         0.02859163f, 0.02921852f, 0.05003135f, -6.85718050e-003f, -0.01632611f,
2542         0.07780217f, 0.04042810f, -0.01216440f, 3.60914599e-003f, -0.06322435f,
2543         0.09516726f, 0.12877031f, -9.69162490e-003f, 0.01031179f, 0.05180895f,
2544         -9.34659224e-003f, -0.01644533f, -0.04849347f, -0.04343236f,
2545         0.10514783f, 0.08046635f, -0.04615205f, -0.03975486f, -0.01485525f,
2546         0.13096830f, -0.01517950f, -0.06571898f, -0.04016372f, 0.01849786f,
2547         0.02439670f, 0.08067258f, 1.74824719e-003f, 0.07053747f, 0.08819518f,
2548         -5.08352555e-003f, -0.06550863f, -0.08266170f, -0.07780605f,
2549         0.01453450f, -0.08756890f, 0.01096501f, -8.71319138e-003f, 0.10110464f,
2550         0.02420769f, -0.06708383f, 0.02007811f, 5.93133038e-003f, 0.05398923f,
2551         0.07538138f, 0.02049227f, 0.02242589f, 0.04011070f, -1.44875818e-003f,
2552         -4.19115182e-003f, 0.06367654f, 0.02506934f, 0.02434536f, 0.05879405f,
2553         -8.22952855e-003f, -0.01242441f, 0.04224926f, -0.01754923f,
2554         0.05958161f, 0.03818886f, -0.01830363f, -0.04308917f, -0.04422197f,
2555         -0.02432721f, 0.02264866f, 2.03751423e-003f, 0.01197031f, 0.04439203f,
2556         0.12169247f, 0.03602713f, -0.02599251f, -1.98226492e-003f, 0.02046336f,
2557         -0.02639058f, -1.91242550e-003f, -0.09334669f, -0.03595153f,
2558         -9.88179818e-003f, -0.06848445f, -0.04666303f, -0.09955736f,
2559         -0.04206430f, 0.02609075f, 9.09005292e-003f, -0.07138551f,
2560         -4.22313227e-004f, 0.01766645f, 0.02756404f, 0.01308276f, 0.04052891f,
2561         0.02387515f, 0.05337298f, 0.02500631f, -0.04970853f, -0.12467445f,
2562         0.17604403f, 0.12256411f, -0.07512254f, 8.70451052e-003f, -0.05697548f,
2563         -0.03626474f, -8.76623299e-003f, -0.01210897f, -0.09451522f,
2564         0.07490732f, -0.02008001f, -0.02681278f, -0.06463405f, -0.01517507f,
2565         7.33757764e-003f, 6.07147906e-003f, -0.09316964f, -0.04575328f,
2566         0.13261597f, 0.15424870f, -0.01655918f, -0.02772390f, -0.05243644f,
2567         -0.02356456f, -0.02351753f, -0.10211615f, -0.12873036f, 0.14549787f,
2568         0.12519856f, 4.38762689e-003f, 0.02795992f, 0.05170322f, 0.09223596f,
2569         0.05890015f, 0.02376701f, -0.02777346f, 0.09506908f, 0.02328936f,
2570         -0.02319928f, -0.03218696f, -0.01527841f, -0.01016694f, -0.02674719f,
2571         0.05137179f, 0.01980666f, 0.06544447f, -0.01746171f, 0.01026380f,
2572         0.01561806f, 7.97004555e-004f, 0.07601810f, 0.01907250f, -0.03083035f,
2573         -0.05987392f, 0.09242783f, 0.14555025f, 0.01035827f, 0.03092401f,
2574         -0.09562709f, -0.03802354f, 0.02531144f, 0.03079449f, -0.07100715f,
2575         0.03330721f, -2.69116857e-003f, 0.03167490f, 0.05744999f, 0.03259895f,
2576         1.91266940e-003f, 0.03194578f, 0.07389776f, 0.02198060f, 0.07633314f,
2577         0.03293105f, -0.09103648f, 0.04718142f, 0.06102672f, -0.01003063f,
2578         5.85481385e-003f, -0.01522574f, 0.02323526f, 0.10584345f,
2579         4.35879454e-003f, 0.06107873f, 0.05868603f, -0.03115531f, 0.01214679f,
2580         0.08567052f, 3.93926632e-003f, -0.02521488f, -1.88425183e-003f,
2581         0.02038053f, -6.26854831e-004f, 0.04897438f, -0.04280585f,
2582         -0.04819689f, -0.04812867f, -0.01451186f, 0.05101469f,
2583         -9.01125465e-003f, -0.03333859f, 0.03917955f, 0.04196448f, 0.04292135f,
2584         0.02809529f, 0.02999715f, 0.04081348f, 9.10039060e-003f, 0.09703232f,
2585         0.10379741f, 0.02348725f, -4.72756615e-003f, 0.01027325f, 0.10402658f,
2586         0.12071823f, 0.09817299f, -0.02612033f, 0.03638414f, 0.05896405f,
2587         0.04865025f, 0.04793910f, -0.03882321f, -0.02962117f, -0.01222268f,
2588         0.04071597f, 0.01922777f, -0.02287866f, 0.03328381f, 0.01859092f,
2589         0.09024994f, 0.03804455f, -0.01424510f, 0.01953739f, 0.02509617f,
2590         -0.03390914f, -0.05663941f, -0.01641979f, 0.05848591f, 0.04639670f,
2591         0.02092116f, 0.12911791f, 0.19918139f, 0.07739855f, -7.25806039e-003f,
2592         0.04074838f, 0.03183993f, 1.39251316e-003f, -0.01428625f, 0.01865480f,
2593         0.08529541f, 0.13547510f, 0.11189661f, 0.03998901f, 0.09575938f,
2594         -0.02631102f, -0.03458253f, -0.04749985f, -0.06070716f,
2595         4.71884012e-003f, 0.06445789f, -0.02450038f, -0.05483776f,
2596         -0.04657237f, -0.02030717f, -0.03480766f, -0.09397731f, -0.06399718f,
2597         -0.01804585f, 5.62348310e-003f, -6.64811488e-003f, -0.06517869f,
2598         6.96210237e-003f, -0.01860148f, -0.04245830f, -0.05850367f,
2599         -3.24417115e-003f, 0.07700698f, 0.11290991f, 0.09923030f, -0.02970599f,
2600         0.05592411f, 0.04813979f, -0.09811195f, -0.09357996f, -0.03276114f,
2601         0.05218338f, 0.04141375f, 3.92977800e-003f, -0.05047480f, 0.15960084f,
2602         0.04612800f, -0.03114098f, -0.04650044f, -0.03249795f, -0.02425641f,
2603         -0.04311355f, 0.04307659f, -0.09401883f, -0.04742785f, -0.01254499f,
2604         -0.06598741f, 3.41369561e-003f, -0.05620445f, -7.28127593e-003f,
2605         -0.05998361f, -0.03274450f, -0.07376868f, 3.19015374e-003f,
2606         -0.07733069f, 0.05815864f, -0.02471071f, 0.03850617f, 0.13838784f,
2607         0.15399861f, 0.01731321f, -0.01477586f, 0.10393341f, 0.05159833f,
2608         -0.01945555f, -0.03427503f, -0.04867341f, 0.09237480f, 0.10732719f,
2609         0.06071450f, -0.01355071f, 0.01844356f, -0.03480803f, -0.03796671f,
2610         2.15628621e-004f, -0.05440186f, 0.01889855f, -0.01443413f,
2611         -0.02607902f, -0.02938001f, 0.02720689f, -0.06228397f, -0.02970936f,
2612         -0.03426210f, -0.10280876f, -0.06739304f, -0.05227850f, 0.03360292f,
2613         -0.11278441f, -0.06966180f, -0.13937433f, 9.10932291e-003f,
2614         2.52020749e-004f, -4.07359656e-003f, 0.12310639f, 0.09343060f,
2615         0.07302511f, 0.03222093f, 0.07532879f, 0.03792387f, -0.04985180f,
2616         0.01804602f, 0.02694195f, 0.13481498f, 0.04601225f, 0.04106982f,
2617         0.08511057f, 0.12314661f, 0.01320830f, 0.05044121f, -5.52943908e-003f,
2618         -0.08992624f, -0.02249301f, -0.08181777f, 0.06165213f, -0.03256603f,
2619         -0.01068920f, -0.01323473f, -0.11970232f, -0.04616347f, -0.12088681f,
2620         -0.06762606f, -0.08676834f, -0.06434575f, 0.01772529f, 0.03469615f,
2621         -0.10926618f, 0.03013873f, 0.14030397f, 0.16130108f, 0.17985588f,
2622         0.11281928f, 0.10530639f, 0.08905948f, 0.07733764f, 0.06695238f,
2623         0.02142088f, 0.06438877f, 0.09794453f, 0.05745072f, 0.02788557f,
2624         0.02632830f, 0.07985807f, 4.24902979e-003f, 8.47890321e-003f,
2625         -0.02679466f, -5.28812688e-003f, -0.02162580f, -0.07490715f,
2626         -0.08251337f, -0.02056576f, -0.01026194f, -1.15492963e-003f,
2627         -5.75720915e-004f, -0.07210591f, -0.07320981f, -0.04883312f,
2628         -0.10897151f, -0.07477258f, -0.08867134f, -0.09222437f, -0.10924666f,
2629         -0.10430276f, 0.07953499f, 0.02767959f, 0.11393359f, 0.18779543f,
2630         0.03313421f, 0.02143700f, 0.05852016f, -2.12067598e-003f,
2631         -3.76984011e-003f, 0.02774167f, -0.03124610f, 0.01465141f, 0.01616004f,
2632         -0.01391913f, -0.04404102f, -0.05444227f, -0.14684731f, -0.15016587f,
2633         0.04509468f, 1.29563001e-003f, 0.01398350f, 0.05610404f, -0.04868806f,
2634         -0.04776716f, -8.16873740e-003f, -2.30126386e-003f, -0.02286313f,
2635         0.11983398f, -0.04703261f, -0.08814441f, -0.07585249f, -0.10799607f,
2636         -0.03232087f, 0.01509786f, -0.04843464f, -0.03967846f, 0.09589416f,
2637         0.01352560f, -0.01458119f, 0.01050829f, -0.03038946f, 0.01608388f,
2638         1.11975556e-003f, -0.01250656f, 2.86211423e-003f, 0.04333691f,
2639         -0.14603497f, -0.01946543f, -0.02327525f, -0.01973944f, 0.07944400f,
2640         -0.02224544f, -0.06701808f, 0.03476532f, 0.11505594f, -0.02712801f,
2641         -0.01665113f, 0.06315716f, -0.08205860f, 0.07431999f, 0.04915778f,
2642         -0.04468752f, -0.01490402f, 0.07400476f, -0.11650901f, 0.05102430f,
2643         0.04559118f, -0.05916039f, 0.08840760f, -0.01587902f, -0.14890194f,
2644         0.07857784f, 0.04710254f, -0.05381983f, -0.07331945f, -0.03604643f,
2645         0.15611970f, 0.07649943f, -0.05959348f, -0.02776607f, 0.11098688f,
2646         0.03758875f, -0.04446875f, 0.04933187f, 0.01345535f, 0.06921103f,
2647         0.07364785f, 0.05518956f, 0.02899585f, 0.09375840f, 0.10518434f,
2648         -0.04420241f, 0.01915282f, -3.56386811e-003f, 0.14586878f, 0.10286101f,
2649         -0.04360626f, -0.12723237f, 0.09076386f, 0.11119842f, -0.06035013f,
2650         0.09674817f, 0.08938243f, 0.07065924f, 0.02603180f, 5.84815582e-003f,
2651         -0.05922065f, 0.12360309f, 3.59695964e-003f, 2.99844006e-003f,
2652         0.03697936f, 0.02043072f, 0.04168725f, 0.01025975f, -0.01359980f,
2653         -0.01600920f, 0.02581056f, 0.02329250f, 2.98100687e-003f, 0.01629762f,
2654         0.06652115f, 0.05855627f, 0.01237463f, -0.01297135f, 0.01761587f,
2655         0.05090865f, 0.06549342f, -0.04425945f, 2.43203156e-003f,
2656         3.07327788e-003f, 0.06678630f, -0.04303836f, 0.01082393f, -0.06476044f,
2657         0.04077786f, 0.12441979f, 0.08237778f, 0.07424165f, 0.04065890f,
2658         0.06905543f, 0.09556347f, 0.12724875f, -0.02132082f, 0.08514154f,
2659         -0.04175328f, -0.02666954f, 0.01897836f, 0.03317382f, 9.45465732e-003f,
2660         -0.01238974f, -0.04242500f, -0.01419479f, -0.03545213f, -0.02440874f,
2661         0.08684119f, 0.04212951f, 0.02462858f, -0.01104825f, -5.01706870e-003f,
2662         0.02968982f, 0.02597476f, -0.01568939f, 0.04514892f, 0.06974549f,
2663         0.08670278f, 0.06828108f, 0.10238872f, 0.05405957f, 0.06548470f,
2664         -0.03763957f, 0.01366090f, 0.07069602f, 0.05363748f, 0.04798120f,
2665         0.11706422f, 0.05466456f, -0.01869259f, 0.06344382f, 0.03106543f,
2666         0.08432506f, -0.02061096f, 0.03821088f, -6.92190882e-003f,
2667         6.40467042e-003f, -0.01271779f, 6.89014705e-005f, 0.04541415f,
2668         -0.01899539f, -0.05020239f, 0.03000903f, 0.01090422f, 4.52452758e-003f,
2669         0.02573632f, -0.02388454f, -0.04200457f, 1.72783900e-003f,
2670         -0.05978370f, -0.02720562f, 0.06573715f, 0.01154317f, 0.01265615f,
2671         0.07375994f, -9.19828378e-003f, -0.04914120f, 0.02124831f, 0.06455322f,
2672         0.04372910f, -0.03310043f, 0.03605788f, -6.78055827e-003f,
2673         9.36202332e-003f, 0.01747596f, -0.06406314f, -0.06812935f, 0.08080816f,
2674         -0.02778088f, 0.02735260f, 0.06393493f, 0.06652229f, 0.05676993f,
2675         0.08640018f, -7.59188086e-003f, -0.02012847f, -0.04741159f,
2676         -0.01657069f, -0.01624399f, 0.05547778f, -2.33309763e-003f,
2677         0.01120033f, 0.06141156f, -0.06285004f, -0.08732341f, -0.09313398f,
2678         -0.04267832f, 5.57443965e-003f, 0.04809862f, 0.01773641f,
2679         5.37361018e-003f, 0.14842421f, -0.06298012f, -0.02935147f, 0.11443478f,
2680         -0.05034208f, 5.65494271e-003f, 0.02076526f, -0.04577984f,
2681         -0.04735741f, 0.02961071f, -0.09307127f, -0.04417921f, -0.04990027f,
2682         -0.03940028f, 0.01306016f, 0.06267900f, 0.03758737f, 0.08460117f,
2683         0.13858789f, 0.04862388f, -0.06319809f, -0.05655516f, 0.01885816f,
2684         -0.03285607f, 0.03371567f, -0.07040928f, -0.04514049f, 0.01392166f,
2685         0.08184422f, -0.07230316f, 0.02386871f, 0.02184591f, 0.02605764f,
2686         -0.01033954f, 9.29878280e-003f, 7.67351175e-003f, 0.15189242f,
2687         0.02069071f, -0.09738296f, -0.08894105f, -0.07768748f, 0.02332268f,
2688         -0.01778995f, -0.03258888f, -0.08180822f, -0.08492987f, 0.02290156f,
2689         -0.11368170f, -0.03554465f, -0.04533844f, -0.02861580f, 0.06782424f,
2690         0.01113123f, 0.02453644f, 0.12721945f, 0.08084814f, -0.03607795f,
2691         0.01109122f, 0.04803548f, -0.03489929f, 0.03399536f, -0.05682014f,
2692         8.59533902e-003f, -4.27904585e-003f, 0.03230887f, -0.01300198f,
2693         -0.01038137f, -0.07930113f, 8.33097473e-003f, 0.02296994f,
2694         -0.01306500f, -0.01881626f, 0.04413369f, 0.05729880f, -0.03761553f,
2695         0.01942326f, 1.64540811e-003f, -0.03811319f, 0.04190650f, -0.14978096f,
2696         -0.04514487f, 0.01209545f, -5.46460645e-003f, -0.01647195f,
2697         7.63064111e-003f, -0.07494587f, 0.08415288f, 0.10020141f, -0.01228561f,
2698         0.06553826f, 0.04554005f, 0.07890417f, 0.03041138f, 0.01752007f,
2699         0.09208256f, -3.74419295e-004f, 0.10549527f, 0.04686913f, 0.01894833f,
2700         -0.02651412f, -4.34682379e-003f, 5.44942822e-003f, 0.01444484f,
2701         0.05882156f, -0.03336544f, 0.04603891f, -0.10432546f, 0.01923928f,
2702         0.01842845f, -0.01712168f, -0.02222766f, 0.04693324f, -0.06202956f,
2703         -0.01422159f, 0.08732220f, -0.07706107f, 0.02661049f, -0.04300238f,
2704         -0.03092422f, -0.03552184f, -0.01886088f, -0.04979934f, 0.03906401f,
2705         0.04608644f, 0.04966111f, 0.04275464f, -0.04621769f, -0.02653212f,
2706         8.57011229e-003f, 0.03839684f, 0.05818764f, 0.03880796f,
2707         -2.76100676e-004f, 0.03076511f, -0.03266929f, -0.05374557f,
2708         0.04986527f, -9.45429131e-003f, 0.03582499f, -2.64564669e-003f,
2709         -1.07461517e-003f, 0.02962313f, -0.01483363f, 0.03060869f, 0.02448327f,
2710         0.01845641f, 0.03282966f, -0.03534438f, -0.01084059f, -0.01119136f,
2711         -1.85360224e-003f, -5.94652840e-004f, -0.04451817f, 2.98327743e-003f,
2712         0.06272484f, -0.02152076f, -3.05971340e-003f, -0.05070828f,
2713         0.01531762f, 0.01282815f, 0.05167150f, 9.46266949e-003f,
2714         -3.34558333e-003f, 0.11442288f, -0.03906701f, -2.67325155e-003f,
2715         0.03069184f, -0.01134165f, 0.02949462f, 0.02879886f, 0.03855566f,
2716         -0.03450781f, 0.09142872f, -0.02156654f, 0.06075062f, -0.06220816f,
2717         0.01944680f, 6.68372354e-003f, -0.06656796f, 8.70784000e-003f,
2718         0.03456013f, 0.02434320f, -0.13236357f, -0.04177035f, -0.02069627f,
2719         0.01068112f, 0.01505432f, -0.07517391f, -3.83571628e-003f,
2720         -0.06298508f, -0.02881260f, -0.13101046f, -0.07221562f,
2721         -5.79945277e-003f, -8.57300125e-003f, 0.03782469f, 0.02762164f,
2722         0.04942456f, -0.02936396f, 0.09597211f, 0.01921411f, 0.06101191f,
2723         -0.04787507f, -0.01379578f, -7.40224449e-003f, -0.02220136f,
2724         -0.01313756f, 7.77558051e-003f, 0.12296968f, 0.02939998f, 0.03594062f,
2725         -0.07788624f, -0.01133144f, 3.99316690e-004f, -0.06090347f,
2726         -0.01122066f, -4.68682544e-003f, 0.07633100f, -0.06748922f,
2727         -0.05640298f, -0.05265681f, -0.01139122f, -0.01624347f, -0.04715714f,
2728         -0.01099092f, 0.01048561f, 3.28499987e-003f, -0.05810167f,
2729         -0.07699911f, -0.03330683f, 0.04185145f, 0.03478536f, 0.02275165f,
2730         0.02304766f, 6.66040834e-003f, 0.10968148f, -5.93013782e-003f,
2731         -0.04858336f, -0.04203213f, -0.09316786f, -6.13074889e-003f,
2732         -0.02544625f, 0.01366201f, 9.18555818e-003f, -0.01846578f,
2733         -0.05622401f, -0.03989377f, -0.07810296f, 6.91275718e-003f,
2734         0.05957597f, -0.03901334f, 0.01572002f, -0.01193903f,
2735         -6.89400872e-003f, -0.03093356f, -0.04136098f, -0.01562869f,
2736         -0.04604580f, 0.02865234f, -0.08678447f, -0.03232484f, -0.05364593f,
2737         -0.01445016f, -0.07003860f, -0.08669746f, -0.04520775f, 0.04274122f,
2738         0.03117515f, 0.08175703f, 0.01081109f, 0.06379741f, 0.06199206f,
2739         0.02865988f, 0.02360346f, 0.06725410f, -0.03248780f, -9.37702879e-003f,
2740         0.08265898f, -0.02245839f, 0.05125763f, -0.01862395f, 0.01973453f,
2741         -0.01994494f, -0.10770868f, 0.03180375f, 3.23935156e-003f,
2742         -0.02142080f, -0.04256190f, 0.04760900f, 0.04282863f, 0.05635953f,
2743         -0.01870849f, 0.05540622f, -0.03042666f, 0.01455277f, -0.06630179f,
2744         -0.05843807f, -0.03739681f, -0.09739155f, -0.03220233f, -0.05620182f,
2745         -0.10381401f, 0.07400211f, 4.20676917e-003f, 0.03258535f,
2746         2.14308966e-003f, 0.05121966f, -0.01274337f, 0.02384761f, 0.06335578f,
2747         -0.07905591f, 0.08375625f, -0.07898903f, -0.06508528f, -0.02498444f,
2748         0.06535810f, 0.03970535f, 0.04895468f, -0.01169566f, -0.03980601f,
2749         0.05682293f, 0.05925463f, -0.01165808f, -0.07936699f, -0.04208954f,
2750         0.01333987f, 0.09051196f, 0.10098671f, -0.03974256f, 0.01238771f,
2751         -0.07501741f, -0.03655440f, -0.04301528f, 0.09216860f,
2752         4.63579083e-004f, 0.02851115f, 0.02142735f, 1.28244064e-004f,
2753         0.02879687f, -0.08554889f, -0.04838862f, 0.08135369f, -0.05756533f,
2754         0.01413900f, 0.03451880f, -0.06619488f, -0.03053130f, 0.02961676f,
2755         -0.07384635f, 0.01135692f, 0.05283910f, -0.07778034f, -0.02107482f,
2756         -0.05511716f, -0.13473752f, 0.03030157f, 0.06722020f, -0.06218817f,
2757         -0.05826827f, 0.06254654f, 0.02895772f, -0.01664000f, -0.03620280f,
2758         -0.01612278f, -1.46097376e-003f, 0.14013411f, -8.96181818e-003f,
2759         -0.03250246f, 3.38630192e-003f, 2.64779478e-003f, 0.03359732f,
2760         -0.02411991f, -0.04229729f, 0.10666174f, -6.66579151f };
2761     return std::vector<float>(detector, detector + sizeof(detector)/sizeof(detector[0]));
2762 }
2763 
2764 // This function renurn 1981 SVM coeffs obtained from daimler's base.
2765 // To use these coeffs the detection window size should be (48,96)
getDaimlerPeopleDetector()2766 std::vector<float> HOGDescriptor::getDaimlerPeopleDetector()
2767 {
2768     static const float detector[] = {
2769         0.294350f, -0.098796f, -0.129522f, 0.078753f,
2770         0.387527f, 0.261529f, 0.145939f, 0.061520f,
2771         0.328699f, 0.227148f, -0.066467f, -0.086723f,
2772         0.047559f, 0.106714f, 0.037897f, 0.111461f,
2773         -0.024406f, 0.304769f, 0.254676f, -0.069235f,
2774         0.082566f, 0.147260f, 0.326969f, 0.148888f,
2775         0.055270f, -0.087985f, 0.261720f, 0.143442f,
2776         0.026812f, 0.238212f, 0.194020f, 0.056341f,
2777         -0.025854f, -0.034444f, -0.156631f, 0.205174f,
2778         0.089008f, -0.139811f, -0.100147f, -0.037830f,
2779         -0.029230f, -0.055641f, 0.033248f, -0.016512f,
2780         0.155244f, 0.247315f, -0.124694f, -0.048414f,
2781         -0.062219f, 0.193683f, 0.004574f, 0.055089f,
2782         0.093565f, 0.167712f, 0.167581f, 0.018895f,
2783         0.215258f, 0.122609f, 0.090520f, -0.067219f,
2784         -0.049029f, -0.099615f, 0.241804f, -0.094893f,
2785         -0.176248f, 0.001727f, -0.134473f, 0.104442f,
2786         0.050942f, 0.081165f, 0.072156f, 0.121646f,
2787         0.002656f, -0.297974f, -0.133587f, -0.060121f,
2788         -0.092515f, -0.048974f, -0.084754f, -0.180111f,
2789         -0.038590f, 0.086283f, -0.134636f, -0.107249f,
2790         0.132890f, 0.141556f, 0.249425f, 0.130273f,
2791         -0.030031f, 0.073212f, -0.008155f, 0.019931f,
2792         0.071688f, 0.000300f, -0.019525f, -0.021725f,
2793         -0.040993f, -0.086841f, 0.070124f, 0.240033f,
2794         0.265350f, 0.043208f, 0.166754f, 0.091453f,
2795         0.060916f, -0.036972f, -0.091043f, 0.079873f,
2796         0.219781f, 0.158102f, -0.140618f, -0.043016f,
2797         0.124802f, 0.093668f, 0.103208f, 0.094872f,
2798         0.080541f, 0.137711f, 0.160566f, -0.169231f,
2799         0.013983f, 0.309508f, -0.004217f, -0.057200f,
2800         -0.064489f, 0.014066f, 0.361009f, 0.251328f,
2801         -0.080983f, -0.044183f, 0.061436f, -0.037381f,
2802         -0.078786f, 0.030993f, 0.066314f, 0.037683f,
2803         0.152325f, -0.091683f, 0.070203f, 0.217856f,
2804         0.036435f, -0.076462f, 0.006254f, -0.094431f,
2805         0.154829f, -0.023038f, -0.196961f, -0.024594f,
2806         0.178465f, -0.050139f, -0.045932f, -0.000965f,
2807         0.109112f, 0.046165f, -0.159373f, -0.008713f,
2808         0.041307f, 0.097129f, -0.057211f, -0.064599f,
2809         0.077165f, 0.176167f, 0.138322f, 0.065753f,
2810         -0.104950f, 0.017933f, 0.136255f, -0.011598f,
2811         0.047007f, 0.080550f, 0.068619f, 0.084661f,
2812         -0.035493f, -0.091314f, -0.041411f, 0.060971f,
2813         -0.101912f, -0.079870f, -0.085977f, -0.022686f,
2814         0.079788f, -0.098064f, -0.054603f, 0.040383f,
2815         0.300794f, 0.128603f, 0.094844f, 0.047407f,
2816         0.101825f, 0.061832f, -0.162160f, -0.204553f,
2817         -0.035165f, 0.101450f, -0.016641f, -0.027140f,
2818         -0.134392f, -0.008743f, 0.102331f, 0.114853f,
2819         0.009644f, 0.062823f, 0.237339f, 0.167843f,
2820         0.053066f, -0.012592f, 0.043158f, 0.002305f,
2821         0.065001f, -0.038929f, -0.020356f, 0.152343f,
2822         0.043469f, -0.029967f, -0.042948f, 0.032481f,
2823         0.068488f, -0.110840f, -0.111083f, 0.111980f,
2824         -0.002072f, -0.005562f, 0.082926f, 0.006635f,
2825         -0.108153f, 0.024242f, -0.086464f, -0.189884f,
2826         -0.017492f, 0.191456f, -0.007683f, -0.128769f,
2827         -0.038017f, -0.132380f, 0.091926f, 0.079696f,
2828         -0.106728f, -0.007656f, 0.172744f, 0.011576f,
2829         0.009883f, 0.083258f, -0.026516f, 0.145534f,
2830         0.153924f, -0.130290f, -0.108945f, 0.124490f,
2831         -0.003186f, -0.100485f, 0.015024f, -0.060512f,
2832         0.026288f, -0.086713f, -0.169012f, 0.076517f,
2833         0.215778f, 0.043701f, -0.131642f, -0.012585f,
2834         -0.045181f, -0.118183f, -0.241544f, -0.167293f,
2835         -0.020107f, -0.019917f, -0.101827f, -0.107096f,
2836         -0.010503f, 0.044938f, 0.189680f, 0.217119f,
2837         -0.046086f, 0.044508f, 0.199716f, -0.036004f,
2838         -0.148927f, 0.013355f, -0.078279f, 0.030451f,
2839         0.056301f, -0.024609f, 0.083224f, 0.099533f,
2840         -0.039432f, -0.138880f, 0.005482f, -0.024120f,
2841         -0.140468f, -0.066381f, -0.017057f, 0.009260f,
2842         -0.058004f, -0.028486f, -0.061610f, 0.007483f,
2843         -0.158309f, -0.150687f, -0.044595f, -0.105121f,
2844         -0.045763f, -0.006618f, -0.024419f, -0.117713f,
2845         -0.119366f, -0.175941f, -0.071542f, 0.119027f,
2846         0.111362f, 0.043080f, 0.034889f, 0.093003f,
2847         0.007842f, 0.057368f, -0.108834f, -0.079968f,
2848         0.230959f, 0.020205f, 0.011470f, 0.098877f,
2849         0.101310f, -0.030215f, -0.018018f, -0.059552f,
2850         -0.106157f, 0.021866f, -0.036471f, 0.080051f,
2851         0.041165f, -0.082101f, 0.117726f, 0.030961f,
2852         -0.054763f, -0.084102f, -0.185778f, -0.061305f,
2853         -0.038089f, -0.110728f, -0.264010f, 0.076675f,
2854         -0.077111f, -0.137644f, 0.036232f, 0.277995f,
2855         0.019116f, 0.107738f, 0.144003f, 0.080304f,
2856         0.215036f, 0.228897f, 0.072713f, 0.077773f,
2857         0.120168f, 0.075324f, 0.062730f, 0.122478f,
2858         -0.049008f, 0.164912f, 0.162450f, 0.041246f,
2859         0.009891f, -0.097827f, -0.038700f, -0.023027f,
2860         -0.120020f, 0.203364f, 0.248474f, 0.149810f,
2861         -0.036276f, -0.082814f, -0.090343f, -0.027143f,
2862         -0.075689f, -0.320310f, -0.000500f, -0.143334f,
2863         -0.065077f, -0.186936f, 0.129372f, 0.116431f,
2864         0.181699f, 0.170436f, 0.418854f, 0.460045f,
2865         0.333719f, 0.230515f, 0.047822f, -0.044954f,
2866         -0.068086f, 0.140179f, -0.044821f, 0.085550f,
2867         0.092483f, -0.107296f, -0.130670f, -0.206629f,
2868         0.114601f, -0.317869f, -0.076663f, 0.038680f,
2869         0.212753f, -0.016059f, -0.126526f, -0.163602f,
2870         0.210154f, 0.099887f, -0.126366f, 0.118453f,
2871         0.019309f, -0.021611f, -0.096499f, -0.111809f,
2872         -0.200489f, 0.142854f, 0.228840f, -0.353346f,
2873         -0.179151f, 0.116834f, 0.252389f, -0.031728f,
2874         -0.188135f, -0.158998f, 0.386523f, 0.122315f,
2875         0.209944f, 0.394023f, 0.359030f, 0.260717f,
2876         0.170335f, 0.013683f, -0.142596f, -0.026138f,
2877         -0.011878f, -0.150519f, 0.047159f, -0.107062f,
2878         -0.147347f, -0.187689f, -0.186027f, -0.208048f,
2879         0.058468f, -0.073026f, -0.236556f, -0.079788f,
2880         -0.146216f, -0.058563f, -0.101361f, -0.071294f,
2881         -0.071093f, 0.116919f, 0.234304f, 0.306781f,
2882         0.321866f, 0.240000f, 0.073261f, -0.012173f,
2883         0.026479f, 0.050173f, 0.166127f, 0.228955f,
2884         0.061905f, 0.156460f, 0.205990f, 0.120672f,
2885         0.037350f, 0.167884f, 0.290099f, 0.420900f,
2886         -0.012601f, 0.189839f, 0.306378f, 0.118383f,
2887         -0.095598f, -0.072360f, -0.132496f, -0.224259f,
2888         -0.126021f, 0.022714f, 0.284039f, 0.051369f,
2889         -0.000927f, -0.058735f, -0.083354f, -0.141254f,
2890         -0.187578f, -0.202669f, 0.048902f, 0.246597f,
2891         0.441863f, 0.342519f, 0.066979f, 0.215286f,
2892         0.188191f, -0.072240f, -0.208142f, -0.030196f,
2893         0.178141f, 0.136985f, -0.043374f, -0.181098f,
2894         0.091815f, 0.116177f, -0.126690f, -0.386625f,
2895         0.368165f, 0.269149f, -0.088042f, -0.028823f,
2896         0.092961f, 0.024099f, 0.046112f, 0.176756f,
2897         0.135849f, 0.124955f, 0.195467f, -0.037218f,
2898         0.167217f, 0.188938f, 0.053528f, -0.066561f,
2899         0.133721f, -0.070565f, 0.115898f, 0.152435f,
2900         -0.116993f, -0.110592f, -0.179005f, 0.026668f,
2901         0.080530f, 0.075084f, -0.070401f, 0.012497f,
2902         0.021849f, -0.139764f, -0.022020f, -0.096301f,
2903         -0.064954f, -0.127446f, -0.013806f, -0.108315f,
2904         0.156285f, 0.149867f, -0.011382f, 0.064532f,
2905         0.029168f, 0.027393f, 0.069716f, 0.153735f,
2906         0.038459f, 0.230714f, 0.253840f, 0.059522f,
2907         -0.045053f, 0.014083f, 0.071103f, 0.068747f,
2908         0.095887f, 0.005832f, 0.144887f, 0.026357f,
2909         -0.067359f, -0.044151f, -0.123283f, -0.019911f,
2910         0.005318f, 0.109208f, -0.003201f, -0.021734f,
2911         0.142025f, -0.066907f, -0.120070f, -0.188639f,
2912         0.012472f, -0.048704f, -0.012366f, -0.184828f,
2913         0.168591f, 0.267166f, 0.058208f, -0.044101f,
2914         0.033500f, 0.178558f, 0.104550f, 0.122418f,
2915         0.080177f, 0.173246f, 0.298537f, 0.064173f,
2916         0.053397f, 0.174341f, 0.230984f, 0.117025f,
2917         0.166242f, 0.227781f, 0.120623f, 0.176952f,
2918         -0.011393f, -0.086483f, -0.008270f, 0.051700f,
2919         -0.153369f, -0.058837f, -0.057639f, -0.060115f,
2920         0.026349f, -0.160745f, -0.037894f, -0.048575f,
2921         0.041052f, -0.022112f, 0.060365f, 0.051906f,
2922         0.162657f, 0.138519f, -0.050185f, -0.005938f,
2923         0.071301f, 0.127686f, 0.062342f, 0.144400f,
2924         0.072600f, 0.198436f, 0.246219f, -0.078185f,
2925         -0.036169f, 0.075934f, 0.047328f, -0.013601f,
2926         0.087205f, 0.019900f, 0.022606f, -0.015365f,
2927         -0.092506f, 0.075275f, -0.116375f, 0.050500f,
2928         0.045118f, 0.166567f, 0.072073f, 0.060371f,
2929         0.131747f, -0.169863f, -0.039352f, -0.047486f,
2930         -0.039797f, -0.204312f, 0.021710f, 0.129443f,
2931         -0.021173f, 0.173416f, -0.070794f, -0.063986f,
2932         0.069689f, -0.064099f, -0.123201f, -0.017372f,
2933         -0.206870f, 0.065863f, 0.113226f, 0.024707f,
2934         -0.071341f, -0.066964f, -0.098278f, -0.062927f,
2935         0.075840f, 0.014716f, 0.019378f, 0.132699f,
2936         -0.074191f, -0.089557f, -0.078446f, -0.197488f,
2937         -0.173665f, 0.052583f, 0.044361f, 0.113549f,
2938         0.098492f, 0.077379f, -0.011146f, -0.192593f,
2939         -0.164435f, 0.045568f, 0.205699f, 0.049187f,
2940         -0.082281f, 0.134874f, 0.185499f, 0.034968f,
2941         -0.119561f, -0.112372f, -0.115091f, -0.054042f,
2942         -0.183816f, -0.078100f, 0.190695f, 0.091617f,
2943         0.004257f, -0.041135f, -0.061453f, -0.141592f,
2944         -0.194809f, -0.120638f, 0.020168f, 0.109672f,
2945         0.067398f, -0.015238f, -0.239145f, -0.264671f,
2946         -0.185176f, 0.050472f, 0.020793f, 0.035678f,
2947         0.022839f, -0.052055f, -0.127968f, -0.113049f,
2948         -0.228416f, -0.258281f, -0.053437f, 0.076424f,
2949         0.061450f, 0.237478f, 0.003618f, -0.055865f,
2950         -0.108087f, -0.028937f, 0.045585f, 0.052829f,
2951         -0.001471f, 0.022826f, 0.059565f, -0.104430f,
2952         -0.077266f, -0.211882f, -0.212078f, 0.028074f,
2953         0.075846f, 0.016265f, 0.161879f, 0.134477f,
2954         0.008935f, -0.048041f, 0.074692f, 0.004928f,
2955         -0.025156f, 0.192874f, 0.074410f, 0.308732f,
2956         0.267400f, 0.094208f, -0.005251f, 0.042041f,
2957         -0.032148f, 0.015588f, 0.252869f, 0.175302f,
2958         0.022892f, 0.081673f, 0.063208f, 0.162626f,
2959         0.194426f, 0.233890f, 0.262292f, 0.186930f,
2960         0.084079f, -0.286388f, -0.213034f, -0.048867f,
2961         -0.207669f, -0.170050f, 0.011673f, -0.092958f,
2962         -0.192786f, -0.273536f, 0.230904f, 0.266732f,
2963         0.320519f, 0.297155f, 0.548169f, 0.304922f,
2964         0.132687f, 0.247333f, 0.212488f, -0.271472f,
2965         -0.142105f, -0.002627f, -0.119215f, 0.128383f,
2966         0.100079f, -0.057490f, -0.121902f, -0.228892f,
2967         0.202292f, -0.399795f, -0.371326f, -0.095836f,
2968         -0.063626f, -0.161375f, -0.311180f, -0.294797f,
2969         0.242122f, 0.011788f, 0.095573f, 0.322523f,
2970         0.511840f, 0.322880f, 0.313259f, 0.173331f,
2971         0.002542f, -0.029802f, 0.324766f, -0.326170f,
2972         -0.340547f, -0.138288f, -0.002963f, -0.114060f,
2973         -0.377312f, -0.442570f, 0.212446f, -0.007759f,
2974         -0.011576f, 0.169711f, 0.308689f, 0.317348f,
2975         0.539390f, 0.332845f, 0.057331f, -0.068180f,
2976         0.101994f, 0.266995f, 0.209570f, 0.355730f,
2977         0.091635f, 0.170238f, 0.125215f, 0.274154f,
2978         0.070223f, 0.025515f, 0.049946f, -0.000550f,
2979         0.043715f, -0.141843f, 0.020844f, 0.129871f,
2980         0.256588f, 0.105015f, 0.148339f, 0.170682f,
2981         0.028792f, 0.074037f, 0.160042f, 0.405137f,
2982         0.246187f, 0.352160f, 0.168951f, 0.222263f,
2983         0.264439f, 0.065945f, 0.021963f, -0.075084f,
2984         0.093105f, 0.027318f, 0.098864f, 0.057566f,
2985         -0.080282f, 0.185032f, 0.314419f, 0.333727f,
2986         0.125798f, 0.294919f, 0.386002f, 0.217619f,
2987         -0.183517f, -0.278622f, -0.002342f, -0.027821f,
2988         -0.134266f, -0.331843f, -0.008296f, 0.124564f,
2989         0.053712f, -0.369016f, -0.095036f, 0.209381f,
2990         0.423760f, 0.371760f, 0.106397f, 0.369408f,
2991         0.485608f, 0.231201f, -0.138685f, -0.349208f,
2992         -0.070083f, 0.028991f, -0.081630f, -0.395992f,
2993         -0.146791f, -0.027354f, 0.063396f, -0.272484f,
2994         0.058299f, 0.338207f, 0.110767f, -0.052642f,
2995         -0.233848f, -0.027448f, 0.030328f, 0.155572f,
2996         -0.093826f, 0.019331f, 0.120638f, 0.006292f,
2997         -0.106083f, -0.236290f, -0.140933f, -0.088067f,
2998         -0.025138f, -0.208395f, -0.025502f, 0.144192f,
2999         -0.048353f, -0.106144f, -0.305121f, -0.114147f,
3000         0.090963f, 0.327727f, 0.035606f, -0.093779f,
3001         0.002651f, -0.171081f, -0.188131f, -0.216571f,
3002         -0.209101f, -0.054402f, 0.157147f, -0.057127f,
3003         0.066584f, 0.008988f, 0.041191f, 0.034456f,
3004         -0.078255f, 0.052099f, -0.022239f, 0.066981f,
3005         -0.117520f, -0.072637f, 0.062512f, 0.037570f,
3006         -0.057544f, -0.312359f, 0.034357f, -0.031549f,
3007         0.002566f, -0.207375f, -0.070654f, -0.018786f,
3008         -0.044815f, -0.012814f, -0.076320f, 0.078183f,
3009         0.023877f, 0.117078f, 0.022292f, -0.205424f,
3010         -0.060430f, -0.017296f, -0.004827f, -0.321036f,
3011         -0.092155f, 0.038837f, 0.073190f, -0.067513f,
3012         0.026521f, 0.171945f, 0.087318f, 0.034495f,
3013         -0.034089f, 0.154410f, -0.061431f, 0.007435f,
3014         -0.111094f, -0.095976f, 0.014741f, -0.132324f,
3015         -0.029517f, -0.192160f, 0.098667f, 0.020762f,
3016         0.177050f, -0.064510f, -0.054437f, -0.058678f,
3017         -0.001858f, 0.167602f, 0.015735f, 0.054338f,
3018         0.016477f, 0.186381f, -0.010667f, 0.054692f,
3019         0.126742f, 0.013140f, 0.090353f, -0.133608f,
3020         -0.018017f, -0.152619f, 0.027600f, -0.138700f,
3021         -0.050274f, 0.045141f, -0.118731f, 0.094797f,
3022         -0.167605f, 0.097461f, -0.009131f, 0.199920f,
3023         -0.052976f, 0.158194f, 0.178568f, -0.107600f,
3024         0.009671f, -0.084072f, -0.040258f, -0.205673f,
3025         0.102891f, 0.223511f, 0.042699f, 0.118548f,
3026         -0.021274f, 0.110997f, -0.155121f, 0.027696f,
3027         -0.149968f, 0.051552f, -0.129219f, 0.173524f,
3028         0.073972f, -0.189045f, -0.034523f, -0.106655f,
3029         -0.011843f, -0.197381f, 0.219413f, 0.183197f,
3030         -0.054920f, 0.144955f, 0.036517f, -0.085412f,
3031         -0.229070f, -0.143710f, -0.049486f, 0.156634f,
3032         -0.008673f, -0.064778f, 0.082344f, 0.145673f,
3033         0.002912f, -0.210121f, -0.116564f, 0.078425f,
3034         0.220908f, -0.067594f, 0.048610f, 0.084912f,
3035         -0.066202f, -0.112515f, -0.217767f, -0.082640f,
3036         -0.017414f, 0.230265f, -0.070735f, 0.066073f,
3037         0.215256f, 0.071157f, -0.087220f, -0.202235f,
3038         -0.011918f, 0.099562f, 0.174716f, -0.063845f,
3039         -0.121055f, 0.014367f, 0.132709f, -0.005060f,
3040         -0.244606f, -0.179693f, -0.134690f, 0.023239f,
3041         -0.193116f, -0.076975f, -0.021164f, -0.001938f,
3042         -0.163799f, -0.111437f, -0.210362f, -0.166376f,
3043         0.034754f, 0.010036f, -0.021917f, 0.068014f,
3044         -0.086893f, -0.251746f, -0.267171f, 0.037383f,
3045         0.003966f, 0.033571f, -0.151506f, 0.025437f,
3046         -0.020626f, -0.308454f, -0.343143f, -0.092263f,
3047         -0.026261f, -0.028345f, 0.036036f, 0.035169f,
3048         0.129470f, 0.122205f, 0.015661f, -0.070612f,
3049         -0.094333f, -0.066055f, -0.041083f, 0.159146f,
3050         0.073184f, 0.110044f, 0.174471f, 0.078069f,
3051         -0.014881f, 0.008116f, 0.013209f, 0.075857f,
3052         0.195605f, 0.062714f, 0.067955f, 0.056544f,
3053         -0.153908f, -0.141749f, -0.072550f, 0.033523f,
3054         -0.024665f, 0.134487f, 0.079076f, 0.133562f,
3055         0.227130f, 0.018054f, 0.004928f, 0.169162f,
3056         0.065152f, 0.072160f, 0.131631f, 0.096303f,
3057         0.054288f, 0.106256f, 0.114632f, 0.119038f,
3058         0.515200f, 0.247429f, 0.199134f, 0.211957f,
3059         0.127558f, -0.294684f, -0.194890f, -0.049988f,
3060         -0.112247f, -0.008122f, -0.006176f, 0.037035f,
3061         -0.110881f, -0.249989f, 0.152434f, 0.234621f,
3062         0.153340f, 0.349283f, 0.683049f, 0.157174f,
3063         0.124844f, 0.099136f, 0.064407f, -0.248400f,
3064         -0.155323f, -0.026498f, -0.023450f, 0.049051f,
3065         -0.114187f, 0.007195f, -0.176825f, -0.376926f,
3066         0.366159f, -0.179938f, -0.148508f, 0.006043f,
3067         0.170048f, 0.097866f, -0.102658f, -0.260430f,
3068         0.248868f, 0.037019f, -0.118111f, 0.078176f,
3069         0.194171f, 0.211328f, 0.368612f, 0.361213f,
3070         0.130013f, 0.094650f, 0.227396f, -0.178058f,
3071         -0.114782f, -0.008093f, 0.231080f, -0.011843f,
3072         -0.097917f, -0.325788f, 0.141879f, 0.119738f,
3073         -0.230427f, -0.117419f, -0.114153f, 0.037903f,
3074         0.116383f, 0.218773f, -0.101884f, 0.059466f,
3075         0.119255f, 0.010874f, -0.031449f, 0.045996f,
3076         0.119931f, 0.273760f, 0.311700f, 0.261794f,
3077         0.194809f, 0.339829f, 0.239449f, 0.064140f,
3078         0.077597f, 0.098996f, 0.143534f, 0.184602f,
3079         0.037507f, 0.225494f, 0.096142f, -0.147370f,
3080         -0.207833f, -0.174742f, -0.086391f, -0.038942f,
3081         0.159577f, -0.088492f, -0.000989f, 0.108154f,
3082         -0.025890f, -0.072713f, 0.025997f, -0.006803f,
3083         -0.086879f, -0.011290f, -0.269200f, -0.103450f,
3084         -0.124910f, -0.116340f, 0.141459f, 0.208800f,
3085         0.042268f, 0.265034f, 0.516474f, 0.217591f,
3086         -0.018843f, -0.313328f, -0.168363f, 0.047129f,
3087         0.090480f, -0.109852f, -0.018761f, 0.210669f,
3088         0.281269f, -0.043591f, -0.034147f, -0.237772f,
3089         -0.134843f, -0.072481f, -0.103831f, 0.038355f,
3090         0.308619f, 0.148023f, -0.045867f, -0.123950f,
3091         -0.210860f, -0.064973f, -0.036308f, -0.046731f,
3092         -0.022099f, 0.095776f, 0.409423f, 0.060635f,
3093         -0.065196f, 0.051828f, 0.027981f, -0.009609f,
3094         -0.137681f, -0.095011f, -0.019045f, 0.177278f,
3095         0.009759f, -0.092119f, -0.016958f, -0.133860f,
3096         -0.118421f, -0.032039f, -0.006214f, -0.084541f,
3097         0.063971f, -0.073642f, 0.165676f, 0.110443f,
3098         0.044131f, 0.046568f, 0.053292f, -0.055466f,
3099         0.015512f, 0.371947f, 0.232102f, -0.016923f,
3100         0.103979f, -0.091758f, 0.005907f, 0.209100f,
3101         0.157433f, 0.030518f, 0.250366f, 0.062322f,
3102         0.036720f, 0.094676f, 0.017306f, -0.010328f,
3103         -0.079012f, 0.016781f, -0.112435f, 0.061795f,
3104         0.042543f, -0.126799f, -0.009975f, -0.056760f,
3105         0.046424f, -0.194712f, -0.139399f, -0.037731f,
3106         0.157989f, -0.016261f, 0.123345f, 0.230563f,
3107         0.083300f, -0.016392f, 0.059567f, -0.016035f,
3108         -0.064767f, 0.231945f, 0.156629f, 0.034602f,
3109         0.145628f, 0.041315f, 0.034535f, 0.019967f,
3110         -0.089188f, -0.012091f, 0.307857f, 0.211405f,
3111         -0.025091f, -0.148249f, -0.129384f, 0.063536f,
3112         -0.068603f, -0.067941f, -0.035104f, 0.210832f,
3113         0.063810f, 0.062764f, -0.089889f, -0.030554f,
3114         0.014791f, -0.053362f, -0.037818f, -0.196640f,
3115         0.008388f, -0.082654f, 0.143056f, 0.064221f,
3116         0.069795f, 0.191040f, 0.097321f, -0.028679f,
3117         0.075794f, 0.313154f, 0.086240f, 0.207643f,
3118         0.017809f, 0.122867f, 0.224586f, 0.167403f,
3119         -0.023884f, 0.047434f, 0.344091f, 0.187745f,
3120         0.136177f, 0.141738f, 0.063799f, 0.045233f,
3121         -0.077342f, -0.003525f, -0.165041f, -0.025616f,
3122         -0.073745f, 0.164439f, 0.011200f, -0.145896f,
3123         -0.027954f, -0.061987f, -0.039874f, -0.142775f,
3124         0.151042f, -0.038238f, 0.053152f, 0.078615f,
3125         0.086061f, 0.100593f, 0.128046f, -0.071006f,
3126         -0.116558f, 0.208445f, 0.051086f, 0.076843f,
3127         0.023191f, -0.084781f, -0.011790f, 0.147807f,
3128         -0.048554f, -0.113932f, 0.283322f, 0.190934f,
3129         0.092789f, 0.033018f, -0.142428f, -0.142480f,
3130         -0.099023f, -0.041020f, -0.042760f, 0.203295f,
3131         -0.053475f, 0.042424f, 0.222839f, -0.019167f,
3132         -0.133176f, -0.276216f, -0.031998f, 0.117290f,
3133         0.177827f, -0.059973f, -0.064744f, -0.117040f,
3134         -0.155482f, -0.099531f, 0.164121f, -0.026682f,
3135         -0.093810f, 0.238993f, -0.006506f, 0.007830f,
3136         0.065819f, -0.203643f, -0.100925f, -0.053652f,
3137         -0.130770f, 0.026277f, 0.131796f, 0.032742f,
3138         0.127186f, 0.116694f, -0.161122f, -0.279773f,
3139         -0.252515f, -0.002638f, 0.042812f, 0.096776f,
3140         -0.123280f, 0.064858f, -0.010455f, -0.219760f,
3141         -0.239331f, -0.104363f, -0.058022f, -0.053584f,
3142         0.025611f, 0.005129f, -0.100418f, -0.045712f,
3143         -0.194418f, -0.126366f, -0.030530f, 0.051168f,
3144         0.215959f, 0.172402f, -0.054700f, -0.185995f,
3145         -0.278360f, -0.193693f, -0.040309f, 0.003735f,
3146         -0.007770f, 0.123556f, 0.190179f, -0.077315f,
3147         0.117403f, 0.212942f, 0.012160f, 0.000113f,
3148         0.027331f, 0.040202f, 0.033293f, 0.219438f,
3149         0.184174f, 0.259349f, 0.311206f, 0.082547f,
3150         -0.047875f, -0.078417f, 0.010746f, 0.082620f,
3151         0.311931f, 0.307605f, 0.003863f, 0.021405f,
3152         -0.026388f, -0.019572f, 0.020582f, -0.059353f,
3153         0.025199f, 0.261319f, 0.086316f, 0.143614f,
3154         0.107780f, 0.003900f, -0.188397f, -0.038563f,
3155         -0.106045f, -0.125154f, -0.010509f, 0.054021f,
3156         0.242130f, 0.279152f, 0.215546f, 0.346995f,
3157         0.440856f, 0.237452f, 0.234154f, 0.301646f,
3158         0.168929f, -0.208358f, -0.126848f, 0.010260f,
3159         0.121018f, -0.062975f, -0.052848f, 0.050341f,
3160         -0.061103f, -0.266482f, 0.107186f, 0.140221f,
3161         0.280065f, 0.287889f, 0.373198f, 0.151596f,
3162         0.013593f, 0.115616f, 0.014616f, -0.281710f,
3163         -0.237597f, -0.117305f, -0.000034f, -0.136739f,
3164         -0.196275f, -0.095225f, -0.125310f, -0.250514f,
3165         0.236804f, -0.071805f, -0.037421f, 0.048230f,
3166         0.321596f, 0.063632f, 0.024039f, -0.029133f,
3167         0.230983f, 0.160593f, -0.154355f, -0.013086f,
3168         -0.079929f, 0.094692f, 0.160391f, 0.180239f,
3169         0.053895f, 0.100759f, 0.288631f, 0.038191f,
3170         0.181692f, 0.229682f, 0.440166f, 0.063401f,
3171         0.006273f, 0.020865f, 0.338695f, 0.256244f,
3172         -0.043927f, 0.115617f, 0.003296f, 0.173965f,
3173         0.021318f, -0.040936f, -0.118932f, 0.182380f,
3174         0.235922f, -0.053233f, -0.015053f, -0.101057f,
3175         0.095341f, 0.051111f, 0.161831f, 0.032614f,
3176         0.159496f, 0.072375f, 0.025089f, 0.023748f,
3177         0.029151f, 0.161284f, -0.117717f, -0.036191f,
3178         -0.176822f, -0.162006f, 0.226542f, -0.078329f,
3179         0.043079f, -0.119172f, 0.054614f, -0.101365f,
3180         -0.064541f, -0.115304f, 0.135170f, 0.298872f,
3181         0.098060f, 0.089428f, -0.007497f, 0.110391f,
3182         -0.028824f, 0.020835f, -0.036804f, 0.125411f,
3183         0.192105f, -0.048931f, 0.003086f, -0.010681f,
3184         0.074698f, -0.016263f, 0.096063f, 0.060267f,
3185         -0.007277f, 0.139139f, -0.080635f, 0.036628f,
3186         0.086058f, 0.131979f, 0.085707f, 0.025301f,
3187         0.226094f, 0.194759f, 0.042193f, -0.157846f,
3188         -0.068402f, -0.141450f, -0.112659f, -0.076305f,
3189         -0.069085f, -0.114332f, -0.102005f, 0.132193f,
3190         -0.067042f, 0.106643f, 0.198964f, 0.171616f,
3191         0.167237f, -0.033730f, -0.026755f, 0.083621f,
3192         0.149459f, -0.002799f, -0.000318f, 0.011753f,
3193         0.065889f, -0.089375f, -0.049610f, 0.224579f,
3194         0.216548f, -0.034908f, -0.017851f, -0.088144f,
3195         0.007530f, 0.240268f, 0.073270f, 0.013263f,
3196         0.175323f, 0.012082f, 0.093993f, 0.015282f,
3197         0.105854f, 0.107990f, 0.077798f, -0.096166f,
3198         -0.079607f, 0.177820f, 0.142392f, 0.033337f,
3199         -0.078100f, -0.081616f, -0.046993f, 0.139459f,
3200         0.020272f, -0.123161f, 0.175269f, 0.105217f,
3201         0.057328f, 0.080909f, -0.012612f, -0.097081f,
3202         0.082060f, -0.096716f, -0.063921f, 0.201884f,
3203         0.128166f, -0.035051f, -0.032227f, -0.068139f,
3204         -0.115915f, 0.095080f, -0.086007f, -0.067543f,
3205         0.030776f, 0.032712f, 0.088937f, 0.054336f,
3206         -0.039329f, -0.114022f, 0.171672f, -0.112321f,
3207         -0.217646f, 0.065186f, 0.060223f, 0.192174f,
3208         0.055580f, -0.131107f, -0.144338f, 0.056730f,
3209         -0.034707f, -0.081616f, -0.135298f, -0.000614f,
3210         0.087189f, 0.014614f, 0.067709f, 0.107689f,
3211         0.225780f, 0.084361f, -0.008544f, 0.051649f,
3212         -0.048369f, -0.037739f, -0.060710f, 0.002654f,
3213         0.016935f, 0.085563f, -0.015961f, -0.019265f,
3214         0.111788f, 0.062376f, 0.202019f, 0.047713f,
3215         0.042261f, 0.069716f, 0.242913f, 0.021052f,
3216         -0.072812f, -0.155920f, -0.026436f, 0.035621f,
3217         -0.079300f, -0.028787f, -0.048329f, 0.084718f,
3218         -0.060565f, -0.083750f, -0.164075f, -0.040742f,
3219         -0.086219f, 0.015271f, -0.005204f, -0.016038f,
3220         0.045816f, -0.050433f, -0.077652f, 0.117109f,
3221         0.009611f, -0.009045f, -0.008634f, -0.055373f,
3222         -0.085968f, 0.028527f, -0.054736f, -0.168089f,
3223         0.175839f, 0.071205f, -0.023603f, 0.037907f,
3224         -0.004561f, -0.022634f, 0.123831f, 0.094469f,
3225         -0.072920f, -0.133642f, -0.014032f, -0.142754f,
3226         -0.026999f, -0.199409f, 0.013268f, 0.226989f,
3227         0.048650f, -0.170988f, -0.050141f, 0.007880f,
3228         0.061880f, 0.019078f, -0.043578f, -0.038139f,
3229         0.134814f, 0.054097f, -0.081670f, 0.176838f,
3230         0.047920f, -0.038176f, 0.050406f, -0.107181f,
3231         -0.036279f, 0.027060f, 0.081594f, -0.002820f,
3232         0.090507f, -0.033338f, -0.059571f, 0.013404f,
3233         -0.099860f, 0.073371f, 0.342805f, 0.098305f,
3234         -0.150910f, -0.020822f, -0.056960f, 0.046262f,
3235         -0.043413f, -0.149405f, -0.129105f, -0.010899f,
3236         -0.014229f, -0.179949f, -0.113044f, -0.049468f,
3237         -0.065513f, 0.090269f, -0.011919f, 0.087846f,
3238         0.095796f, 0.146127f, 0.101599f, 0.078066f,
3239         -0.084348f, -0.100002f, -0.020134f, -0.050169f,
3240         0.062122f, 0.014640f, 0.019143f, 0.036543f,
3241         0.180924f, -0.013976f, -0.066768f, -0.001090f,
3242         -0.070419f, -0.004839f, -0.001504f, 0.034483f,
3243         -0.044954f, -0.050336f, -0.088638f, -0.174782f,
3244         -0.116082f, -0.205507f, 0.015587f, -0.042839f,
3245         -0.096879f, -0.144097f, -0.050268f, -0.196796f,
3246         0.109639f, 0.271411f, 0.173732f, 0.108070f,
3247         0.156437f, 0.124255f, 0.097242f, 0.238693f,
3248         0.083941f, 0.109105f, 0.223940f, 0.267188f,
3249         0.027385f, 0.025819f, 0.125070f, 0.093738f,
3250         0.040353f, 0.038645f, -0.012730f, 0.144063f,
3251         0.052931f, -0.009138f, 0.084193f, 0.160272f,
3252         -0.041366f, 0.011951f, -0.121446f, -0.106713f,
3253         -0.047566f, 0.047984f, -0.255224f, -0.076116f,
3254         0.098685f, -0.150845f, -0.171513f, -0.156590f,
3255         0.058331f, 0.187493f, 0.413018f, 0.554265f,
3256         0.372242f, 0.237943f, 0.124571f, 0.110829f,
3257         0.010322f, -0.174477f, -0.067627f, -0.001979f,
3258         0.142913f, 0.040597f, 0.019907f, 0.025963f,
3259         -0.043585f, -0.120732f, 0.099937f, 0.091059f,
3260         0.247307f, 0.204226f, -0.042753f, -0.068580f,
3261         -0.119002f, 0.026722f, 0.034853f, -0.060934f,
3262         -0.025054f, -0.093026f, -0.035372f, -0.233209f,
3263         -0.049869f, -0.039151f, -0.022279f, -0.065380f,
3264         -9.063785f};
3265     return std::vector<float>(detector, detector + sizeof(detector)/sizeof(detector[0]));
3266 }
3267 
3268 class HOGConfInvoker :
3269     public ParallelLoopBody
3270 {
3271 public:
HOGConfInvoker(const HOGDescriptor * _hog,const Mat & _img,double _hitThreshold,const Size & _padding,std::vector<DetectionROI> * locs,std::vector<Rect> * _vec,Mutex * _mtx)3272     HOGConfInvoker( const HOGDescriptor* _hog, const Mat& _img,
3273         double _hitThreshold, const Size& _padding,
3274         std::vector<DetectionROI>* locs,
3275         std::vector<Rect>* _vec, Mutex* _mtx )
3276     {
3277         hog = _hog;
3278         img = _img;
3279         hitThreshold = _hitThreshold;
3280         padding = _padding;
3281         locations = locs;
3282         vec = _vec;
3283         mtx = _mtx;
3284     }
3285 
operator ()(const Range & range) const3286     void operator()( const Range& range ) const
3287     {
3288         int i, i1 = range.start, i2 = range.end;
3289 
3290         Size maxSz(cvCeil(img.cols/(*locations)[0].scale), cvCeil(img.rows/(*locations)[0].scale));
3291         Mat smallerImgBuf(maxSz, img.type());
3292         std::vector<Point> dets;
3293 
3294         for( i = i1; i < i2; i++ )
3295         {
3296             double scale = (*locations)[i].scale;
3297 
3298             Size sz(cvRound(img.cols / scale), cvRound(img.rows / scale));
3299             Mat smallerImg(sz, img.type(), smallerImgBuf.ptr());
3300 
3301             if( sz == img.size() )
3302                 smallerImg = Mat(sz, img.type(), img.data, img.step);
3303             else
3304                 resize(img, smallerImg, sz);
3305 
3306             hog->detectROI(smallerImg, (*locations)[i].locations, dets, (*locations)[i].confidences, hitThreshold, Size(), padding);
3307             Size scaledWinSize = Size(cvRound(hog->winSize.width*scale), cvRound(hog->winSize.height*scale));
3308             mtx->lock();
3309             for( size_t j = 0; j < dets.size(); j++ )
3310                 vec->push_back(Rect(cvRound(dets[j].x*scale),
3311                                     cvRound(dets[j].y*scale),
3312                                     scaledWinSize.width, scaledWinSize.height));
3313             mtx->unlock();
3314         }
3315     }
3316 
3317     const HOGDescriptor* hog;
3318     Mat img;
3319     double hitThreshold;
3320     std::vector<DetectionROI>* locations;
3321     Size padding;
3322     std::vector<Rect>* vec;
3323     Mutex* mtx;
3324 };
3325 
detectROI(const cv::Mat & img,const std::vector<cv::Point> & locations,CV_OUT std::vector<cv::Point> & foundLocations,CV_OUT std::vector<double> & confidences,double hitThreshold,cv::Size winStride,cv::Size padding) const3326 void HOGDescriptor::detectROI(const cv::Mat& img, const std::vector<cv::Point> &locations,
3327     CV_OUT std::vector<cv::Point>& foundLocations, CV_OUT std::vector<double>& confidences,
3328     double hitThreshold, cv::Size winStride, cv::Size padding) const
3329 {
3330     foundLocations.clear();
3331     confidences.clear();
3332 
3333     if( svmDetector.empty() || locations.empty())
3334         return;
3335 
3336     if( winStride == Size() )
3337         winStride = cellSize;
3338     Size cacheStride(gcd(winStride.width, blockStride.width),
3339                      gcd(winStride.height, blockStride.height));
3340 
3341     size_t nwindows = locations.size();
3342     padding.width = (int)alignSize(std::max(padding.width, 0), cacheStride.width);
3343     padding.height = (int)alignSize(std::max(padding.height, 0), cacheStride.height);
3344     Size paddedImgSize(img.cols + padding.width*2, img.rows + padding.height*2);
3345 
3346     // HOGCache cache(this, img, padding, padding, nwindows == 0, cacheStride);
3347     HOGCache cache(this, img, padding, padding, true, cacheStride);
3348     if( !nwindows )
3349         nwindows = cache.windowsInImage(paddedImgSize, winStride).area();
3350 
3351     const HOGCache::BlockData* blockData = &cache.blockData[0];
3352 
3353     int nblocks = cache.nblocks.area();
3354     int blockHistogramSize = cache.blockHistogramSize;
3355     size_t dsize = getDescriptorSize();
3356 
3357     double rho = svmDetector.size() > dsize ? svmDetector[dsize] : 0;
3358     std::vector<float> blockHist(blockHistogramSize);
3359 
3360 #if CV_SSE2
3361     float partSum[4];
3362 #endif
3363 
3364     for( size_t i = 0; i < nwindows; i++ )
3365     {
3366         Point pt0;
3367         pt0 = locations[i];
3368         if( pt0.x < -padding.width || pt0.x > img.cols + padding.width - winSize.width ||
3369                 pt0.y < -padding.height || pt0.y > img.rows + padding.height - winSize.height )
3370         {
3371             // out of image
3372             confidences.push_back(-10.0);
3373             continue;
3374         }
3375 
3376         double s = rho;
3377         const float* svmVec = &svmDetector[0];
3378         int j, k;
3379 
3380         for( j = 0; j < nblocks; j++, svmVec += blockHistogramSize )
3381         {
3382             const HOGCache::BlockData& bj = blockData[j];
3383             Point pt = pt0 + bj.imgOffset;
3384 
3385             // need to devide this into 4 parts!
3386             const float* vec = cache.getBlock(pt, &blockHist[0]);
3387 #if CV_SSE2
3388             __m128 _vec = _mm_loadu_ps(vec);
3389             __m128 _svmVec = _mm_loadu_ps(svmVec);
3390             __m128 sum = _mm_mul_ps(_svmVec, _vec);
3391 
3392             for( k = 4; k <= blockHistogramSize - 4; k += 4 )
3393             {
3394                 _vec = _mm_loadu_ps(vec + k);
3395                 _svmVec = _mm_loadu_ps(svmVec + k);
3396 
3397                 sum = _mm_add_ps(sum, _mm_mul_ps(_vec, _svmVec));
3398             }
3399 
3400             _mm_storeu_ps(partSum, sum);
3401             double t0 = partSum[0] + partSum[1];
3402             double t1 = partSum[2] + partSum[3];
3403             s += t0 + t1;
3404 #else
3405             for( k = 0; k <= blockHistogramSize - 4; k += 4 )
3406                 s += vec[k]*svmVec[k] + vec[k+1]*svmVec[k+1] +
3407                         vec[k+2]*svmVec[k+2] + vec[k+3]*svmVec[k+3];
3408 #endif
3409             for( ; k < blockHistogramSize; k++ )
3410                 s += vec[k]*svmVec[k];
3411         }
3412         confidences.push_back(s);
3413 
3414         if( s >= hitThreshold )
3415             foundLocations.push_back(pt0);
3416     }
3417 }
3418 
detectMultiScaleROI(const cv::Mat & img,CV_OUT std::vector<cv::Rect> & foundLocations,std::vector<DetectionROI> & locations,double hitThreshold,int groupThreshold) const3419 void HOGDescriptor::detectMultiScaleROI(const cv::Mat& img,
3420     CV_OUT std::vector<cv::Rect>& foundLocations, std::vector<DetectionROI>& locations,
3421     double hitThreshold, int groupThreshold) const
3422 {
3423     std::vector<Rect> allCandidates;
3424     Mutex mtx;
3425 
3426     parallel_for_(Range(0, (int)locations.size()),
3427                   HOGConfInvoker(this, img, hitThreshold, Size(8, 8),
3428                                  &locations, &allCandidates, &mtx));
3429 
3430     foundLocations.resize(allCandidates.size());
3431     std::copy(allCandidates.begin(), allCandidates.end(), foundLocations.begin());
3432     cv::groupRectangles(foundLocations, groupThreshold, 0.2);
3433 }
3434 
readALTModel(String modelfile)3435 void HOGDescriptor::readALTModel(String modelfile)
3436 {
3437     // read model from SVMlight format..
3438     FILE *modelfl;
3439     if ((modelfl = fopen(modelfile.c_str(), "rb")) == NULL)
3440     {
3441         String eerr("file not exist");
3442         String efile(__FILE__);
3443         String efunc(__FUNCTION__);
3444         throw Exception(Error::StsError, eerr, efile, efunc, __LINE__);
3445     }
3446     char version_buffer[10];
3447     if (!fread (&version_buffer,sizeof(char),10,modelfl))
3448     {
3449         String eerr("version?");
3450         String efile(__FILE__);
3451         String efunc(__FUNCTION__);
3452         throw Exception(Error::StsError, eerr, efile, efunc, __LINE__);
3453     }
3454     if(strcmp(version_buffer,"V6.01")) {
3455         String eerr("version doesnot match");
3456         String efile(__FILE__);
3457         String efunc(__FUNCTION__);
3458         throw Exception(Error::StsError, eerr, efile, efunc, __LINE__);
3459     }
3460     /* read version number */
3461     int version = 0;
3462     if (!fread (&version,sizeof(int),1,modelfl))
3463     { throw Exception(); }
3464     if (version < 200)
3465     {
3466         String eerr("version doesnot match");
3467         String efile(__FILE__);
3468         String efunc(__FUNCTION__);
3469         throw Exception();
3470     }
3471     int kernel_type;
3472     size_t nread;
3473     nread=fread(&(kernel_type),sizeof(int),1,modelfl);
3474 
3475     {// ignore these
3476         int poly_degree;
3477         nread=fread(&(poly_degree),sizeof(int),1,modelfl);
3478 
3479         double rbf_gamma;
3480         nread=fread(&(rbf_gamma),sizeof(double), 1, modelfl);
3481         double coef_lin;
3482         nread=fread(&(coef_lin),sizeof(double),1,modelfl);
3483         double coef_const;
3484         nread=fread(&(coef_const),sizeof(double),1,modelfl);
3485         int l;
3486         nread=fread(&l,sizeof(int),1,modelfl);
3487         char* custom = new char[l];
3488         nread=fread(custom,sizeof(char),l,modelfl);
3489         delete[] custom;
3490     }
3491     int totwords;
3492     nread=fread(&(totwords),sizeof(int),1,modelfl);
3493     {// ignore these
3494         int totdoc;
3495         nread=fread(&(totdoc),sizeof(int),1,modelfl);
3496         int sv_num;
3497         nread=fread(&(sv_num), sizeof(int),1,modelfl);
3498     }
3499 
3500     double linearbias;
3501     nread=fread(&linearbias, sizeof(double), 1, modelfl);
3502 
3503     std::vector<float> detector;
3504     detector.clear();
3505     if(kernel_type == 0) { /* linear kernel */
3506         /* save linear wts also */
3507         double *linearwt = new double[totwords+1];
3508         int length = totwords;
3509         nread = fread(linearwt, sizeof(double), totwords + 1, modelfl);
3510         if(nread != static_cast<size_t>(length) + 1) {
3511             delete [] linearwt;
3512             throw Exception();
3513         }
3514 
3515         for(int i = 0; i < length; i++)
3516             detector.push_back((float)linearwt[i]);
3517 
3518         detector.push_back((float)-linearbias);
3519         setSVMDetector(detector);
3520         delete [] linearwt;
3521     } else {
3522         throw Exception();
3523     }
3524     fclose(modelfl);
3525 }
3526 
groupRectangles(std::vector<cv::Rect> & rectList,std::vector<double> & weights,int groupThreshold,double eps) const3527 void HOGDescriptor::groupRectangles(std::vector<cv::Rect>& rectList, std::vector<double>& weights, int groupThreshold, double eps) const
3528 {
3529     if( groupThreshold <= 0 || rectList.empty() )
3530     {
3531         return;
3532     }
3533 
3534     CV_Assert(rectList.size() == weights.size());
3535 
3536     std::vector<int> labels;
3537     int nclasses = partition(rectList, labels, SimilarRects(eps));
3538 
3539     std::vector<cv::Rect_<double> > rrects(nclasses);
3540     std::vector<int> numInClass(nclasses, 0);
3541     std::vector<double> foundWeights(nclasses, -std::numeric_limits<double>::max());
3542     int i, j, nlabels = (int)labels.size();
3543 
3544     for( i = 0; i < nlabels; i++ )
3545     {
3546         int cls = labels[i];
3547         rrects[cls].x += rectList[i].x;
3548         rrects[cls].y += rectList[i].y;
3549         rrects[cls].width += rectList[i].width;
3550         rrects[cls].height += rectList[i].height;
3551         foundWeights[cls] = max(foundWeights[cls], weights[i]);
3552         numInClass[cls]++;
3553     }
3554 
3555     for( i = 0; i < nclasses; i++ )
3556     {
3557         // find the average of all ROI in the cluster
3558         cv::Rect_<double> r = rrects[i];
3559         double s = 1.0/numInClass[i];
3560         rrects[i] = cv::Rect_<double>(cv::saturate_cast<double>(r.x*s),
3561             cv::saturate_cast<double>(r.y*s),
3562             cv::saturate_cast<double>(r.width*s),
3563             cv::saturate_cast<double>(r.height*s));
3564     }
3565 
3566     rectList.clear();
3567     weights.clear();
3568 
3569     for( i = 0; i < nclasses; i++ )
3570     {
3571         cv::Rect r1 = rrects[i];
3572         int n1 = numInClass[i];
3573         double w1 = foundWeights[i];
3574         if( n1 <= groupThreshold )
3575             continue;
3576         // filter out small rectangles inside large rectangles
3577         for( j = 0; j < nclasses; j++ )
3578         {
3579             int n2 = numInClass[j];
3580 
3581             if( j == i || n2 <= groupThreshold )
3582                 continue;
3583 
3584             cv::Rect r2 = rrects[j];
3585 
3586             int dx = cv::saturate_cast<int>( r2.width * eps );
3587             int dy = cv::saturate_cast<int>( r2.height * eps );
3588 
3589             if( r1.x >= r2.x - dx &&
3590                 r1.y >= r2.y - dy &&
3591                 r1.x + r1.width <= r2.x + r2.width + dx &&
3592                 r1.y + r1.height <= r2.y + r2.height + dy &&
3593                 (n2 > std::max(3, n1) || n1 < 3) )
3594                 break;
3595         }
3596 
3597         if( j == nclasses )
3598         {
3599             rectList.push_back(r1);
3600             weights.push_back(w1);
3601         }
3602     }
3603 }
3604 }
3605