Renesas GR-PEACH OpenCV Development / gr-peach-opencv-project-sd-card_update

Fork of gr-peach-opencv-project-sd-card by the do

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers hog.cpp Source File

hog.cpp

00001 /*M///////////////////////////////////////////////////////////////////////////////////////
00002 //
00003 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
00004 //
00005 //  By downloading, copying, installing or using the software you agree to this license.
00006 //  If you do not agree to this license, do not download, install,
00007 //  copy or use the software.
00008 //
00009 //
00010 //                           License Agreement
00011 //                For Open Source Computer Vision Library
00012 //
00013 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
00014 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
00015 // Third party copyrights are property of their respective owners.
00016 //
00017 // Redistribution and use in source and binary forms, with or without modification,
00018 // are permitted provided that the following conditions are met:
00019 //
00020 //   * Redistribution's of source code must retain the above copyright notice,
00021 //     this list of conditions and the following disclaimer.
00022 //
00023 //   * Redistribution's in binary form must reproduce the above copyright notice,
00024 //     this list of conditions and the following disclaimer in the documentation
00025 //     and/or other materials provided with the distribution.
00026 //
00027 //   * The name of the copyright holders may not be used to endorse or promote products
00028 //     derived from this software without specific prior written permission.
00029 //
00030 // This software is provided by the copyright holders and contributors "as is" and
00031 // any express or implied warranties, including, but not limited to, the implied
00032 // warranties of merchantability and fitness for a particular purpose are disclaimed.
00033 // In no event shall the Intel Corporation or contributors be liable for any direct,
00034 // indirect, incidental, special, exemplary, or consequential damages
00035 // (including, but not limited to, procurement of substitute goods or services;
00036 // loss of use, data, or profits; or business interruption) however caused
00037 // and on any theory of liability, whether in contract, strict liability,
00038 // or tort (including negligence or otherwise) arising in any way out of
00039 // the use of this software, even if advised of the possibility of such damage.
00040 //
00041 //M*/
00042 #include "opencv2/core.hpp"
00043 #include "precomp.hpp"
00044 #include "cascadedetect.hpp"
00045 #include "opencv2/core/core_c.h"
00046 //#include "opencl_kernels_objdetect.hpp"
00047 
00048 #include <cstdio>
00049 #include <iterator>
00050 #include <limits>
00051 
00052 /****************************************************************************************\
00053       The code below is implementation of HOG (Histogram-of-Oriented Gradients)
00054       descriptor and object detection, introduced by Navneet Dalal and Bill Triggs.
00055 
00056       The computed feature vectors are compatible with the
00057       INRIA Object Detection and Localization Toolkit
00058       (http://pascal.inrialpes.fr/soft/olt/)
00059 \****************************************************************************************/
00060 
00061 namespace cv
00062 {
00063 
00064 #define NTHREADS 256
00065 
00066 enum {DESCR_FORMAT_COL_BY_COL, DESCR_FORMAT_ROW_BY_ROW};
00067 
00068 static int numPartsWithin(int size, int part_size, int stride)
00069 {
00070     return (size - part_size + stride) / stride;
00071 }
00072 
00073 static Size numPartsWithin(cv::Size size, cv::Size part_size,
00074                                                 cv::Size stride)
00075 {
00076     return Size(numPartsWithin(size.width, part_size.width, stride.width),
00077         numPartsWithin(size.height, part_size.height, stride.height));
00078 }
00079 
00080 static size_t getBlockHistogramSize(Size block_size, Size cell_size, int nbins)
00081 {
00082     Size cells_per_block = Size(block_size.width / cell_size.width,
00083         block_size.height / cell_size.height);
00084     return (size_t)(nbins * cells_per_block.area());
00085 }
00086 
00087 size_t HOGDescriptor::getDescriptorSize() const
00088 {
00089     CV_Assert(blockSize.width % cellSize.width == 0 &&
00090         blockSize.height % cellSize.height == 0);
00091     CV_Assert((winSize.width - blockSize.width) % blockStride.width == 0 &&
00092         (winSize.height - blockSize.height) % blockStride.height == 0 );
00093 
00094     return (size_t)nbins*
00095         (blockSize.width/cellSize.width)*
00096         (blockSize.height/cellSize.height)*
00097         ((winSize.width - blockSize.width)/blockStride.width + 1)*
00098         ((winSize.height - blockSize.height)/blockStride.height + 1);
00099 }
00100 
00101 double HOGDescriptor::getWinSigma() const
00102 {
00103     return winSigma >= 0 ? winSigma : (blockSize.width + blockSize.height)/8.;
00104 }
00105 
00106 bool HOGDescriptor::checkDetectorSize() const
00107 {
00108     size_t detectorSize = svmDetector.size(), descriptorSize = getDescriptorSize();
00109     return detectorSize == 0 ||
00110         detectorSize == descriptorSize ||
00111         detectorSize == descriptorSize + 1;
00112 }
00113 
00114 void HOGDescriptor::setSVMDetector(InputArray _svmDetector)
00115 {
00116     _svmDetector.getMat().convertTo(svmDetector, CV_32F);
00117     CV_Assert(checkDetectorSize());
00118 
00119     Mat detector_reordered(1, (int)svmDetector.size(), CV_32FC1);
00120 
00121     size_t block_hist_size = getBlockHistogramSize(blockSize, cellSize, nbins);
00122     cv::Size blocks_per_img = numPartsWithin(winSize, blockSize, blockStride);
00123 
00124     for (int i = 0; i < blocks_per_img.height; ++i)
00125         for (int j = 0; j < blocks_per_img.width; ++j)
00126         {
00127             const float *src = &svmDetector[0] + (j * blocks_per_img.height + i) * block_hist_size;
00128             float *dst = detector_reordered.ptr<float>() + (i * blocks_per_img.width + j) * block_hist_size;
00129             for (size_t k = 0; k < block_hist_size; ++k)
00130                 dst[k] = src[k];
00131         }
00132     size_t descriptor_size = getDescriptorSize();
00133     free_coef = svmDetector.size() > descriptor_size ? svmDetector[descriptor_size] : 0;
00134     detector_reordered.copyTo(oclSvmDetector);
00135 }
00136 
00137 #define CV_TYPE_NAME_HOG_DESCRIPTOR "opencv-object-detector-hog"
00138 
00139 bool HOGDescriptor::read(FileNode& obj)
00140 {
00141     if( !obj.isMap() )
00142         return false;
00143     FileNodeIterator it = obj["winSize"].begin();
00144     it >> winSize.width >> winSize.height;
00145     it = obj["blockSize"].begin();
00146     it >> blockSize.width >> blockSize.height;
00147     it = obj["blockStride"].begin();
00148     it >> blockStride.width >> blockStride.height;
00149     it = obj["cellSize"].begin();
00150     it >> cellSize.width >> cellSize.height;
00151     obj["nbins"] >> nbins;
00152     obj["derivAperture"] >> derivAperture;
00153     obj["winSigma"] >> winSigma;
00154     obj["histogramNormType"] >> histogramNormType;
00155     obj["L2HysThreshold"] >> L2HysThreshold;
00156     obj["gammaCorrection"] >> gammaCorrection;
00157     obj["nlevels"] >> nlevels;
00158     if (obj["signedGradient"].empty())
00159         signedGradient = false;
00160     else
00161         obj["signedGradient"] >> signedGradient;
00162 
00163     FileNode vecNode = obj["SVMDetector"];
00164     if( vecNode.isSeq() )
00165     {
00166         vecNode >> svmDetector;
00167         CV_Assert(checkDetectorSize());
00168     }
00169     return true;
00170 }
00171 
00172 void HOGDescriptor::write(FileStorage& fs, const String& objName) const
00173 {
00174     if( !objName.empty() )
00175         fs << objName;
00176 
00177     fs << "{" CV_TYPE_NAME_HOG_DESCRIPTOR
00178        << "winSize" << winSize
00179        << "blockSize" << blockSize
00180        << "blockStride" << blockStride
00181        << "cellSize" << cellSize
00182        << "nbins" << nbins
00183        << "derivAperture" << derivAperture
00184        << "winSigma" << getWinSigma()
00185        << "histogramNormType" << histogramNormType
00186        << "L2HysThreshold" << L2HysThreshold
00187        << "gammaCorrection" << gammaCorrection
00188        << "nlevels" << nlevels
00189        << "signedGradient" << signedGradient;
00190     if( !svmDetector.empty() )
00191         fs << "SVMDetector" << svmDetector;
00192     fs << "}";
00193 }
00194 
00195 bool HOGDescriptor::load(const String& filename, const String& objname)
00196 {
00197     FileStorage fs(filename, FileStorage::READ);
00198     FileNode obj = !objname.empty() ? fs[objname] : fs.getFirstTopLevelNode();
00199     return read(obj);
00200 }
00201 
00202 void HOGDescriptor::save(const String& filename, const String& objName) const
00203 {
00204     FileStorage fs(filename, FileStorage::WRITE);
00205     write(fs, !objName.empty() ? objName : FileStorage::getDefaultObjectName(filename));
00206 }
00207 
00208 void HOGDescriptor::copyTo(HOGDescriptor& c) const
00209 {
00210     c.winSize = winSize;
00211     c.blockSize = blockSize;
00212     c.blockStride = blockStride;
00213     c.cellSize = cellSize;
00214     c.nbins = nbins;
00215     c.derivAperture = derivAperture;
00216     c.winSigma = winSigma;
00217     c.histogramNormType = histogramNormType;
00218     c.L2HysThreshold = L2HysThreshold;
00219     c.gammaCorrection = gammaCorrection;
00220     c.svmDetector = svmDetector;
00221     c.nlevels = nlevels;
00222     c.signedGradient = signedGradient;
00223 }
00224 
00225 void HOGDescriptor::computeGradient(const Mat& img, Mat& grad, Mat& qangle,
00226     Size paddingTL, Size paddingBR) const
00227 {
00228     CV_Assert( img.type() == CV_8U || img.type() == CV_8UC3 );
00229 
00230     Size gradsize(img.cols + paddingTL.width + paddingBR.width,
00231         img.rows + paddingTL.height + paddingBR.height);
00232     grad.create(gradsize, CV_32FC2);  // <magnitude*(1-alpha), magnitude*alpha>
00233     qangle.create(gradsize, CV_8UC2); // [0..nbins-1] - quantized gradient orientation
00234 
00235     Size wholeSize;
00236     Point roiofs;
00237     img.locateROI(wholeSize, roiofs);
00238 
00239     int i, x, y;
00240     int cn = img.channels();
00241 
00242     Mat_<float> _lut(1, 256);
00243     const float* const lut = &_lut(0,0);
00244 #if CV_SSE2
00245     const int indeces[] = { 0, 1, 2, 3 };
00246     __m128i idx = _mm_loadu_si128((const __m128i*)indeces);
00247     __m128i ifour = _mm_set1_epi32(4);
00248 
00249     float* const _data = &_lut(0, 0);
00250     if( gammaCorrection )
00251         for( i = 0; i < 256; i += 4 )
00252         {
00253             _mm_storeu_ps(_data + i, _mm_sqrt_ps(_mm_cvtepi32_ps(idx)));
00254             idx = _mm_add_epi32(idx, ifour);
00255         }
00256     else
00257         for( i = 0; i < 256; i += 4 )
00258         {
00259             _mm_storeu_ps(_data + i, _mm_cvtepi32_ps(idx));
00260             idx = _mm_add_epi32(idx, ifour);
00261         }
00262 #else
00263     if( gammaCorrection )
00264         for( i = 0; i < 256; i++ )
00265             _lut(0,i) = std::sqrt((float)i);
00266     else
00267         for( i = 0; i < 256; i++ )
00268             _lut(0,i) = (float)i;
00269 #endif
00270 
00271     AutoBuffer<int> mapbuf(gradsize.width + gradsize.height + 4);
00272     int* xmap = (int*)mapbuf + 1;
00273     int* ymap = xmap + gradsize.width + 2;
00274 
00275     const int borderType = (int)BORDER_REFLECT_101;
00276 
00277     for( x = -1; x < gradsize.width + 1; x++ )
00278         xmap[x] = borderInterpolate(x - paddingTL.width + roiofs.x,
00279         wholeSize.width, borderType) - roiofs.x;
00280     for( y = -1; y < gradsize.height + 1; y++ )
00281         ymap[y] = borderInterpolate(y - paddingTL.height + roiofs.y,
00282         wholeSize.height, borderType) - roiofs.y;
00283 
00284     // x- & y- derivatives for the whole row
00285     int width = gradsize.width;
00286     AutoBuffer<float> _dbuf(width*4);
00287     float* const dbuf = _dbuf;
00288     Mat Dx(1, width, CV_32F, dbuf);
00289     Mat Dy(1, width, CV_32F, dbuf + width);
00290     Mat Mag(1, width, CV_32F, dbuf + width*2);
00291     Mat Angle(1, width, CV_32F, dbuf + width*3);
00292 
00293     if (cn == 3)
00294     {
00295         int end = gradsize.width + 2;
00296         xmap -= 1, x = 0;
00297 #if CV_SSE2
00298         __m128i ithree = _mm_set1_epi32(3);
00299         for ( ; x <= end - 4; x += 4)
00300             _mm_storeu_si128((__m128i*)(xmap + x), _mm_mullo_epi16(ithree,
00301                 _mm_loadu_si128((const __m128i*)(xmap + x))));
00302 #endif
00303         for ( ; x < end; ++x)
00304             xmap[x] *= 3;
00305         xmap += 1;
00306     }
00307 
00308     float angleScale = signedGradient ? (float)(nbins/(2.0*CV_PI)) : (float)(nbins/CV_PI);
00309     for( y = 0; y < gradsize.height; y++ )
00310     {
00311         const uchar* imgPtr  = img.ptr(ymap[y]);
00312         //In case subimage is used ptr() generates an assert for next and prev rows
00313         //(see http://code.opencv.org/issues/4149)
00314         const uchar* prevPtr = img.data + img.step*ymap[y-1];
00315         const uchar* nextPtr = img.data + img.step*ymap[y+1];
00316 
00317         float* gradPtr = grad.ptr<float>(y);
00318         uchar* qanglePtr = qangle.ptr(y);
00319 
00320         if( cn == 1 )
00321         {
00322             for( x = 0; x < width; x++ )
00323             {
00324                 int x1 = xmap[x];
00325                 dbuf[x] = (float)(lut[imgPtr[xmap[x+1]]] - lut[imgPtr[xmap[x-1]]]);
00326                 dbuf[width + x] = (float)(lut[nextPtr[x1]] - lut[prevPtr[x1]]);
00327             }
00328         }
00329         else
00330         {
00331             x = 0;
00332 #if CV_SSE2
00333             for( ; x <= width - 4; x += 4 )
00334             {
00335                 int x0 = xmap[x], x1 = xmap[x+1], x2 = xmap[x+2], x3 = xmap[x+3];
00336                 typedef const uchar* const T;
00337                 T p02 = imgPtr + xmap[x+1], p00 = imgPtr + xmap[x-1];
00338                 T p12 = imgPtr + xmap[x+2], p10 = imgPtr + xmap[x];
00339                 T p22 = imgPtr + xmap[x+3], p20 = p02;
00340                 T p32 = imgPtr + xmap[x+4], p30 = p12;
00341 
00342                 __m128 _dx0 = _mm_sub_ps(_mm_set_ps(lut[p32[0]], lut[p22[0]], lut[p12[0]], lut[p02[0]]),
00343                                          _mm_set_ps(lut[p30[0]], lut[p20[0]], lut[p10[0]], lut[p00[0]]));
00344                 __m128 _dx1 = _mm_sub_ps(_mm_set_ps(lut[p32[1]], lut[p22[1]], lut[p12[1]], lut[p02[1]]),
00345                                          _mm_set_ps(lut[p30[1]], lut[p20[1]], lut[p10[1]], lut[p00[1]]));
00346                 __m128 _dx2 = _mm_sub_ps(_mm_set_ps(lut[p32[2]], lut[p22[2]], lut[p12[2]], lut[p02[2]]),
00347                                          _mm_set_ps(lut[p30[2]], lut[p20[2]], lut[p10[2]], lut[p00[2]]));
00348 
00349                 __m128 _dy0 = _mm_sub_ps(_mm_set_ps(lut[nextPtr[x3]], lut[nextPtr[x2]], lut[nextPtr[x1]], lut[nextPtr[x0]]),
00350                                          _mm_set_ps(lut[prevPtr[x3]], lut[prevPtr[x2]], lut[prevPtr[x1]], lut[prevPtr[x0]]));
00351                 __m128 _dy1 = _mm_sub_ps(_mm_set_ps(lut[nextPtr[x3+1]], lut[nextPtr[x2+1]], lut[nextPtr[x1+1]], lut[nextPtr[x0+1]]),
00352                                          _mm_set_ps(lut[prevPtr[x3+1]], lut[prevPtr[x2+1]], lut[prevPtr[x1+1]], lut[prevPtr[x0+1]]));
00353                 __m128 _dy2 = _mm_sub_ps(_mm_set_ps(lut[nextPtr[x3+2]], lut[nextPtr[x2+2]], lut[nextPtr[x1+2]], lut[nextPtr[x0+2]]),
00354                                          _mm_set_ps(lut[prevPtr[x3+2]], lut[prevPtr[x2+2]], lut[prevPtr[x1+2]], lut[prevPtr[x0+2]]));
00355 
00356                 __m128 _mag0 = _mm_add_ps(_mm_mul_ps(_dx0, _dx0), _mm_mul_ps(_dy0, _dy0));
00357                 __m128 _mag1 = _mm_add_ps(_mm_mul_ps(_dx1, _dx1), _mm_mul_ps(_dy1, _dy1));
00358                 __m128 _mag2 = _mm_add_ps(_mm_mul_ps(_dx2, _dx2), _mm_mul_ps(_dy2, _dy2));
00359 
00360                 __m128 mask = _mm_cmpgt_ps(_mag2, _mag1);
00361                 _dx2 = _mm_or_ps(_mm_and_ps(_dx2, mask), _mm_andnot_ps(mask, _dx1));
00362                 _dy2 = _mm_or_ps(_mm_and_ps(_dy2, mask), _mm_andnot_ps(mask, _dy1));
00363 
00364                 mask = _mm_cmpgt_ps(_mm_max_ps(_mag2, _mag1), _mag0);
00365                 _dx2 = _mm_or_ps(_mm_and_ps(_dx2, mask), _mm_andnot_ps(mask, _dx0));
00366                 _dy2 = _mm_or_ps(_mm_and_ps(_dy2, mask), _mm_andnot_ps(mask, _dy0));
00367 
00368                 _mm_storeu_ps(dbuf + x, _dx2);
00369                 _mm_storeu_ps(dbuf + x + width, _dy2);
00370             }
00371 #endif
00372             for( ; x < width; x++ )
00373             {
00374                 int x1 = xmap[x];
00375                 float dx0, dy0, dx, dy, mag0, mag;
00376                 const uchar* p2 = imgPtr + xmap[x+1];
00377                 const uchar* p0 = imgPtr + xmap[x-1];
00378 
00379                 dx0 = lut[p2[2]] - lut[p0[2]];
00380                 dy0 = lut[nextPtr[x1+2]] - lut[prevPtr[x1+2]];
00381                 mag0 = dx0*dx0 + dy0*dy0;
00382 
00383                 dx = lut[p2[1]] - lut[p0[1]];
00384                 dy = lut[nextPtr[x1+1]] - lut[prevPtr[x1+1]];
00385                 mag = dx*dx + dy*dy;
00386                 if( mag0 < mag )
00387                 {
00388                     dx0 = dx;
00389                     dy0 = dy;
00390                     mag0 = mag;
00391                 }
00392 
00393                 dx = lut[p2[0]] - lut[p0[0]];
00394                 dy = lut[nextPtr[x1]] - lut[prevPtr[x1]];
00395                 mag = dx*dx + dy*dy;
00396                 if( mag0 < mag )
00397                 {
00398                     dx0 = dx;
00399                     dy0 = dy;
00400                     mag0 = mag;
00401                 }
00402 
00403                 dbuf[x] = dx0;
00404                 dbuf[x+width] = dy0;
00405             }
00406         }
00407 
00408         // computing angles and magnidutes
00409         cartToPolar( Dx, Dy, Mag, Angle, false );
00410 
00411         // filling the result matrix
00412         x = 0;
00413 #if CV_SSE2
00414         __m128 fhalf = _mm_set1_ps(0.5f), fzero = _mm_setzero_ps();
00415         __m128 _angleScale = _mm_set1_ps(angleScale), fone = _mm_set1_ps(1.0f);
00416         __m128i ione = _mm_set1_epi32(1), _nbins = _mm_set1_epi32(nbins), izero = _mm_setzero_si128();
00417 
00418         for ( ; x <= width - 4; x += 4)
00419         {
00420             int x2 = x << 1;
00421             __m128 _mag = _mm_loadu_ps(dbuf + x + (width << 1));
00422             __m128 _angle = _mm_loadu_ps(dbuf + x + width * 3);
00423             _angle = _mm_sub_ps(_mm_mul_ps(_angleScale, _angle), fhalf);
00424 
00425             __m128 sign = _mm_and_ps(fone, _mm_cmplt_ps(_angle, fzero));
00426             __m128i _hidx = _mm_cvttps_epi32(_angle);
00427             _hidx = _mm_sub_epi32(_hidx, _mm_cvtps_epi32(sign));
00428             _angle = _mm_sub_ps(_angle, _mm_cvtepi32_ps(_hidx));
00429 
00430             __m128 ft0 = _mm_mul_ps(_mag, _mm_sub_ps(fone, _angle));
00431             __m128 ft1 = _mm_mul_ps(_mag, _angle);
00432             __m128 ft2 = _mm_unpacklo_ps(ft0, ft1);
00433             __m128 ft3 = _mm_unpackhi_ps(ft0, ft1);
00434 
00435             _mm_storeu_ps(gradPtr + x2, ft2);
00436             _mm_storeu_ps(gradPtr + x2 + 4, ft3);
00437 
00438             __m128i mask0 = _mm_sub_epi32(izero, _mm_srli_epi32(_hidx, 31));
00439             __m128i it0 = _mm_and_si128(mask0, _nbins);
00440             mask0 = _mm_cmplt_epi32(_hidx, _nbins);
00441             __m128i it1 = _mm_andnot_si128(mask0, _nbins);
00442             _hidx = _mm_add_epi32(_hidx, _mm_sub_epi32(it0, it1));
00443 
00444             it0 = _mm_packus_epi16(_mm_packs_epi32(_hidx, izero), izero);
00445             _hidx = _mm_add_epi32(ione, _hidx);
00446             _hidx = _mm_and_si128(_hidx, _mm_cmplt_epi32(_hidx, _nbins));
00447             it1 = _mm_packus_epi16(_mm_packs_epi32(_hidx, izero), izero);
00448             it0 = _mm_unpacklo_epi8(it0, it1);
00449 
00450             _mm_storel_epi64((__m128i*)(qanglePtr + x2), it0);
00451         }
00452 #endif
00453         for( ; x < width; x++ )
00454         {
00455             float mag = dbuf[x+width*2], angle = dbuf[x+width*3]*angleScale - 0.5f;
00456             int hidx = cvFloor(angle);
00457             angle -= hidx;
00458             gradPtr[x*2] = mag*(1.f - angle);
00459             gradPtr[x*2+1] = mag*angle;
00460 
00461             if( hidx < 0 )
00462                 hidx += nbins;
00463             else if( hidx >= nbins )
00464                 hidx -= nbins;
00465 
00466             CV_Assert( (unsigned)hidx < (unsigned)nbins );
00467 
00468             qanglePtr[x*2] = (uchar)hidx;
00469             hidx++;
00470             hidx &= hidx < nbins ? -1 : 0;
00471             qanglePtr[x*2+1] = (uchar)hidx;
00472         }
00473     }
00474 }
00475 
00476 struct HOGCache
00477 {
00478     struct BlockData
00479     {
00480         BlockData() :
00481             histOfs(0), imgOffset()
00482         { }
00483 
00484         int histOfs;
00485         Point imgOffset;
00486     };
00487 
00488     struct PixData
00489     {
00490         size_t gradOfs, qangleOfs;
00491         int histOfs[4];
00492         float histWeights[4];
00493         float gradWeight;
00494     };
00495 
00496     HOGCache();
00497     HOGCache(const HOGDescriptor* descriptor,
00498         const Mat& img, const Size& paddingTL, const Size& paddingBR,
00499         bool useCache, const Size& cacheStride);
00500     virtual ~HOGCache() { }
00501     virtual void init(const HOGDescriptor* descriptor,
00502         const Mat& img, const Size& paddingTL, const Size& paddingBR,
00503         bool useCache, const Size& cacheStride);
00504 
00505     Size windowsInImage(const Size& imageSize, const Size& winStride) const;
00506     Rect getWindow(const Size& imageSize, const Size& winStride, int idx) const;
00507 
00508     const float* getBlock(Point pt, float* buf);
00509     virtual void normalizeBlockHistogram(float* histogram) const;
00510 
00511     std::vector<PixData> pixData;
00512     std::vector<BlockData> blockData;
00513 
00514     bool useCache;
00515     std::vector<int> ymaxCached;
00516     Size winSize;
00517     Size cacheStride;
00518     Size nblocks, ncells;
00519     int blockHistogramSize;
00520     int count1, count2, count4;
00521     Point imgoffset;
00522     Mat_<float> blockCache;
00523     Mat_<uchar> blockCacheFlags;
00524 
00525     Mat grad, qangle;
00526     const HOGDescriptor* descriptor;
00527 };
00528 
00529 HOGCache::HOGCache() :
00530     blockHistogramSize(), count1(), count2(), count4()
00531 {
00532     useCache = false;
00533     descriptor = 0;
00534 }
00535 
00536 HOGCache::HOGCache(const HOGDescriptor* _descriptor,
00537     const Mat& _img, const Size& _paddingTL, const Size& _paddingBR,
00538     bool _useCache, const Size& _cacheStride)
00539 {
00540     init(_descriptor, _img, _paddingTL, _paddingBR, _useCache, _cacheStride);
00541 }
00542 
00543 void HOGCache::init(const HOGDescriptor* _descriptor,
00544     const Mat& _img, const Size& _paddingTL, const Size& _paddingBR,
00545     bool _useCache, const Size& _cacheStride)
00546 {
00547     descriptor = _descriptor;
00548     cacheStride = _cacheStride;
00549     useCache = _useCache;
00550 
00551     descriptor->computeGradient(_img, grad, qangle, _paddingTL, _paddingBR);
00552     imgoffset = _paddingTL;
00553 
00554     winSize = descriptor->winSize;
00555     Size blockSize = descriptor->blockSize;
00556     Size blockStride = descriptor->blockStride;
00557     Size cellSize = descriptor->cellSize;
00558     int i, j, nbins = descriptor->nbins;
00559     int rawBlockSize = blockSize.width*blockSize.height;
00560 
00561     nblocks = Size((winSize.width - blockSize.width)/blockStride.width + 1,
00562         (winSize.height - blockSize.height)/blockStride.height + 1);
00563     ncells = Size(blockSize.width/cellSize.width, blockSize.height/cellSize.height);
00564     blockHistogramSize = ncells.width*ncells.height*nbins;
00565 
00566     if( useCache )
00567     {
00568         Size cacheSize((grad.cols - blockSize.width)/cacheStride.width+1,
00569             (winSize.height/cacheStride.height)+1);
00570 
00571         blockCache.create(cacheSize.height, cacheSize.width*blockHistogramSize);
00572         blockCacheFlags.create(cacheSize);
00573 
00574         size_t cacheRows = blockCache.rows;
00575         ymaxCached.resize(cacheRows);
00576         for(size_t ii = 0; ii < cacheRows; ii++ )
00577             ymaxCached[ii] = -1;
00578     }
00579 
00580     Mat_<float> weights(blockSize);
00581     float sigma = (float)descriptor->getWinSigma();
00582     float scale = 1.f/(sigma*sigma*2);
00583 
00584     {
00585         AutoBuffer<float> di(blockSize.height), dj(blockSize.width);
00586         float* _di = (float*)di, *_dj = (float*)dj;
00587         float bh = blockSize.height * 0.5f, bw = blockSize.width * 0.5f;
00588 
00589         i = 0;
00590     #if CV_SSE2
00591         const int a[] = { 0, 1, 2, 3 };
00592         __m128i idx = _mm_loadu_si128((__m128i*)a);
00593         __m128 _bw = _mm_set1_ps(bw), _bh = _mm_set1_ps(bh);
00594         __m128i ifour = _mm_set1_epi32(4);
00595 
00596         for (; i <= blockSize.height - 4; i += 4)
00597         {
00598             __m128 t = _mm_sub_ps(_mm_cvtepi32_ps(idx), _bh);
00599             t = _mm_mul_ps(t, t);
00600             idx = _mm_add_epi32(idx, ifour);
00601             _mm_storeu_ps(_di + i, t);
00602         }
00603     #endif
00604         for ( ; i < blockSize.height; ++i)
00605         {
00606             _di[i] = i - bh;
00607             _di[i] *= _di[i];
00608         }
00609 
00610         j = 0;
00611     #if CV_SSE2
00612         idx = _mm_loadu_si128((__m128i*)a);
00613         for (; j <= blockSize.width - 4; j += 4)
00614         {
00615             __m128 t = _mm_sub_ps(_mm_cvtepi32_ps(idx), _bw);
00616             t = _mm_mul_ps(t, t);
00617             idx = _mm_add_epi32(idx, ifour);
00618             _mm_storeu_ps(_dj + j, t);
00619         }
00620     #endif
00621         for ( ; j < blockSize.width; ++j)
00622         {
00623             _dj[j] = j - bw;
00624             _dj[j] *= _dj[j];
00625         }
00626 
00627         for(i = 0; i < blockSize.height; i++)
00628             for(j = 0; j < blockSize.width; j++)
00629                 weights(i,j) = std::exp(-(_di[i] + _dj[j])*scale);
00630     }
00631 
00632     blockData.resize(nblocks.width*nblocks.height);
00633     pixData.resize(rawBlockSize*3);
00634 
00635     // Initialize 2 lookup tables, pixData & blockData.
00636     // Here is why:
00637     //
00638     // The detection algorithm runs in 4 nested loops (at each pyramid layer):
00639     //  loop over the windows within the input image
00640     //    loop over the blocks within each window
00641     //      loop over the cells within each block
00642     //        loop over the pixels in each cell
00643     //
00644     // As each of the loops runs over a 2-dimensional array,
00645     // we could get 8(!) nested loops in total, which is very-very slow.
00646     //
00647     // To speed the things up, we do the following:
00648     //   1. loop over windows is unrolled in the HOGDescriptor::{compute|detect} methods;
00649     //         inside we compute the current search window using getWindow() method.
00650     //         Yes, it involves some overhead (function call + couple of divisions),
00651     //         but it's tiny in fact.
00652     //   2. loop over the blocks is also unrolled. Inside we use pre-computed blockData[j]
00653     //         to set up gradient and histogram pointers.
00654     //   3. loops over cells and pixels in each cell are merged
00655     //       (since there is no overlap between cells, each pixel in the block is processed once)
00656     //      and also unrolled. Inside we use PixData[k] to access the gradient values and
00657     //      update the histogram
00658     //
00659 
00660     count1 = count2 = count4 = 0;
00661     for( j = 0; j < blockSize.width; j++ )
00662         for( i = 0; i < blockSize.height; i++ )
00663         {
00664             PixData* data = 0;
00665             float cellX = (j+0.5f)/cellSize.width - 0.5f;
00666             float cellY = (i+0.5f)/cellSize.height - 0.5f;
00667             int icellX0 = cvFloor(cellX);
00668             int icellY0 = cvFloor(cellY);
00669             int icellX1 = icellX0 + 1, icellY1 = icellY0 + 1;
00670             cellX -= icellX0;
00671             cellY -= icellY0;
00672 
00673             if( (unsigned)icellX0 < (unsigned)ncells.width &&
00674                (unsigned)icellX1 < (unsigned)ncells.width )
00675             {
00676                 if( (unsigned)icellY0 < (unsigned)ncells.height &&
00677                    (unsigned)icellY1 < (unsigned)ncells.height )
00678                 {
00679                     data = &pixData[rawBlockSize*2 + (count4++)];
00680                     data->histOfs[0] = (icellX0*ncells.height + icellY0)*nbins;
00681                     data->histWeights[0] = (1.f - cellX)*(1.f - cellY);
00682                     data->histOfs[1] = (icellX1*ncells.height + icellY0)*nbins;
00683                     data->histWeights[1] = cellX*(1.f - cellY);
00684                     data->histOfs[2] = (icellX0*ncells.height + icellY1)*nbins;
00685                     data->histWeights[2] = (1.f - cellX)*cellY;
00686                     data->histOfs[3] = (icellX1*ncells.height + icellY1)*nbins;
00687                     data->histWeights[3] = cellX*cellY;
00688                 }
00689                 else
00690                 {
00691                     data = &pixData[rawBlockSize + (count2++)];
00692                     if( (unsigned)icellY0 < (unsigned)ncells.height )
00693                     {
00694                         icellY1 = icellY0;
00695                         cellY = 1.f - cellY;
00696                     }
00697                     data->histOfs[0] = (icellX0*ncells.height + icellY1)*nbins;
00698                     data->histWeights[0] = (1.f - cellX)*cellY;
00699                     data->histOfs[1] = (icellX1*ncells.height + icellY1)*nbins;
00700                     data->histWeights[1] = cellX*cellY;
00701                     data->histOfs[2] = data->histOfs[3] = 0;
00702                     data->histWeights[2] = data->histWeights[3] = 0;
00703                 }
00704             }
00705             else
00706             {
00707                 if( (unsigned)icellX0 < (unsigned)ncells.width )
00708                 {
00709                     icellX1 = icellX0;
00710                     cellX = 1.f - cellX;
00711                 }
00712 
00713                 if( (unsigned)icellY0 < (unsigned)ncells.height &&
00714                    (unsigned)icellY1 < (unsigned)ncells.height )
00715                 {
00716                     data = &pixData[rawBlockSize + (count2++)];
00717                     data->histOfs[0] = (icellX1*ncells.height + icellY0)*nbins;
00718                     data->histWeights[0] = cellX*(1.f - cellY);
00719                     data->histOfs[1] = (icellX1*ncells.height + icellY1)*nbins;
00720                     data->histWeights[1] = cellX*cellY;
00721                     data->histOfs[2] = data->histOfs[3] = 0;
00722                     data->histWeights[2] = data->histWeights[3] = 0;
00723                 }
00724                 else
00725                 {
00726                     data = &pixData[count1++];
00727                     if( (unsigned)icellY0 < (unsigned)ncells.height )
00728                     {
00729                         icellY1 = icellY0;
00730                         cellY = 1.f - cellY;
00731                     }
00732                     data->histOfs[0] = (icellX1*ncells.height + icellY1)*nbins;
00733                     data->histWeights[0] = cellX*cellY;
00734                     data->histOfs[1] = data->histOfs[2] = data->histOfs[3] = 0;
00735                     data->histWeights[1] = data->histWeights[2] = data->histWeights[3] = 0;
00736                 }
00737             }
00738             data->gradOfs = (grad.cols*i + j)*2;
00739             data->qangleOfs = (qangle.cols*i + j)*2;
00740             data->gradWeight = weights(i,j);
00741         }
00742 
00743     assert( count1 + count2 + count4 == rawBlockSize );
00744     // defragment pixData
00745     for( j = 0; j < count2; j++ )
00746         pixData[j + count1] = pixData[j + rawBlockSize];
00747     for( j = 0; j < count4; j++ )
00748         pixData[j + count1 + count2] = pixData[j + rawBlockSize*2];
00749     count2 += count1;
00750     count4 += count2;
00751 
00752     // initialize blockData
00753     for( j = 0; j < nblocks.width; j++ )
00754         for( i = 0; i < nblocks.height; i++ )
00755         {
00756             BlockData& data = blockData[j*nblocks.height + i];
00757             data.histOfs = (j*nblocks.height + i)*blockHistogramSize;
00758             data.imgOffset = Point(j*blockStride.width,i*blockStride.height);
00759         }
00760 }
00761 
00762 const float* HOGCache::getBlock(Point pt, float* buf)
00763 {
00764     float* blockHist = buf;
00765     assert(descriptor != 0);
00766 
00767 //    Size blockSize = descriptor->blockSize;
00768     pt += imgoffset;
00769 
00770 //    CV_Assert( (unsigned)pt.x <= (unsigned)(grad.cols - blockSize.width) &&
00771 //        (unsigned)pt.y <= (unsigned)(grad.rows - blockSize.height) );
00772 
00773     if( useCache )
00774     {
00775         CV_Assert( pt.x % cacheStride.width == 0 &&
00776                    pt.y % cacheStride.height == 0 );
00777         Point cacheIdx(pt.x/cacheStride.width,
00778                        (pt.y/cacheStride.height) % blockCache.rows);
00779         if( pt.y != ymaxCached[cacheIdx.y] )
00780         {
00781             Mat_<uchar> cacheRow = blockCacheFlags.row(cacheIdx.y);
00782             cacheRow = (uchar)0;
00783             ymaxCached[cacheIdx.y] = pt.y;
00784         }
00785 
00786         blockHist = &blockCache[cacheIdx.y][cacheIdx.x*blockHistogramSize];
00787         uchar& computedFlag = blockCacheFlags(cacheIdx.y, cacheIdx.x);
00788         if( computedFlag != 0 )
00789             return blockHist;
00790         computedFlag = (uchar)1; // set it at once, before actual computing
00791     }
00792 
00793     int k, C1 = count1, C2 = count2, C4 = count4;
00794     const float* gradPtr = grad.ptr<float>(pt.y) + pt.x*2;
00795     const uchar* qanglePtr = qangle.ptr(pt.y) + pt.x*2;
00796 
00797 //    CV_Assert( blockHist != 0 );
00798     memset(blockHist, 0, sizeof(float) * blockHistogramSize);
00799 
00800     const PixData* _pixData = &pixData[0];
00801 
00802     for( k = 0; k < C1; k++ )
00803     {
00804         const PixData& pk = _pixData[k];
00805         const float* const a = gradPtr + pk.gradOfs;
00806         float w = pk.gradWeight*pk.histWeights[0];
00807         const uchar* h = qanglePtr + pk.qangleOfs;
00808         int h0 = h[0], h1 = h[1];
00809 
00810         float* hist = blockHist + pk.histOfs[0];
00811         float t0 = hist[h0] + a[0]*w;
00812         float t1 = hist[h1] + a[1]*w;
00813         hist[h0] = t0; hist[h1] = t1;
00814     }
00815 
00816 #if CV_SSE2
00817     float hist0[4], hist1[4];
00818     for( ; k < C2; k++ )
00819     {
00820         const PixData& pk = _pixData[k];
00821         const float* const a = gradPtr + pk.gradOfs;
00822         const uchar* const h = qanglePtr + pk.qangleOfs;
00823         int h0 = h[0], h1 = h[1];
00824 
00825         __m128 _a0 = _mm_set1_ps(a[0]), _a1 = _mm_set1_ps(a[1]);
00826         __m128 _w = _mm_mul_ps(_mm_set1_ps(pk.gradWeight), _mm_loadu_ps(pk.histWeights));
00827         __m128 _t0 = _mm_mul_ps(_a0, _w), _t1 = _mm_mul_ps(_a1, _w);
00828 
00829         _mm_storeu_ps(hist0, _t0);
00830         _mm_storeu_ps(hist1, _t1);
00831 
00832         float* hist = blockHist + pk.histOfs[0];
00833         float t0 = hist[h0] + hist0[0];
00834         float t1 = hist[h1] + hist1[0];
00835         hist[h0] = t0; hist[h1] = t1;
00836 
00837         hist = blockHist + pk.histOfs[1];
00838         t0 = hist[h0] + hist0[1];
00839         t1 = hist[h1] + hist1[1];
00840         hist[h0] = t0; hist[h1] = t1;
00841     }
00842 #else
00843     for( ; k < C2; k++ )
00844     {
00845         const PixData& pk = _pixData[k];
00846         const float* const a = gradPtr + pk.gradOfs;
00847         float w, t0, t1, a0 = a[0], a1 = a[1];
00848         const uchar* const h = qanglePtr + pk.qangleOfs;
00849         int h0 = h[0], h1 = h[1];
00850 
00851         float* hist = blockHist + pk.histOfs[0];
00852         w = pk.gradWeight*pk.histWeights[0];
00853         t0 = hist[h0] + a0*w;
00854         t1 = hist[h1] + a1*w;
00855         hist[h0] = t0; hist[h1] = t1;
00856 
00857         hist = blockHist + pk.histOfs[1];
00858         w = pk.gradWeight*pk.histWeights[1];
00859         t0 = hist[h0] + a0*w;
00860         t1 = hist[h1] + a1*w;
00861         hist[h0] = t0; hist[h1] = t1;
00862     }
00863 #endif
00864 
00865 #if CV_SSE2
00866     for( ; k < C4; k++ )
00867     {
00868         const PixData& pk = _pixData[k];
00869         const float* const a = gradPtr + pk.gradOfs;
00870         const uchar* const h = qanglePtr + pk.qangleOfs;
00871         int h0 = h[0], h1 = h[1];
00872 
00873         __m128 _a0 = _mm_set1_ps(a[0]), _a1 = _mm_set1_ps(a[1]);
00874         __m128 _w = _mm_mul_ps(_mm_set1_ps(pk.gradWeight), _mm_loadu_ps(pk.histWeights));
00875         __m128 _t0 = _mm_mul_ps(_a0, _w), _t1 = _mm_mul_ps(_a1, _w);
00876 
00877         _mm_storeu_ps(hist0, _t0);
00878         _mm_storeu_ps(hist1, _t1);
00879 
00880         float* hist = blockHist + pk.histOfs[0];
00881         float t0 = hist[h0] + hist0[0];
00882         float t1 = hist[h1] + hist1[0];
00883         hist[h0] = t0; hist[h1] = t1;
00884 
00885         hist = blockHist + pk.histOfs[1];
00886         t0 = hist[h0] + hist0[1];
00887         t1 = hist[h1] + hist1[1];
00888         hist[h0] = t0; hist[h1] = t1;
00889 
00890         hist = blockHist + pk.histOfs[2];
00891         t0 = hist[h0] + hist0[2];
00892         t1 = hist[h1] + hist1[2];
00893         hist[h0] = t0; hist[h1] = t1;
00894 
00895         hist = blockHist + pk.histOfs[3];
00896         t0 = hist[h0] + hist0[3];
00897         t1 = hist[h1] + hist1[3];
00898         hist[h0] = t0; hist[h1] = t1;
00899 
00900 //        __m128 _hist0 = _mm_set_ps((blockHist + pk.histOfs[3])[h0], (blockHist + pk.histOfs[2])[h0],
00901 //            (blockHist + pk.histOfs[1])[h0], (blockHist + pk.histOfs[0])[h0]);
00902 //        __m128 _hist1 = _mm_set_ps((blockHist + pk.histOfs[3])[h1], (blockHist + pk.histOfs[2])[h1],
00903 //            (blockHist + pk.histOfs[1])[h1], (blockHist + pk.histOfs[0])[h1]);
00904 //
00905 //        _hist0 = _mm_add_ps(_t0, _hist0);
00906 //        _hist1 = _mm_add_ps(_t1, _hist1);
00907 //
00908 //        _mm_storeu_ps(hist0, _hist0);
00909 //        _mm_storeu_ps(hist1, _hist1);
00910 //
00911 //        (pk.histOfs[0] + blockHist)[h0] = hist0[0];
00912 //        (pk.histOfs[1] + blockHist)[h0] = hist0[1];
00913 //        (pk.histOfs[2] + blockHist)[h0] = hist0[2];
00914 //        (pk.histOfs[3] + blockHist)[h0] = hist0[3];
00915 //
00916 //        (pk.histOfs[0] + blockHist)[h1] = hist1[0];
00917 //        (pk.histOfs[1] + blockHist)[h1] = hist1[1];
00918 //        (pk.histOfs[2] + blockHist)[h1] = hist1[2];
00919 //        (pk.histOfs[3] + blockHist)[h1] = hist1[3];
00920     }
00921 #else
00922     for( ; k < C4; k++ )
00923     {
00924         const PixData& pk = _pixData[k];
00925         const float* a = gradPtr + pk.gradOfs;
00926         float w, t0, t1, a0 = a[0], a1 = a[1];
00927         const uchar* h = qanglePtr + pk.qangleOfs;
00928         int h0 = h[0], h1 = h[1];
00929 
00930         float* hist = blockHist + pk.histOfs[0];
00931         w = pk.gradWeight*pk.histWeights[0];
00932         t0 = hist[h0] + a0*w;
00933         t1 = hist[h1] + a1*w;
00934         hist[h0] = t0; hist[h1] = t1;
00935 
00936         hist = blockHist + pk.histOfs[1];
00937         w = pk.gradWeight*pk.histWeights[1];
00938         t0 = hist[h0] + a0*w;
00939         t1 = hist[h1] + a1*w;
00940         hist[h0] = t0; hist[h1] = t1;
00941 
00942         hist = blockHist + pk.histOfs[2];
00943         w = pk.gradWeight*pk.histWeights[2];
00944         t0 = hist[h0] + a0*w;
00945         t1 = hist[h1] + a1*w;
00946         hist[h0] = t0; hist[h1] = t1;
00947 
00948         hist = blockHist + pk.histOfs[3];
00949         w = pk.gradWeight*pk.histWeights[3];
00950         t0 = hist[h0] + a0*w;
00951         t1 = hist[h1] + a1*w;
00952         hist[h0] = t0; hist[h1] = t1;
00953     }
00954 #endif
00955 
00956     normalizeBlockHistogram(blockHist);
00957 
00958     return blockHist;
00959 }
00960 
00961 void HOGCache::normalizeBlockHistogram(float* _hist) const
00962 {
00963     float* hist = &_hist[0], sum = 0.0f, partSum[4];
00964     size_t i = 0, sz = blockHistogramSize;
00965 
00966 #if CV_SSE2
00967     __m128 p0 = _mm_loadu_ps(hist);
00968     __m128 s = _mm_mul_ps(p0, p0);
00969 
00970     for (i = 4; i <= sz - 4; i += 4)
00971     {
00972         p0 = _mm_loadu_ps(hist + i);
00973         s = _mm_add_ps(s, _mm_mul_ps(p0, p0));
00974     }
00975     _mm_storeu_ps(partSum, s);
00976 #else
00977     partSum[0] = 0.0f;
00978     partSum[1] = 0.0f;
00979     partSum[2] = 0.0f;
00980     partSum[3] = 0.0f;
00981     for ( ; i <= sz - 4; i += 4)
00982     {
00983         partSum[0] += hist[i] * hist[i];
00984         partSum[1] += hist[i+1] * hist[i+1];
00985         partSum[2] += hist[i+2] * hist[i+2];
00986         partSum[3] += hist[i+3] * hist[i+3];
00987     }
00988 #endif
00989     float t0 = partSum[0] + partSum[1];
00990     float t1 = partSum[2] + partSum[3];
00991     sum = t0 + t1;
00992     for ( ; i < sz; ++i)
00993         sum += hist[i]*hist[i];
00994 
00995     float scale = 1.f/(std::sqrt(sum)+sz*0.1f), thresh = (float)descriptor->L2HysThreshold;
00996     i = 0, sum = 0.0f;
00997 
00998 #if CV_SSE2
00999     __m128 _scale = _mm_set1_ps(scale);
01000     static __m128 _threshold = _mm_set1_ps(thresh);
01001 
01002     __m128 p = _mm_mul_ps(_scale, _mm_loadu_ps(hist));
01003     p = _mm_min_ps(p, _threshold);
01004     s = _mm_mul_ps(p, p);
01005     _mm_storeu_ps(hist, p);
01006 
01007     for(i = 4 ; i <= sz - 4; i += 4)
01008     {
01009         p = _mm_loadu_ps(hist + i);
01010         p = _mm_mul_ps(p, _scale);
01011         p = _mm_min_ps(p, _threshold);
01012         s = _mm_add_ps(s, _mm_mul_ps(p, p));
01013         _mm_storeu_ps(hist + i, p);
01014     }
01015 
01016     _mm_storeu_ps(partSum, s);
01017 #else
01018     partSum[0] = 0.0f;
01019     partSum[1] = 0.0f;
01020     partSum[2] = 0.0f;
01021     partSum[3] = 0.0f;
01022     for( ; i <= sz - 4; i += 4)
01023     {
01024         hist[i] = std::min(hist[i]*scale, thresh);
01025         hist[i+1] = std::min(hist[i+1]*scale, thresh);
01026         hist[i+2] = std::min(hist[i+2]*scale, thresh);
01027         hist[i+3] = std::min(hist[i+3]*scale, thresh);
01028         partSum[0] += hist[i]*hist[i];
01029         partSum[1] += hist[i+1]*hist[i+1];
01030         partSum[2] += hist[i+2]*hist[i+2];
01031         partSum[3] += hist[i+3]*hist[i+3];
01032     }
01033 #endif
01034     t0 = partSum[0] + partSum[1];
01035     t1 = partSum[2] + partSum[3];
01036     sum = t0 + t1;
01037     for( ; i < sz; ++i)
01038     {
01039         hist[i] = std::min(hist[i]*scale, thresh);
01040         sum += hist[i]*hist[i];
01041     }
01042 
01043     scale = 1.f/(std::sqrt(sum)+1e-3f), i = 0;
01044 #if CV_SSE2
01045     __m128 _scale2 = _mm_set1_ps(scale);
01046     for ( ; i <= sz - 4; i += 4)
01047     {
01048         __m128 t = _mm_mul_ps(_scale2, _mm_loadu_ps(hist + i));
01049         _mm_storeu_ps(hist + i, t);
01050     }
01051 #endif
01052     for ( ; i < sz; ++i)
01053         hist[i] *= scale;
01054 }
01055 
01056 Size HOGCache::windowsInImage(const Size& imageSize, const Size& winStride) const
01057 {
01058     return Size((imageSize.width - winSize.width)/winStride.width + 1,
01059         (imageSize.height - winSize.height)/winStride.height + 1);
01060 }
01061 
01062 Rect HOGCache::getWindow(const Size& imageSize, const Size& winStride, int idx) const
01063 {
01064     int nwindowsX = (imageSize.width - winSize.width)/winStride.width + 1;
01065     int y = idx / nwindowsX;
01066     int x = idx - nwindowsX*y;
01067     return Rect( x*winStride.width, y*winStride.height, winSize.width, winSize.height );
01068 }
01069 
01070 static inline int gcd(int a, int b)
01071 {
01072     if( a < b )
01073         std::swap(a, b);
01074     while( b > 0 )
01075     {
01076         int r = a % b;
01077         a = b;
01078         b = r;
01079     }
01080     return a;
01081 }
01082 
01083 #ifdef HAVE_OPENCL
01084 
01085 static bool ocl_compute_gradients_8UC1(int height, int width, InputArray _img, float angle_scale,
01086                                        UMat grad, UMat qangle, bool correct_gamma, int nbins)
01087 {
01088     ocl::Kernel k("compute_gradients_8UC1_kernel", ocl::objdetect::objdetect_hog_oclsrc);
01089     if(k.empty())
01090         return false;
01091 
01092     UMat img = _img.getUMat();
01093 
01094     size_t localThreads[3] = { NTHREADS, 1, 1 };
01095     size_t globalThreads[3] = { (size_t)width, (size_t)height, 1 };
01096     char correctGamma = (correct_gamma) ? 1 : 0;
01097     int grad_quadstep = (int)grad.step >> 3;
01098     int qangle_elem_size = CV_ELEM_SIZE1(qangle.type());
01099     int qangle_step = (int)qangle.step / (2 * qangle_elem_size);
01100 
01101     int idx = 0;
01102     idx = k.set(idx, height);
01103     idx = k.set(idx, width);
01104     idx = k.set(idx, (int)img.step1());
01105     idx = k.set(idx, grad_quadstep);
01106     idx = k.set(idx, qangle_step);
01107     idx = k.set(idx, ocl::KernelArg::PtrReadOnly(img));
01108     idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(grad));
01109     idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(qangle));
01110     idx = k.set(idx, angle_scale);
01111     idx = k.set(idx, correctGamma);
01112     idx = k.set(idx, nbins);
01113 
01114     return k.run(2, globalThreads, localThreads, false);
01115 }
01116 
01117 static bool ocl_computeGradient(InputArray img, UMat grad, UMat qangle, int nbins, Size effect_size, bool gamma_correction, bool signedGradient)
01118 {
01119     float angleScale = signedGradient ? (float)(nbins/(2.0*CV_PI)) : (float)(nbins/CV_PI);
01120 
01121     return ocl_compute_gradients_8UC1(effect_size.height, effect_size.width, img,
01122          angleScale, grad, qangle, gamma_correction, nbins);
01123 }
01124 
01125 #define CELL_WIDTH 8
01126 #define CELL_HEIGHT 8
01127 #define CELLS_PER_BLOCK_X 2
01128 #define CELLS_PER_BLOCK_Y 2
01129 
01130 static bool ocl_compute_hists(int nbins, int block_stride_x, int block_stride_y, int height, int width,
01131                               UMat grad, UMat qangle, UMat gauss_w_lut, UMat block_hists, size_t block_hist_size)
01132 {
01133     ocl::Kernel k("compute_hists_lut_kernel", ocl::objdetect::objdetect_hog_oclsrc);
01134     if(k.empty())
01135         return false;
01136     bool is_cpu = cv::ocl::Device::getDefault().type() == cv::ocl::Device::TYPE_CPU;
01137     cv::String opts;
01138     if(is_cpu)
01139        opts = "-D CPU ";
01140     else
01141         opts = cv::format("-D WAVE_SIZE=%d", k.preferedWorkGroupSizeMultiple());
01142     k.create("compute_hists_lut_kernel", ocl::objdetect::objdetect_hog_oclsrc, opts);
01143     if(k.empty())
01144         return false;
01145 
01146     int img_block_width = (width - CELLS_PER_BLOCK_X * CELL_WIDTH + block_stride_x)/block_stride_x;
01147     int img_block_height = (height - CELLS_PER_BLOCK_Y * CELL_HEIGHT + block_stride_y)/block_stride_y;
01148     int blocks_total = img_block_width * img_block_height;
01149 
01150     int qangle_elem_size = CV_ELEM_SIZE1(qangle.type());
01151     int grad_quadstep = (int)grad.step >> 2;
01152     int qangle_step = (int)qangle.step / qangle_elem_size;
01153 
01154     int blocks_in_group = 4;
01155     size_t localThreads[3] = { (size_t)blocks_in_group * 24, 2, 1 };
01156     size_t globalThreads[3] = {((img_block_width * img_block_height + blocks_in_group - 1)/blocks_in_group) * localThreads[0], 2, 1 };
01157 
01158     int hists_size = (nbins * CELLS_PER_BLOCK_X * CELLS_PER_BLOCK_Y * 12) * sizeof(float);
01159     int final_hists_size = (nbins * CELLS_PER_BLOCK_X * CELLS_PER_BLOCK_Y) * sizeof(float);
01160 
01161     int smem = (hists_size + final_hists_size) * blocks_in_group;
01162 
01163     int idx = 0;
01164     idx = k.set(idx, block_stride_x);
01165     idx = k.set(idx, block_stride_y);
01166     idx = k.set(idx, nbins);
01167     idx = k.set(idx, (int)block_hist_size);
01168     idx = k.set(idx, img_block_width);
01169     idx = k.set(idx, blocks_in_group);
01170     idx = k.set(idx, blocks_total);
01171     idx = k.set(idx, grad_quadstep);
01172     idx = k.set(idx, qangle_step);
01173     idx = k.set(idx, ocl::KernelArg::PtrReadOnly(grad));
01174     idx = k.set(idx, ocl::KernelArg::PtrReadOnly(qangle));
01175     idx = k.set(idx, ocl::KernelArg::PtrReadOnly(gauss_w_lut));
01176     idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(block_hists));
01177     idx = k.set(idx, (void*)NULL, (size_t)smem);
01178 
01179     return k.run(2, globalThreads, localThreads, false);
01180 }
01181 
01182 static int power_2up(unsigned int n)
01183 {
01184     for(unsigned int i = 1; i<=1024; i<<=1)
01185         if(n < i)
01186             return i;
01187     return -1; // Input is too big
01188 }
01189 
01190 static bool ocl_normalize_hists(int nbins, int block_stride_x, int block_stride_y,
01191                                 int height, int width, UMat block_hists, float threshold)
01192 {
01193     int block_hist_size = nbins * CELLS_PER_BLOCK_X * CELLS_PER_BLOCK_Y;
01194     int img_block_width = (width - CELLS_PER_BLOCK_X * CELL_WIDTH + block_stride_x)
01195         / block_stride_x;
01196     int img_block_height = (height - CELLS_PER_BLOCK_Y * CELL_HEIGHT + block_stride_y)
01197         / block_stride_y;
01198     int nthreads;
01199     size_t globalThreads[3] = { 1, 1, 1  };
01200     size_t localThreads[3] = { 1, 1, 1  };
01201 
01202     int idx = 0;
01203     bool is_cpu = cv::ocl::Device::getDefault().type() == cv::ocl::Device::TYPE_CPU;
01204     cv::String opts;
01205     ocl::Kernel k;
01206     if ( nbins == 9 )
01207     {
01208         k.create("normalize_hists_36_kernel", ocl::objdetect::objdetect_hog_oclsrc, "");
01209         if(k.empty())
01210             return false;
01211         if(is_cpu)
01212            opts = "-D CPU ";
01213         else
01214             opts = cv::format("-D WAVE_SIZE=%d", k.preferedWorkGroupSizeMultiple());
01215         k.create("normalize_hists_36_kernel", ocl::objdetect::objdetect_hog_oclsrc, opts);
01216         if(k.empty())
01217             return false;
01218 
01219         int blocks_in_group = NTHREADS / block_hist_size;
01220         nthreads = blocks_in_group * block_hist_size;
01221         int num_groups = (img_block_width * img_block_height + blocks_in_group - 1)/blocks_in_group;
01222         globalThreads[0] = nthreads * num_groups;
01223         localThreads[0] = nthreads;
01224     }
01225     else
01226     {
01227         k.create("normalize_hists_kernel", ocl::objdetect::objdetect_hog_oclsrc, "-D WAVE_SIZE=32");
01228         if(k.empty())
01229             return false;
01230         if(is_cpu)
01231            opts = "-D CPU ";
01232         else
01233             opts = cv::format("-D WAVE_SIZE=%d", k.preferedWorkGroupSizeMultiple());
01234         k.create("normalize_hists_kernel", ocl::objdetect::objdetect_hog_oclsrc, opts);
01235         if(k.empty())
01236             return false;
01237 
01238         nthreads = power_2up(block_hist_size);
01239         globalThreads[0] = img_block_width * nthreads;
01240         globalThreads[1] = img_block_height;
01241         localThreads[0] = nthreads;
01242 
01243         if ((nthreads < 32) || (nthreads > 512) )
01244             return false;
01245 
01246         idx = k.set(idx, nthreads);
01247         idx = k.set(idx, block_hist_size);
01248         idx = k.set(idx, img_block_width);
01249     }
01250     idx = k.set(idx, ocl::KernelArg::PtrReadWrite(block_hists));
01251     idx = k.set(idx, threshold);
01252     idx = k.set(idx, (void*)NULL,  nthreads * sizeof(float));
01253 
01254     return k.run(2, globalThreads, localThreads, false);
01255 }
01256 
01257 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,
01258                                        int height, int width, UMat block_hists, UMat descriptors,
01259                                        int block_hist_size, int descr_size, int descr_width)
01260 {
01261     ocl::Kernel k("extract_descrs_by_rows_kernel", ocl::objdetect::objdetect_hog_oclsrc);
01262     if(k.empty())
01263         return false;
01264 
01265     int win_block_stride_x = win_stride_x / block_stride_x;
01266     int win_block_stride_y = win_stride_y / block_stride_y;
01267     int img_win_width = (width - win_width + win_stride_x) / win_stride_x;
01268     int img_win_height = (height - win_height + win_stride_y) / win_stride_y;
01269     int img_block_width = (width - CELLS_PER_BLOCK_X * CELL_WIDTH + block_stride_x) /
01270         block_stride_x;
01271 
01272     int descriptors_quadstep = (int)descriptors.step >> 2;
01273 
01274     size_t globalThreads[3] = { (size_t)img_win_width * NTHREADS, (size_t)img_win_height, 1 };
01275     size_t localThreads[3] = { NTHREADS, 1, 1 };
01276 
01277     int idx = 0;
01278     idx = k.set(idx, block_hist_size);
01279     idx = k.set(idx, descriptors_quadstep);
01280     idx = k.set(idx, descr_size);
01281     idx = k.set(idx, descr_width);
01282     idx = k.set(idx, img_block_width);
01283     idx = k.set(idx, win_block_stride_x);
01284     idx = k.set(idx, win_block_stride_y);
01285     idx = k.set(idx, ocl::KernelArg::PtrReadOnly(block_hists));
01286     idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(descriptors));
01287 
01288     return k.run(2, globalThreads, localThreads, false);
01289 }
01290 
01291 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,
01292                                        int height, int width, UMat block_hists, UMat descriptors,
01293                                        int block_hist_size, int descr_size, int nblocks_win_x, int nblocks_win_y)
01294 {
01295     ocl::Kernel k("extract_descrs_by_cols_kernel", ocl::objdetect::objdetect_hog_oclsrc);
01296     if(k.empty())
01297         return false;
01298 
01299     int win_block_stride_x = win_stride_x / block_stride_x;
01300     int win_block_stride_y = win_stride_y / block_stride_y;
01301     int img_win_width = (width - win_width + win_stride_x) / win_stride_x;
01302     int img_win_height = (height - win_height + win_stride_y) / win_stride_y;
01303     int img_block_width = (width - CELLS_PER_BLOCK_X * CELL_WIDTH + block_stride_x) /
01304         block_stride_x;
01305 
01306     int descriptors_quadstep = (int)descriptors.step >> 2;
01307 
01308     size_t globalThreads[3] = { (size_t)img_win_width * NTHREADS, (size_t)img_win_height, 1 };
01309     size_t localThreads[3] = { NTHREADS, 1, 1 };
01310 
01311     int idx = 0;
01312     idx = k.set(idx, block_hist_size);
01313     idx = k.set(idx, descriptors_quadstep);
01314     idx = k.set(idx, descr_size);
01315     idx = k.set(idx, nblocks_win_x);
01316     idx = k.set(idx, nblocks_win_y);
01317     idx = k.set(idx, img_block_width);
01318     idx = k.set(idx, win_block_stride_x);
01319     idx = k.set(idx, win_block_stride_y);
01320     idx = k.set(idx, ocl::KernelArg::PtrReadOnly(block_hists));
01321     idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(descriptors));
01322 
01323     return k.run(2, globalThreads, localThreads, false);
01324 }
01325 
01326 static bool ocl_compute(InputArray _img, Size win_stride, std::vector<float>& _descriptors, int descr_format, Size blockSize,
01327                         Size cellSize, int nbins, Size blockStride, Size winSize, float sigma, bool gammaCorrection, double L2HysThreshold, bool signedGradient)
01328 {
01329     Size imgSize = _img.size();
01330     Size effect_size = imgSize;
01331 
01332     UMat grad(imgSize, CV_32FC2);
01333     int qangle_type = ocl::Device::getDefault().isIntel() ? CV_32SC2 : CV_8UC2;
01334     UMat qangle(imgSize, qangle_type);
01335 
01336     const size_t block_hist_size = getBlockHistogramSize(blockSize, cellSize, nbins);
01337     const Size blocks_per_img = numPartsWithin(imgSize, blockSize, blockStride);
01338     UMat block_hists(1, static_cast<int>(block_hist_size * blocks_per_img.area()) + 256, CV_32F);
01339 
01340     Size wins_per_img = numPartsWithin(imgSize, winSize, win_stride);
01341     UMat labels(1, wins_per_img.area(), CV_8U);
01342 
01343     float scale = 1.f / (2.f * sigma * sigma);
01344     Mat gaussian_lut(1, 512, CV_32FC1);
01345     int idx = 0;
01346     for(int i=-8; i<8; i++)
01347         for(int j=-8; j<8; j++)
01348             gaussian_lut.at<float>(idx++) = std::exp(-(j * j + i * i) * scale);
01349     for(int i=-8; i<8; i++)
01350         for(int j=-8; j<8; j++)
01351             gaussian_lut.at<float>(idx++) = (8.f - fabs(j + 0.5f)) * (8.f - fabs(i + 0.5f)) / 64.f;
01352 
01353     if(!ocl_computeGradient(_img, grad, qangle, nbins, effect_size, gammaCorrection, signedGradient))
01354         return false;
01355 
01356     UMat gauss_w_lut;
01357     gaussian_lut.copyTo(gauss_w_lut);
01358     if(!ocl_compute_hists(nbins, blockStride.width, blockStride.height, effect_size.height,
01359         effect_size.width, grad, qangle, gauss_w_lut, block_hists, block_hist_size))
01360         return false;
01361 
01362     if(!ocl_normalize_hists(nbins, blockStride.width, blockStride.height, effect_size.height,
01363         effect_size.width, block_hists, (float)L2HysThreshold))
01364         return false;
01365 
01366     Size blocks_per_win = numPartsWithin(winSize, blockSize, blockStride);
01367     wins_per_img = numPartsWithin(effect_size, winSize, win_stride);
01368 
01369     int descr_size = blocks_per_win.area()*(int)block_hist_size;
01370     int descr_width = (int)block_hist_size*blocks_per_win.width;
01371 
01372     UMat descriptors(wins_per_img.area(), static_cast<int>(blocks_per_win.area() * block_hist_size), CV_32F);
01373     switch (descr_format)
01374     {
01375     case DESCR_FORMAT_ROW_BY_ROW:
01376         if(!ocl_extract_descrs_by_rows(winSize.height, winSize.width,
01377             blockStride.height, blockStride.width, win_stride.height, win_stride.width, effect_size.height,
01378             effect_size.width, block_hists, descriptors, (int)block_hist_size, descr_size, descr_width))
01379             return false;
01380         break;
01381     case DESCR_FORMAT_COL_BY_COL:
01382         if(!ocl_extract_descrs_by_cols(winSize.height, winSize.width,
01383             blockStride.height, blockStride.width, win_stride.height, win_stride.width, effect_size.height, effect_size.width,
01384             block_hists, descriptors, (int)block_hist_size, descr_size, blocks_per_win.width, blocks_per_win.height))
01385             return false;
01386         break;
01387     default:
01388         return false;
01389     }
01390     descriptors.reshape(1, (int)descriptors.total()).getMat(ACCESS_READ).copyTo(_descriptors);
01391     return true;
01392 }
01393 #endif //HAVE_OPENCL
01394 
01395 void HOGDescriptor::compute(InputArray _img, std::vector<float>& descriptors,
01396     Size winStride, Size padding, const std::vector<Point>& locations) const
01397 {
01398     if( winStride == Size() )
01399         winStride = cellSize;
01400     Size cacheStride(gcd(winStride.width, blockStride.width),
01401                      gcd(winStride.height, blockStride.height));
01402 
01403     Size imgSize = _img.size();
01404 
01405     size_t nwindows = locations.size();
01406     padding.width = (int)alignSize(std::max(padding.width, 0), cacheStride.width);
01407     padding.height = (int)alignSize(std::max(padding.height, 0), cacheStride.height);
01408     Size paddedImgSize(imgSize.width + padding.width*2, imgSize.height + padding.height*2);
01409 
01410 #ifdef HAVE_OPENCL
01411     CV_OCL_RUN(_img.dims() <= 2 && _img.type() == CV_8UC1 && _img.isUMat(),
01412         ocl_compute(_img, winStride, descriptors, DESCR_FORMAT_COL_BY_COL, blockSize,
01413         cellSize, nbins, blockStride, winSize, (float)getWinSigma(), gammaCorrection, L2HysThreshold, signedGradient))
01414 #endif 
01415 
01416     Mat img = _img.getMat();
01417     HOGCache cache(this, img, padding, padding, nwindows == 0, cacheStride);
01418 
01419     if( !nwindows )
01420         nwindows = cache.windowsInImage(paddedImgSize, winStride).area();
01421 
01422     const HOGCache::BlockData* blockData = &cache.blockData[0];
01423 
01424     int nblocks = cache.nblocks.area();
01425     int blockHistogramSize = cache.blockHistogramSize;
01426     size_t dsize = getDescriptorSize();
01427     descriptors.resize(dsize*nwindows);
01428 
01429     // for each window
01430     for( size_t i = 0; i < nwindows; i++ )
01431     {
01432         float* descriptor = &descriptors[i*dsize];
01433 
01434         Point pt0;
01435         if( !locations.empty() )
01436         {
01437             pt0 = locations[i];
01438             if( pt0.x < -padding.width || pt0.x > img.cols + padding.width - winSize.width ||
01439                 pt0.y < -padding.height || pt0.y > img.rows + padding.height - winSize.height )
01440                 continue;
01441         }
01442         else
01443         {
01444             pt0 = cache.getWindow(paddedImgSize, winStride, (int)i).tl() - Point(padding);
01445 //            CV_Assert(pt0.x % cacheStride.width == 0 && pt0.y % cacheStride.height == 0);
01446         }
01447 
01448         for( int j = 0; j < nblocks; j++ )
01449         {
01450             const HOGCache::BlockData& bj = blockData[j];
01451             Point pt = pt0 + bj.imgOffset;
01452 
01453             float* dst = descriptor + bj.histOfs;
01454             const float* src = cache.getBlock(pt, dst);
01455             if( src != dst )
01456                 memcpy(dst, src, blockHistogramSize * sizeof(float));
01457         }
01458     }
01459 }
01460 
01461 void HOGDescriptor::detect(const Mat& img,
01462     std::vector<Point>& hits, std::vector<double>& weights, double hitThreshold,
01463     Size winStride, Size padding, const std::vector<Point>& locations) const
01464 {
01465     hits.clear();
01466     weights.clear();
01467     if( svmDetector.empty() )
01468         return;
01469 
01470     if( winStride == Size() )
01471         winStride = cellSize;
01472     Size cacheStride(gcd(winStride.width, blockStride.width),
01473         gcd(winStride.height, blockStride.height));
01474 
01475     size_t nwindows = locations.size();
01476     padding.width = (int)alignSize(std::max(padding.width, 0), cacheStride.width);
01477     padding.height = (int)alignSize(std::max(padding.height, 0), cacheStride.height);
01478     Size paddedImgSize(img.cols + padding.width*2, img.rows + padding.height*2);
01479 
01480     HOGCache cache(this, img, padding, padding, nwindows == 0, cacheStride);
01481 
01482     if( !nwindows )
01483         nwindows = cache.windowsInImage(paddedImgSize, winStride).area();
01484 
01485     const HOGCache::BlockData* blockData = &cache.blockData[0];
01486 
01487     int nblocks = cache.nblocks.area();
01488     int blockHistogramSize = cache.blockHistogramSize;
01489     size_t dsize = getDescriptorSize();
01490 
01491     double rho = svmDetector.size() > dsize ? svmDetector[dsize] : 0;
01492     std::vector<float> blockHist(blockHistogramSize);
01493 
01494 #if CV_SSE2
01495     float partSum[4];
01496 #endif
01497 
01498     for( size_t i = 0; i < nwindows; i++ )
01499     {
01500         Point pt0;
01501         if( !locations.empty() )
01502         {
01503             pt0 = locations[i];
01504             if( pt0.x < -padding.width || pt0.x > img.cols + padding.width - winSize.width ||
01505                     pt0.y < -padding.height || pt0.y > img.rows + padding.height - winSize.height )
01506                 continue;
01507         }
01508         else
01509         {
01510             pt0 = cache.getWindow(paddedImgSize, winStride, (int)i).tl() - Point(padding);
01511             CV_Assert(pt0.x % cacheStride.width == 0 && pt0.y % cacheStride.height == 0);
01512         }
01513         double s = rho;
01514         const float* svmVec = &svmDetector[0];
01515 
01516         int j, k;
01517         for( j = 0; j < nblocks; j++, svmVec += blockHistogramSize )
01518         {
01519             const HOGCache::BlockData& bj = blockData[j];
01520             Point pt = pt0 + bj.imgOffset;
01521 
01522             const float* vec = cache.getBlock(pt, &blockHist[0]);
01523 #if CV_SSE2
01524             __m128 _vec = _mm_loadu_ps(vec);
01525             __m128 _svmVec = _mm_loadu_ps(svmVec);
01526             __m128 sum = _mm_mul_ps(_svmVec, _vec);
01527 
01528             for( k = 4; k <= blockHistogramSize - 4; k += 4 )
01529             {
01530                 _vec = _mm_loadu_ps(vec + k);
01531                 _svmVec = _mm_loadu_ps(svmVec + k);
01532 
01533                 sum = _mm_add_ps(sum, _mm_mul_ps(_vec, _svmVec));
01534             }
01535 
01536             _mm_storeu_ps(partSum, sum);
01537             double t0 = partSum[0] + partSum[1];
01538             double t1 = partSum[2] + partSum[3];
01539             s += t0 + t1;
01540 #else
01541             for( k = 0; k <= blockHistogramSize - 4; k += 4 )
01542                 s += vec[k]*svmVec[k] + vec[k+1]*svmVec[k+1] +
01543                     vec[k+2]*svmVec[k+2] + vec[k+3]*svmVec[k+3];
01544 #endif
01545             for( ; k < blockHistogramSize; k++ )
01546                 s += vec[k]*svmVec[k];
01547         }
01548         if( s >= hitThreshold )
01549         {
01550             hits.push_back(pt0);
01551             weights.push_back(s);
01552         }
01553     }
01554 }
01555 
01556 void HOGDescriptor::detect(const Mat& img, std::vector<Point>& hits, double hitThreshold,
01557     Size winStride, Size padding, const std::vector<Point>& locations) const
01558 {
01559     std::vector<double> weightsV;
01560     detect(img, hits, weightsV, hitThreshold, winStride, padding, locations);
01561 }
01562 
01563 class HOGInvoker :
01564     public ParallelLoopBody
01565 {
01566 public:
01567     HOGInvoker( const HOGDescriptor* _hog, const Mat& _img,
01568         double _hitThreshold, const Size& _winStride, const Size& _padding,
01569         const double* _levelScale, std::vector<Rect> * _vec, Mutex* _mtx,
01570         std::vector<double>* _weights=0, std::vector<double>* _scales=0 )
01571     {
01572         hog = _hog;
01573         img = _img;
01574         hitThreshold = _hitThreshold;
01575         winStride = _winStride;
01576         padding = _padding;
01577         levelScale = _levelScale;
01578         vec = _vec;
01579         weights = _weights;
01580         scales = _scales;
01581         mtx = _mtx;
01582     }
01583 
01584     void operator()( const Range& range ) const
01585     {
01586         int i, i1 = range.start, i2 = range.end;
01587         double minScale = i1 > 0 ? levelScale[i1] : i2 > 1 ? levelScale[i1+1] : std::max(img.cols, img.rows);
01588         Size maxSz(cvCeil(img.cols/minScale), cvCeil(img.rows/minScale));
01589         Mat smallerImgBuf(maxSz, img.type());
01590         std::vector<Point> locations;
01591         std::vector<double> hitsWeights;
01592 
01593         for( i = i1; i < i2; i++ )
01594         {
01595             double scale = levelScale[i];
01596             Size sz(cvRound(img.cols/scale), cvRound(img.rows/scale));
01597             Mat smallerImg(sz, img.type(), smallerImgBuf.ptr());
01598             if( sz == img.size() )
01599                 smallerImg = Mat(sz, img.type(), img.data, img.step);
01600             else
01601                 resize(img, smallerImg, sz);
01602             hog->detect(smallerImg, locations, hitsWeights, hitThreshold, winStride, padding);
01603             Size scaledWinSize = Size(cvRound(hog->winSize.width*scale), cvRound(hog->winSize.height*scale));
01604 
01605             mtx->lock();
01606             for( size_t j = 0; j < locations.size(); j++ )
01607             {
01608                 vec->push_back(Rect(cvRound(locations[j].x*scale),
01609                                     cvRound(locations[j].y*scale),
01610                                     scaledWinSize.width, scaledWinSize.height));
01611                 if (scales)
01612                     scales->push_back(scale);
01613             }
01614             mtx->unlock();
01615 
01616             if (weights && (!hitsWeights.empty()))
01617             {
01618                 mtx->lock();
01619                 for (size_t j = 0; j < locations.size(); j++)
01620                     weights->push_back(hitsWeights[j]);
01621                 mtx->unlock();
01622             }
01623         }
01624     }
01625 
01626 private:
01627     const HOGDescriptor* hog;
01628     Mat img;
01629     double hitThreshold;
01630     Size winStride;
01631     Size padding;
01632     const double* levelScale;
01633     std::vector<Rect>* vec;
01634     std::vector<double>* weights;
01635     std::vector<double>* scales;
01636     Mutex* mtx;
01637 };
01638 
01639 #ifdef HAVE_OPENCL
01640 
01641 static bool ocl_classify_hists(int win_height, int win_width, int block_stride_y, int block_stride_x,
01642                                int win_stride_y, int win_stride_x, int height, int width,
01643                                const UMat& block_hists, UMat detector,
01644                                float free_coef, float threshold, UMat& labels, Size descr_size, int block_hist_size)
01645 {
01646     int nthreads;
01647     bool is_cpu = cv::ocl::Device::getDefault().type() == cv::ocl::Device::TYPE_CPU;
01648     cv::String opts;
01649 
01650     ocl::Kernel k;
01651     int idx = 0;
01652     switch (descr_size.width)
01653     {
01654     case 180:
01655         nthreads = 180;
01656         k.create("classify_hists_180_kernel", ocl::objdetect::objdetect_hog_oclsrc, "-D WAVE_SIZE=32");
01657         if(k.empty())
01658             return false;
01659         if(is_cpu)
01660            opts = "-D CPU ";
01661         else
01662             opts = cv::format("-D WAVE_SIZE=%d", k.preferedWorkGroupSizeMultiple());
01663         k.create("classify_hists_180_kernel", ocl::objdetect::objdetect_hog_oclsrc, opts);
01664         if(k.empty())
01665             return false;
01666         idx = k.set(idx, descr_size.width);
01667         idx = k.set(idx, descr_size.height);
01668         break;
01669 
01670     case 252:
01671         nthreads = 256;
01672         k.create("classify_hists_252_kernel", ocl::objdetect::objdetect_hog_oclsrc, "-D WAVE_SIZE=32");
01673         if(k.empty())
01674             return false;
01675         if(is_cpu)
01676            opts = "-D CPU ";
01677         else
01678             opts = cv::format("-D WAVE_SIZE=%d", k.preferedWorkGroupSizeMultiple());
01679         k.create("classify_hists_252_kernel", ocl::objdetect::objdetect_hog_oclsrc, opts);
01680         if(k.empty())
01681             return false;
01682         idx = k.set(idx, descr_size.width);
01683         idx = k.set(idx, descr_size.height);
01684         break;
01685 
01686     default:
01687         nthreads = 256;
01688         k.create("classify_hists_kernel", ocl::objdetect::objdetect_hog_oclsrc, "-D WAVE_SIZE=32");
01689         if(k.empty())
01690             return false;
01691         if(is_cpu)
01692            opts = "-D CPU ";
01693         else
01694             opts = cv::format("-D WAVE_SIZE=%d", k.preferedWorkGroupSizeMultiple());
01695         k.create("classify_hists_kernel", ocl::objdetect::objdetect_hog_oclsrc, opts);
01696         if(k.empty())
01697             return false;
01698         idx = k.set(idx, descr_size.area());
01699         idx = k.set(idx, descr_size.height);
01700     }
01701 
01702     int win_block_stride_x = win_stride_x / block_stride_x;
01703     int win_block_stride_y = win_stride_y / block_stride_y;
01704     int img_win_width = (width - win_width + win_stride_x) / win_stride_x;
01705     int img_win_height = (height - win_height + win_stride_y) / win_stride_y;
01706     int img_block_width = (width - CELLS_PER_BLOCK_X * CELL_WIDTH + block_stride_x) /
01707         block_stride_x;
01708 
01709     size_t globalThreads[3] = { (size_t)img_win_width * nthreads, (size_t)img_win_height, 1 };
01710     size_t localThreads[3] = { (size_t)nthreads, 1, 1 };
01711 
01712     idx = k.set(idx, block_hist_size);
01713     idx = k.set(idx, img_win_width);
01714     idx = k.set(idx, img_block_width);
01715     idx = k.set(idx, win_block_stride_x);
01716     idx = k.set(idx, win_block_stride_y);
01717     idx = k.set(idx, ocl::KernelArg::PtrReadOnly(block_hists));
01718     idx = k.set(idx, ocl::KernelArg::PtrReadOnly(detector));
01719     idx = k.set(idx, free_coef);
01720     idx = k.set(idx, threshold);
01721     idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(labels));
01722 
01723     return k.run(2, globalThreads, localThreads, false);
01724 }
01725 
01726 static bool ocl_detect(InputArray img, std::vector<Point> &hits, double hit_threshold, Size win_stride,
01727                        const UMat& oclSvmDetector, Size blockSize, Size cellSize, int nbins, Size blockStride, Size winSize,
01728                        bool gammaCorrection, double L2HysThreshold, float sigma, float free_coef, bool signedGradient)
01729 {
01730     hits.clear();
01731     if (oclSvmDetector.empty())
01732         return false;
01733 
01734     Size imgSize = img.size();
01735     Size effect_size = imgSize;
01736     UMat grad(imgSize, CV_32FC2);
01737     int qangle_type = ocl::Device::getDefault().isIntel() ? CV_32SC2 : CV_8UC2;
01738     UMat qangle(imgSize, qangle_type);
01739 
01740     const size_t block_hist_size = getBlockHistogramSize(blockSize, cellSize, nbins);
01741     const Size blocks_per_img = numPartsWithin(imgSize, blockSize, blockStride);
01742     UMat block_hists(1, static_cast<int>(block_hist_size * blocks_per_img.area()) + 256, CV_32F);
01743 
01744     Size wins_per_img = numPartsWithin(imgSize, winSize, win_stride);
01745     UMat labels(1, wins_per_img.area(), CV_8U);
01746 
01747     float scale = 1.f / (2.f * sigma * sigma);
01748     Mat gaussian_lut(1, 512, CV_32FC1);
01749     int idx = 0;
01750     for(int i=-8; i<8; i++)
01751         for(int j=-8; j<8; j++)
01752             gaussian_lut.at<float>(idx++) = std::exp(-(j * j + i * i) * scale);
01753     for(int i=-8; i<8; i++)
01754         for(int j=-8; j<8; j++)
01755             gaussian_lut.at<float>(idx++) = (8.f - fabs(j + 0.5f)) * (8.f - fabs(i + 0.5f)) / 64.f;
01756 
01757     if(!ocl_computeGradient(img, grad, qangle, nbins, effect_size, gammaCorrection, signedGradient))
01758         return false;
01759 
01760     UMat gauss_w_lut;
01761     gaussian_lut.copyTo(gauss_w_lut);
01762     if(!ocl_compute_hists(nbins, blockStride.width, blockStride.height, effect_size.height,
01763         effect_size.width, grad, qangle, gauss_w_lut, block_hists, block_hist_size))
01764         return false;
01765 
01766     if(!ocl_normalize_hists(nbins, blockStride.width, blockStride.height, effect_size.height,
01767         effect_size.width, block_hists, (float)L2HysThreshold))
01768         return false;
01769 
01770     Size blocks_per_win = numPartsWithin(winSize, blockSize, blockStride);
01771 
01772     Size descr_size((int)block_hist_size*blocks_per_win.width, blocks_per_win.height);
01773 
01774     if(!ocl_classify_hists(winSize.height, winSize.width, blockStride.height,
01775         blockStride.width, win_stride.height, win_stride.width,
01776         effect_size.height, effect_size.width, block_hists, oclSvmDetector,
01777         free_coef, (float)hit_threshold, labels, descr_size, (int)block_hist_size))
01778         return false;
01779 
01780     Mat labels_host = labels.getMat(ACCESS_READ);
01781     unsigned char *vec = labels_host.ptr();
01782     for (int i = 0; i < wins_per_img.area(); i++)
01783     {
01784         int y = i / wins_per_img.width;
01785         int x = i - wins_per_img.width * y;
01786         if (vec[i])
01787         {
01788             hits.push_back(Point(x * win_stride.width, y * win_stride.height));
01789         }
01790     }
01791     return true;
01792 }
01793 
01794 static bool ocl_detectMultiScale(InputArray _img, std::vector<Rect> &found_locations, std::vector<double>& level_scale,
01795                                               double hit_threshold, Size win_stride, double group_threshold,
01796                                               const UMat& oclSvmDetector, Size blockSize, Size cellSize,
01797                                               int nbins, Size blockStride, Size winSize, bool gammaCorrection,
01798                                               double L2HysThreshold, float sigma, float free_coef, bool signedGradient)
01799 {
01800     std::vector<Rect> all_candidates;
01801     std::vector<Point> locations;
01802     UMat image_scale;
01803     Size imgSize = _img.size();
01804     image_scale.create(imgSize, _img.type());
01805 
01806     for (size_t i = 0; i<level_scale.size() ; i++)
01807     {
01808         double scale = level_scale[i];
01809         Size effect_size = Size(cvRound(imgSize.width / scale), cvRound(imgSize.height / scale));
01810         if (effect_size == imgSize)
01811         {
01812             if(!ocl_detect(_img, locations, hit_threshold, win_stride, oclSvmDetector, blockSize, cellSize, nbins,
01813                 blockStride, winSize, gammaCorrection, L2HysThreshold, sigma, free_coef, signedGradient))
01814                 return false;
01815         }
01816         else
01817         {
01818             resize(_img, image_scale, effect_size);
01819             if(!ocl_detect(image_scale, locations, hit_threshold, win_stride, oclSvmDetector, blockSize, cellSize, nbins,
01820                 blockStride, winSize, gammaCorrection, L2HysThreshold, sigma, free_coef, signedGradient))
01821                 return false;
01822         }
01823         Size scaled_win_size(cvRound(winSize.width * scale),
01824             cvRound(winSize.height * scale));
01825         for (size_t j = 0; j < locations.size(); j++)
01826             all_candidates.push_back(Rect(Point2d(locations[j]) * scale, scaled_win_size));
01827     }
01828     found_locations.assign(all_candidates.begin(), all_candidates.end());
01829     groupRectangles (found_locations, (int)group_threshold, 0.2);
01830     clipObjects(imgSize, found_locations, 0, 0);
01831 
01832     return true;
01833 }
01834 #endif //HAVE_OPENCL
01835 
01836 void HOGDescriptor::detectMultiScale(
01837     InputArray _img, std::vector<Rect>& foundLocations, std::vector<double>& foundWeights,
01838     double hitThreshold, Size winStride, Size padding,
01839     double scale0, double finalThreshold, bool useMeanshiftGrouping) const
01840 {
01841     double scale = 1.;
01842     int levels = 0;
01843 
01844     Size imgSize = _img.size();
01845     std::vector<double> levelScale;
01846     for( levels = 0; levels < nlevels; levels++ )
01847     {
01848         levelScale.push_back(scale);
01849         if( cvRound(imgSize.width/scale) < winSize.width ||
01850             cvRound(imgSize.height/scale) < winSize.height ||
01851                 scale0 <= 1 )
01852             break;
01853         scale *= scale0;
01854     }
01855     levels = std::max(levels, 1);
01856     levelScale.resize(levels);
01857 
01858     if(winStride == Size())
01859         winStride = blockStride;
01860 
01861 #ifdef HAVE_OPENCL
01862     CV_OCL_RUN(_img.dims() <= 2 && _img.type() == CV_8UC1 && scale0 > 1 && winStride.width % blockStride.width == 0 &&
01863         winStride.height % blockStride.height == 0 && padding == Size(0,0) && _img.isUMat(),
01864         ocl_detectMultiScale(_img, foundLocations, levelScale, hitThreshold, winStride, finalThreshold, oclSvmDetector,
01865         blockSize, cellSize, nbins, blockStride, winSize, gammaCorrection, L2HysThreshold, (float)getWinSigma(), free_coef, signedGradient));
01866 #endif
01867     std::vector<Rect> allCandidates;
01868     std::vector<double> tempScales;
01869     std::vector<double> tempWeights;
01870     std::vector<double> foundScales;
01871 
01872     Mutex mtx;
01873     Mat img = _img.getMat();
01874     Range range(0, (int)levelScale.size());
01875     HOGInvoker invoker(this, img, hitThreshold, winStride, padding, &levelScale[0], &allCandidates, &mtx, &tempWeights, &tempScales);
01876     parallel_for_(range, invoker);
01877 
01878     std::copy(tempScales.begin(), tempScales.end(), back_inserter(foundScales));
01879     foundLocations.clear();
01880     std::copy(allCandidates.begin(), allCandidates.end(), back_inserter(foundLocations));
01881     foundWeights.clear();
01882     std::copy(tempWeights.begin(), tempWeights.end(), back_inserter(foundWeights));
01883 
01884     if ( useMeanshiftGrouping )
01885         groupRectangles_meanshift (foundLocations, foundWeights, foundScales, finalThreshold, winSize);
01886     else
01887         groupRectangles (foundLocations, foundWeights, (int)finalThreshold, 0.2);
01888     clipObjects(imgSize, foundLocations, 0, &foundWeights);
01889 }
01890 
01891 void HOGDescriptor::detectMultiScale(InputArray img, std::vector<Rect>& foundLocations,
01892     double hitThreshold, Size winStride, Size padding,
01893     double scale0, double finalThreshold, bool useMeanshiftGrouping) const
01894 {
01895     std::vector<double> foundWeights;
01896     detectMultiScale(img, foundLocations, foundWeights, hitThreshold, winStride,
01897                 padding, scale0, finalThreshold, useMeanshiftGrouping);
01898 }
01899 
01900 template<typename _ClsName> struct RTTIImpl
01901 {
01902 public:
01903     static int isInstance(const void* ptr)
01904     {
01905         static _ClsName dummy;
01906         static void* dummyp = &dummy;
01907         union
01908         {
01909             const void* p;
01910             const void** pp;
01911         } a, b;
01912         a.p = dummyp;
01913         b.p = ptr;
01914         return *a.pp == *b.pp;
01915     }
01916     static void release(void** dbptr)
01917     {
01918         if(dbptr && *dbptr)
01919         {
01920             delete (_ClsName*)*dbptr;
01921             *dbptr = 0;
01922         }
01923     }
01924     static void* read(CvFileStorage* fs, CvFileNode* n)
01925     {
01926         FileNode fn(fs, n);
01927         _ClsName* obj = new _ClsName;
01928         if(obj->read(fn))
01929             return obj;
01930         delete obj;
01931         return 0;
01932     }
01933 
01934     static void write(CvFileStorage* _fs, const char* name, const void* ptr, CvAttrList)
01935     {
01936         if(ptr && _fs)
01937         {
01938             FileStorage fs(_fs, false);
01939             ((const _ClsName*)ptr)->write(fs, String(name));
01940         }
01941     }
01942 
01943     static void* clone(const void* ptr)
01944     {
01945         if(!ptr)
01946             return 0;
01947         return new _ClsName(*(const _ClsName*)ptr);
01948     }
01949 };
01950 
01951 typedef RTTIImpl<HOGDescriptor> HOGRTTI;
01952 
01953 CvType hog_type( CV_TYPE_NAME_HOG_DESCRIPTOR, HOGRTTI::isInstance,
01954     HOGRTTI::release, HOGRTTI::read, HOGRTTI::write, HOGRTTI::clone);
01955 
01956 std::vector<float> HOGDescriptor::getDefaultPeopleDetector()
01957 {
01958     static const float detector[] = {
01959         0.05359386f, -0.14721455f, -0.05532170f, 0.05077307f,
01960         0.11547081f, -0.04268804f, 0.04635834f, -0.05468199f, 0.08232084f,
01961         0.10424068f, -0.02294518f, 0.01108519f, 0.01378693f, 0.11193510f,
01962         0.01268418f, 0.08528346f, -0.06309239f, 0.13054633f, 0.08100729f,
01963         -0.05209739f, -0.04315529f, 0.09341384f, 0.11035026f, -0.07596218f,
01964         -0.05517511f, -0.04465296f, 0.02947334f, 0.04555536f,
01965         -3.55954492e-003f, 0.07818956f, 0.07730991f, 0.07890715f, 0.06222893f,
01966         0.09001380f, -0.03574381f, 0.03414327f, 0.05677258f, -0.04773581f,
01967         0.03746637f, -0.03521175f, 0.06955440f, -0.03849038f, 0.01052293f,
01968         0.01736112f, 0.10867710f, 0.08748853f, 3.29739624e-003f, 0.10907028f,
01969         0.07913758f, 0.10393070f, 0.02091867f, 0.11594022f, 0.13182420f,
01970         0.09879354f, 0.05362710f, -0.06745391f, -7.01260753e-003f,
01971         5.24702156e-003f, 0.03236255f, 0.01407916f, 0.02207983f, 0.02537322f,
01972         0.04547948f, 0.07200756f, 0.03129894f, -0.06274468f, 0.02107014f,
01973         0.06035208f, 0.08636236f, 4.53164103e-003f, 0.02193363f, 0.02309801f,
01974         0.05568166f, -0.02645093f, 0.04448695f, 0.02837519f, 0.08975694f,
01975         0.04461516f, 0.08975355f, 0.07514391f, 0.02306982f, 0.10410084f,
01976         0.06368385f, 0.05943464f, 4.58420580e-003f, 0.05220337f, 0.06675851f,
01977         0.08358569f, 0.06712101f, 0.06559004f, -0.03930482f, -9.15936660e-003f,
01978         -0.05897915f, 0.02816453f, 0.05032348f, 0.06780671f, 0.03377650f,
01979         -6.09417039e-004f, -0.01795146f, -0.03083684f, -0.01302475f,
01980         -0.02972313f, 7.88706727e-003f, -0.03525961f, -2.50397739e-003f,
01981         0.05245084f, 0.11791293f, -0.02167498f, 0.05299332f, 0.06640524f,
01982         0.05190265f, -8.27316567e-003f, 0.03033127f, 0.05842173f,
01983         -4.01050318e-003f, -6.25105947e-003f, 0.05862958f, -0.02465461f,
01984         0.05546781f, -0.08228195f, -0.07234028f, 0.04640540f, -0.01308254f,
01985         -0.02506191f, 0.03100746f, -0.04665651f, -0.04591486f, 0.02949927f,
01986         0.06035462f, 0.02244646f, -0.01698639f, 0.01040041f, 0.01131170f,
01987         0.05419579f, -0.02130277f, -0.04321722f, -0.03665198f, 0.01126490f,
01988         -0.02606488f, -0.02228328f, -0.02255680f, -0.03427236f,
01989         -7.75165204e-003f, -0.06195229f, 8.21638294e-003f, 0.09535975f,
01990         -0.03709979f, -0.06942501f, 0.14579427f, -0.05448192f, -0.02055904f,
01991         0.05747357f, 0.02781788f, -0.07077577f, -0.05178314f, -0.10429011f,
01992         -0.11235505f, 0.07529039f, -0.07559302f, -0.08786739f, 0.02983843f,
01993         0.02667585f, 0.01382199f, -0.01797496f, -0.03141199f, -0.02098101f,
01994         0.09029204f, 0.04955018f, 0.13718739f, 0.11379953f, 1.80019124e-003f,
01995         -0.04577610f, -1.11108483e-003f, -0.09470536f, -0.11596080f,
01996         0.04489342f, 0.01784211f, 3.06850672e-003f, 0.10781866f,
01997         3.36498418e-003f, -0.10842580f, -0.07436839f, -0.10535070f,
01998         -0.01866805f, 0.16057891f, -5.07316366e-003f, -0.04295658f,
01999         -5.90488780e-003f, 8.82003549e-003f, -0.01492646f, -0.05029279f,
02000         -0.12875880f, 8.78831954e-004f, -0.01297184f, -0.07592774f,
02001         -0.02668831f, -6.93787413e-004f, 0.02406698f, -0.01773298f,
02002         -0.03855745f, -0.05877856f, 0.03259695f, 0.12826584f, 0.06292590f,
02003         -4.10733931e-003f, 0.10996531f, 0.01332991f, 0.02088735f, 0.04037504f,
02004         -0.05210760f, 0.07760046f, 0.06399347f, -0.05751930f, -0.10053057f,
02005         0.07505023f, -0.02139782f, 0.01796176f, 2.34400877e-003f, -0.04208319f,
02006         0.07355055f, 0.05093350f, -0.02996780f, -0.02219072f, 0.03355330f,
02007         0.04418742f, -0.05580705f, -0.05037573f, -0.04548179f, 0.01379514f,
02008         0.02150671f, -0.02194211f, -0.13682702f, 0.05464972f, 0.01608082f,
02009         0.05309116f, 0.04701022f, 1.33690401e-003f, 0.07575664f, 0.09625306f,
02010         8.92647635e-003f, -0.02819123f, 0.10866830f, -0.03439325f,
02011         -0.07092371f, -0.06004780f, -0.02712298f, -7.07467366e-003f,
02012         -0.01637020f, 0.01336790f, -0.10313606f, 0.04906582f, -0.05732445f,
02013         -0.02731079f, 0.01042235f, -0.08340668f, 0.03686501f, 0.06108340f,
02014         0.01322748f, -0.07809529f, 0.03774724f, -0.03413248f, -0.06096525f,
02015         -0.04212124f, -0.07982176f, -1.25973229e-003f, -0.03045501f,
02016         -0.01236493f, -0.06312395f, 0.04789570f, -0.04602066f, 0.08576570f,
02017         0.02521080f, 0.02988098f, 0.10314583f, 0.07060035f, 0.04520544f,
02018         -0.04426654f, 0.13146530f, 0.08386490f, 0.02164590f, -2.12280243e-003f,
02019         -0.03686353f, -0.02074944f, -0.03829959f, -0.01530596f, 0.02689708f,
02020         0.11867401f, -0.06043470f, -0.02785023f, -0.04775074f, 0.04878745f,
02021         0.06350956f, 0.03494788f, 0.01467400f, 1.17890188e-003f, 0.04379614f,
02022         2.03681854e-003f, -0.03958609f, -0.01072688f, 6.43705716e-003f,
02023         0.02996500f, -0.03418507f, -0.01960307f, -0.01219154f,
02024         -4.37000440e-003f, -0.02549453f, 0.02646318f, -0.01632513f,
02025         6.46516960e-003f, -0.01929734f, 4.78711911e-003f, 0.04962371f,
02026         0.03809111f, 0.07265724f, 0.05758125f, -0.03741554f, 0.01648608f,
02027         -8.45285598e-003f, 0.03996826f, -0.08185477f, 0.02638875f,
02028         -0.04026615f, -0.02744674f, -0.04071517f, 1.05096330e-003f,
02029         -0.04741232f, -0.06733172f, 8.70434940e-003f, -0.02192543f,
02030         1.35350740e-003f, -0.03056974f, -0.02975521f, -0.02887780f,
02031         -0.01210713f, -0.04828526f, -0.09066251f, -0.09969629f, -0.03665164f,
02032         -8.88111943e-004f, -0.06826669f, -0.01866150f, -0.03627640f,
02033         -0.01408288f, 0.01874239f, -0.02075835f, 0.09145175f, -0.03547291f,
02034         0.05396780f, 0.04198981f, 0.01301925f, -0.03384354f, -0.12201976f,
02035         0.06830920f, -0.03715654f, 9.55848210e-003f, 5.05685573e-003f,
02036         0.05659294f, 3.90764466e-003f, 0.02808490f, -0.05518097f, -0.03711621f,
02037         -0.02835565f, -0.04420464f, -0.01031947f, 0.01883466f,
02038         -8.49525444e-003f, -0.09419250f, -0.01269387f, -0.02133371f,
02039         -0.10190815f, -0.07844430f, 2.43644323e-003f, -4.09610150e-003f,
02040         0.01202551f, -0.06452291f, -0.10593818f, -0.02464746f, -0.02199699f,
02041         -0.07401930f, 0.07285886f, 8.87513801e-004f, 9.97662079e-003f,
02042         8.46779719e-003f, 0.03730333f, -0.02905126f, 0.03573337f, -0.04393689f,
02043         -0.12014472f, 0.03176554f, -2.76015815e-003f, 0.10824566f, 0.05090732f,
02044         -3.30179278e-003f, -0.05123822f, 5.04784798e-003f, -0.05664124f,
02045         -5.99415926e-003f, -0.05341901f, -0.01221393f, 0.01291318f,
02046         9.91760660e-003f, -7.56987557e-003f, -0.06193124f, -2.24549137e-003f,
02047         0.01987562f, -0.02018840f, -0.06975540f, -0.06601523f, -0.03349112f,
02048         -0.08910118f, -0.03371435f, -0.07406893f, -0.02248047f, -0.06159951f,
02049         2.77751544e-003f, -0.05723337f, -0.04792468f, 0.07518548f,
02050         2.77279224e-003f, 0.04211938f, 0.03100502f, 0.05278448f, 0.03954679f,
02051         -0.03006846f, -0.03851741f, -0.02792403f, -0.02875333f, 0.01531280f,
02052         0.02186953f, -0.01989829f, 2.50679464e-003f, -0.10258728f,
02053         -0.04785743f, -0.02887216f, 3.85063468e-003f, 0.01112236f,
02054         8.29218887e-003f, -0.04822981f, -0.04503597f, -0.03713100f,
02055         -0.06988008f, -0.11002295f, -2.69209221e-003f, 1.85383670e-003f,
02056         -0.05921049f, -0.06105053f, -0.08458050f, -0.04527602f,
02057         8.90329306e-004f, -0.05875023f, -2.68602883e-003f, -0.01591195f,
02058         0.03631859f, 0.05493166f, 0.07300330f, 5.53333294e-003f, 0.06400407f,
02059         0.01847740f, -5.76280477e-003f, -0.03210877f, 4.25160583e-003f,
02060         0.01166520f, -1.44864211e-003f, 0.02253744f, -0.03367080f, 0.06983195f,
02061         -4.22323542e-003f, -8.89401045e-003f, -0.07943393f, 0.05199728f,
02062         0.06065201f, 0.04133492f, 1.44032843e-003f, -0.09585235f, -0.03964731f,
02063         0.04232114f, 0.01750465f, -0.04487902f, -7.59733608e-003f, 0.02011171f,
02064         0.04673622f, 0.09011173f, -0.07869188f, -0.04682482f, -0.05080139f,
02065         -3.99383716e-003f, -0.05346331f, 0.01085723f, -0.03599333f,
02066         -0.07097908f, 0.03551549f, 0.02680387f, 0.03471529f, 0.01790393f,
02067         0.05471273f, 9.62048303e-003f, -0.03180215f, 0.05864431f, 0.02330614f,
02068         0.01633144f, -0.05616681f, -0.10245429f, -0.08302189f, 0.07291322f,
02069         -0.01972590f, -0.02619633f, -0.02485327f, -0.04627592f,
02070         1.48853404e-003f, 0.05514185f, -0.01270860f, -0.01948900f, 0.06373586f,
02071         0.05002292f, -0.03009798f, 8.76216311e-003f, -0.02474238f,
02072         -0.05504891f, 1.74034527e-003f, -0.03333667f, 0.01524987f, 0.11663762f,
02073         -1.32344989e-003f, -0.06608453f, 0.05687166f, -6.89525274e-004f,
02074         -0.04402352f, 0.09450210f, -0.04222684f, -0.05360983f, 0.01779531f,
02075         0.02561388f, -0.11075410f, -8.77790991e-003f, -0.01099504f,
02076         -0.10380266f, 0.03103457f, -0.02105741f, -0.07371717f, 0.05146710f,
02077         0.10581432f, -0.08617968f, -0.02892107f, 0.01092199f, 0.14551543f,
02078         -2.24320893e-003f, -0.05818033f, -0.07390742f, 0.05701261f,
02079         0.12937020f, -0.04986651f, 0.10182415f, 0.05028650f, 0.12515625f,
02080         0.09175041f, 0.06404983f, 0.01523394f, 0.09460562f, 0.06106631f,
02081         -0.14266998f, -0.02926703f, 0.02762171f, 0.02164151f,
02082         -9.58488265e-004f, -0.04231362f, -0.09866509f, 0.04322244f,
02083         0.05872034f, -0.04838847f, 0.06319253f, 0.02443798f, -0.03606876f,
02084         9.38737206e-003f, 0.04289991f, -0.01027411f, 0.08156885f, 0.08751175f,
02085         -0.13191354f, 8.16054735e-003f, -0.01452161f, 0.02952677f, 0.03615945f,
02086         -2.09128903e-003f, 0.02246693f, 0.09623287f, 0.09412123f, -0.02924758f,
02087         -0.07815186f, -0.02203079f, -2.02566991e-003f, 0.01094733f,
02088         -0.01442332f, 0.02838561f, 0.11882371f, 7.28798332e-003f, -0.10345965f,
02089         0.07561217f, -0.02049661f, 4.44177445e-003f, 0.01609347f, -0.04893158f,
02090         -0.08758243f, -7.67420698e-003f, 0.08862378f, 0.06098121f, 0.06565887f,
02091         7.32981879e-003f, 0.03558407f, -0.03874352f, -0.02490055f,
02092         -0.06771075f, 0.09939223f, -0.01066077f, 0.01382995f, -0.07289080f,
02093         7.47184316e-003f, 0.10621431f, -0.02878659f, 0.02383525f, -0.03274646f,
02094         0.02137008f, 0.03837290f, 0.02450992f, -0.04296818f, -0.02895143f,
02095         0.05327370f, 0.01499020f, 0.04998732f, 0.12938657f, 0.09391870f,
02096         0.04292390f, -0.03359194f, -0.06809492f, 0.01125796f, 0.17290455f,
02097         -0.03430733f, -0.06255233f, -0.01813114f, 0.11726857f, -0.06127599f,
02098         -0.08677909f, -0.03429872f, 0.04684938f, 0.08161420f, 0.03538774f,
02099         0.01833884f, 0.11321855f, 0.03261845f, -0.04826299f, 0.01752407f,
02100         -0.01796414f, -0.10464549f, -3.30041884e-003f, 2.29343961e-004f,
02101         0.01457292f, -0.02132982f, -0.02602923f, -9.87351313e-003f,
02102         0.04273872f, -0.02103316f, -0.07994065f, 0.02614958f, -0.02111666f,
02103         -0.06964913f, -0.13453490f, -0.06861878f, -6.09341264e-003f,
02104         0.08251446f, 0.15612499f, 2.46531400e-003f, 8.88424646e-003f,
02105         -0.04152999f, 0.02054853f, 0.05277953f, -0.03087788f, 0.02817579f,
02106         0.13939077f, 0.07641046f, -0.03627627f, -0.03015098f, -0.04041540f,
02107         -0.01360690f, -0.06227205f, -0.02738223f, 0.13577610f, 0.15235767f,
02108         -0.05392922f, -0.11175954f, 0.02157129f, 0.01146481f, -0.05264937f,
02109         -0.06595174f, -0.02749175f, 0.11812254f, 0.17404149f, -0.06137035f,
02110         -0.11003478f, -0.01351621f, -0.01745916f, -0.08577441f, -0.04469909f,
02111         -0.06106115f, 0.10559758f, 0.20806813f, -0.09174948f, 7.09621934e-004f,
02112         0.03579374f, 0.07215115f, 0.02221742f, 0.01827742f, -7.90785067e-003f,
02113         0.01489554f, 0.14519960f, -0.06425831f, 0.02990399f, -1.80181325e-003f,
02114         -0.01401528f, -0.04171134f, -3.70530109e-003f, -0.09090481f,
02115         0.09520713f, 0.08845516f, -0.02651753f, -0.03016730f, 0.02562448f,
02116         0.03563816f, -0.03817881f, 0.01433385f, 0.02256983f, 0.02872120f,
02117         0.01001934f, -0.06332260f, 0.04338406f, 0.07001807f, -0.04705722f,
02118         -0.07318907f, 0.02630457f, 0.03106382f, 0.06648342f, 0.10913180f,
02119         -0.01630815f, 0.02910308f, 0.02895109f, 0.08040254f, 0.06969310f,
02120         0.06797734f, 6.08639978e-003f, 4.16588830e-003f, 0.08926726f,
02121         -0.03123648f, 0.02700146f, 0.01168734f, -0.01631594f, 4.61015804e-003f,
02122         8.51359498e-003f, -0.03544224f, 0.03571994f, 4.29766066e-003f,
02123         -0.01970077f, -8.79793242e-003f, 0.09607988f, 0.01544222f,
02124         -0.03923707f, 0.07308586f, 0.06061262f, 1.31683104e-004f,
02125         -7.98222050e-003f, 0.02399261f, -0.06084389f, -0.02743429f,
02126         -0.05475523f, -0.04131311f, 0.03559756f, 0.03055342f, 0.02981433f,
02127         0.14860515f, 0.01766787f, 0.02945257f, 0.04898238f, 0.01026922f,
02128         0.02811658f, 0.08267091f, 0.02732154f, -0.01237693f, 0.11760156f,
02129         0.03802063f, -0.03309754f, 5.24957618e-003f, -0.02460510f, 0.02691451f,
02130         0.05399988f, -0.10133506f, 0.06385437f, -0.01818005f, 0.02259503f,
02131         0.03573135f, 0.01042848f, -0.04153402f, -0.04043029f, 0.01643575f,
02132         0.08326677f, 4.61383024e-004f, -0.05308095f, -0.08536223f,
02133         -1.61011645e-003f, -0.02163720f, -0.01783352f, 0.03859637f,
02134         0.08498885f, -0.01725216f, 0.08625131f, 0.10995087f, 0.09177644f,
02135         0.08498347f, 0.07646490f, 0.05580502f, 0.02693516f, 0.09996913f,
02136         0.09070327f, 0.06667200f, 0.05873008f, -0.02247842f, 0.07772321f,
02137         0.12408436f, 0.12629253f, -8.41997913e-004f, 0.01477783f, 0.09165990f,
02138         -2.98401713e-003f, -0.06466447f, -0.07057302f, 2.09516948e-004f,
02139         0.02210209f, -0.02158809f, -0.08602506f, -0.02284836f,
02140         4.01876355e-003f, 9.56660323e-003f, -0.02073978f, -0.04635138f,
02141         -7.59423291e-003f, -0.01377393f, -0.04559359f, -0.13284740f,
02142         -0.08671406f, -0.03654395f, 0.01142869f, 0.03287891f, -0.04392983f,
02143         0.06142959f, 0.17710890f, 0.10385257f, 0.01329137f, 0.10067633f,
02144         0.12450829f, -0.04476709f, 0.09049144f, 0.04589312f, 0.11167907f,
02145         0.08587538f, 0.04767583f, 1.67188141e-003f, 0.02359802f, -0.03808852f,
02146         0.03126272f, -0.01919029f, -0.05698918f, -0.02365112f, -0.06519032f,
02147         -0.05599358f, -0.07097308f, -0.03301812f, -0.04719102f, -0.02566297f,
02148         0.01324074f, -0.09230672f, -0.05518232f, -0.04712864f, -0.03380903f,
02149         -0.06719479f, 0.01183908f, -0.09326738f, 0.01642865f, 0.03789867f,
02150         -6.61567831e-003f, 0.07796386f, 0.07246574f, 0.04706347f, -0.02523437f,
02151         -0.01696830f, -0.08068866f, 0.06030888f, 0.10527060f, -0.06611756f,
02152         0.02977346f, 0.02621830f, 0.01913855f, -0.08479366f, -0.06322418f,
02153         -0.13570616f, -0.07644490f, 9.31900274e-003f, -0.08095149f,
02154         -0.10197903f, -0.05204025f, 0.01413151f, -0.07800411f, -0.01885122f,
02155         -0.07509381f, -0.10136326f, -0.05212355f, -0.09944065f,
02156         -1.33606605e-003f, -0.06342617f, -0.04178550f, -0.12373723f,
02157         -0.02832736f, -0.06057501f, 0.05830070f, 0.07604282f, -0.06462587f,
02158         8.02447461e-003f, 0.11580125f, 0.12332212f, 0.01978462f,
02159         -2.72378162e-003f, 0.05850752f, -0.04674481f, 0.05148062f,
02160         -2.62542837e-003f, 0.11253355f, 0.09893716f, 0.09785093f, -0.04659257f,
02161         -0.01102429f, -0.07002308f, 0.03088913f, -0.02565549f, -0.07671449f,
02162         3.17443861e-003f, -0.10783514f, -0.02314270f, -0.11089555f,
02163         -0.01024768f, 0.03116021f, -0.04964825f, 0.02281825f, 5.50005678e-003f,
02164         -0.08427856f, -0.14685495f, -0.07719755f, -0.13342668f, -0.04525511f,
02165         -0.09914210f, 0.02588859f, 0.03469279f, 0.04664020f, 0.11688190f,
02166         0.09647275f, 0.10857815f, -0.01448726f, 0.04299758f, -0.06763151f,
02167         1.33257592e-003f, 0.14331576f, 0.07574340f, 0.09166205f, 0.05674926f,
02168         0.11325553f, -0.01106494f, 0.02062161f, -0.11484840f, -0.07492137f,
02169         -0.02864293f, -0.01275638f, -0.06946032f, -0.10101652f, -0.04113498f,
02170         -0.02214783f, -0.01273942f, -0.07480393f, -0.10556041f, -0.07622112f,
02171         -0.09988393f, -0.11453961f, -0.12073903f, -0.09412795f, -0.07146588f,
02172         -0.04054537f, -0.06127083f, 0.04221122f, 0.07688113f, 0.04099256f,
02173         0.12663734f, 0.14683802f, 0.21761774f, 0.12525328f, 0.18431792f,
02174         -1.66402373e-003f, 2.37777247e-003f, 0.01445475f, 0.03509416f,
02175         0.02654697f, 0.01716739f, 0.05374011f, 0.02944174f, 0.11323927f,
02176         -0.01485456f, -0.01611330f, -1.85554172e-003f, -0.01708549f,
02177         -0.05435753f, -0.05302101f, 0.05260378f, -0.03582945f,
02178         -3.42867890e-004f, 1.36076682e-003f, -0.04436073f, -0.04228432f,
02179         0.03281291f, -0.05480836f, -0.10197772f, -0.07206279f, -0.10741059f,
02180         -0.02366946f, 0.10278475f, -2.74783419e-003f, -0.03242477f,
02181         0.02308955f, 0.02835869f, 0.10348799f, 0.19580358f, 0.10252027f,
02182         0.08039929f, 0.05525554f, -0.13250865f, -0.14395352f, 3.13586881e-003f,
02183         -0.03387071f, 8.94669443e-003f, 0.05406157f, -4.97324532e-003f,
02184         -0.01189114f, 2.82919413e-004f, -0.03901557f, -0.04898705f,
02185         0.02164520f, -0.01382906f, -0.01850416f, 0.01869347f, -0.02450060f,
02186         0.02291678f, 0.08196463f, 0.03309153f, -0.10629974f, 0.02473924f,
02187         0.05344394f, -0.02404823f, -0.03243643f, -5.55244600e-003f,
02188         -0.08009996f, 0.02811539f, 0.04235742f, 0.01859004f, 0.04902123f,
02189         -0.01438252f, -0.01526853f, 0.02044195f, -0.05008660f, 0.04244113f,
02190         0.07611816f, 0.04950470f, -0.06020549f, -4.26026015e-003f, 0.13133512f,
02191         -0.01438738f, -0.01958807f, -0.04044152f, -0.12425045f,
02192         2.84353318e-003f, -0.05042776f, -0.09121484f, 7.34345755e-003f,
02193         0.09388847f, 0.11800314f, 4.72295098e-003f, 4.44378285e-003f,
02194         -0.07984917f, -0.03613737f, 0.04490915f, -0.02246483f, 0.04681071f,
02195         0.05240871f, 0.02157206f, -0.04603431f, -0.01197929f, -0.02748779f,
02196         0.13621049f, 0.08812155f, -0.07802048f, 4.86458559e-003f, -0.01598836f,
02197         0.01024450f, -0.03463517f, -0.02304239f, -0.08692665f, 0.06655128f,
02198         0.05785803f, -0.12640759f, 0.02307472f, 0.07337402f, 0.07525434f,
02199         0.04943763f, -0.02241034f, -0.09978238f, 0.14487994f, -0.06570521f,
02200         -0.07855482f, 0.02830222f, -5.29603509e-004f, -0.04669895f,
02201         -0.11822784f, -0.12246452f, -0.15365660f, -0.02969127f, 0.08078201f,
02202         0.13512598f, 0.11505685f, 0.04740673f, 0.01376022f, -0.05852978f,
02203         -0.01537809f, -0.05541119f, 0.02491065f, -0.02870786f, 0.02760978f,
02204         0.23836176f, 0.22347429f, 0.10306466f, -0.06919070f, -0.10132039f,
02205         -0.20198342f, -0.05040560f, 0.27163076f, 0.36987007f, 0.34540465f,
02206         0.29095781f, 0.05649706f, 0.04125737f, 0.07505883f, -0.02737836f,
02207         -8.43431335e-003f, 0.07368195f, 0.01653876f, -0.09402955f,
02208         -0.09574359f, 0.01474337f, -0.07128561f, -0.03460737f, 0.11438941f,
02209         0.13752601f, -0.06385452f, -0.06310338f, 8.19548313e-003f, 0.11622470f,
02210         5.05133113e-003f, -0.07602754f, 0.06695660f, 0.25723928f, 0.09037900f,
02211         0.28826267f, 0.13165380f, -0.05312614f, -0.02137198f, -0.03442232f,
02212         -0.06255679f, 0.03899667f, 0.18391028f, 0.26016650f, 0.03374462f,
02213         0.01860465f, 0.19077586f, 0.18160543f, 3.43634398e-003f, -0.03036782f,
02214         0.19683038f, 0.35378191f, 0.24968483f, -0.03222649f, 0.28972381f,
02215         0.43091634f, 0.30778357f, 0.02335266f, -0.09877399f, -6.85245218e-003f,
02216         0.08945240f, -0.08150686f, 0.02792493f, 0.24806842f, 0.17338486f,
02217         0.06231801f, -0.10432383f, -0.16653322f, -0.13197899f, -0.08531576f,
02218         -0.19271527f, -0.13536365f, 0.22240199f, 0.39219588f, 0.26597717f,
02219         -0.01231649f, 0.01016179f, 0.13379875f, 0.12018334f, -0.04852953f,
02220         -0.07915270f, 0.07036012f, 3.87723115e-003f, -0.06126805f,
02221         -0.15015170f, -0.11406515f, -0.08556531f, -0.07429333f, -0.16115491f,
02222         0.13214062f, 0.25691369f, 0.05697750f, 0.06861912f, -6.02903729e-003f,
02223         -7.94562511e-003f, 0.04799571f, 0.06695165f, -0.01926842f, 0.06206308f,
02224         0.13450983f, -0.06381495f, -2.98370165e-003f, -0.03482971f,
02225         7.53991678e-003f, 0.03895611f, 0.11464261f, 0.01669971f,
02226         8.27818643e-003f, -7.49160210e-003f, -0.11712562f, -0.10650621f,
02227         -0.10353880f, -0.04994106f, -7.65618810e-004f, 0.03023767f,
02228         -0.04759270f, -0.07302686f, -0.05825012f, -0.13156348f, -0.10639747f,
02229         -0.19393684f, -0.09973683f, -0.07918908f, 4.63177625e-004f,
02230         -6.61382044e-004f, 0.15853868f, 0.08561199f, -0.07660093f,
02231         -0.08015265f, -0.06164073f, 0.01882577f, -7.29908410e-004f,
02232         0.06840892f, 0.03843764f, 0.20274927f, 0.22028814f, -5.26101235e-003f,
02233         0.01452435f, -0.06331623f, 0.02865064f, 0.05673740f, 0.12171564f,
02234         0.03837196f, 0.03555467f, -0.02662914f, -0.10280123f, -0.06526285f,
02235         -0.11066351f, -0.08988424f, -0.10103678f, 8.10526591e-003f,
02236         5.95238712e-003f, 0.02617721f, -0.01705742f, -0.10897956f,
02237         -0.08004991f, -0.11271993f, -0.06185647f, -0.06103712f, 0.01597041f,
02238         -0.05923606f, 0.09410726f, 0.22858568f, 0.03263380f, 0.06772990f,
02239         -0.09003516f, 0.01017870f, 0.01931688f, 0.08628357f, -0.01430009f,
02240         0.10954945f, 0.16612452f, -0.02434544f, -0.03310068f, -0.04236627f,
02241         0.01212392f, -6.15046406e-003f, 0.06954194f, 0.03015283f, 0.01787957f,
02242         0.02781667f, -0.05561153f, -8.96244217e-003f, -0.04971489f,
02243         0.07510284f, 0.01775282f, 0.05889897f, -0.07981427f, 0.03647643f,
02244         -3.73833324e-003f, -0.08894575f, -0.06429435f, -0.08068276f,
02245         0.03567704f, -0.07131936f, -7.21910037e-003f, -0.09566668f,
02246         0.17886090f, 0.14911725f, 0.02070032f, -0.05017120f, -0.04992622f,
02247         0.01570143f, -0.09906903f, 0.06456193f, 0.15329507f, 0.18820767f,
02248         0.11689861f, -0.01178513f, -0.02225163f, -0.01905318f, 0.10271224f,
02249         -7.27029052e-003f, 0.11664233f, 0.14796902f, 0.07771893f, 0.02400013f,
02250         -0.05361797f, -0.01972888f, 0.01376177f, 0.06740040f, -0.06525395f,
02251         0.05726178f, -0.02404981f, -0.14018567f, -0.02074987f, -0.04621970f,
02252         -0.04688627f, -0.01842059f, 0.07722727f, -0.04852883f, 0.01529004f,
02253         -0.19639495f, 0.10817073f, 0.03795860f, -0.09435206f, -0.07984378f,
02254         -0.03383440f, 0.11081333f, 0.02237366f, 0.12703256f, 0.21613893f,
02255         0.02918790f, 4.66472283e-003f, -0.10274266f, -0.04854131f,
02256         -3.46305710e-003f, 0.08652268f, 0.02251546f, 0.09636052f, 0.17180754f,
02257         -0.09272388f, 4.59174305e-004f, -0.11723048f, -0.12210111f,
02258         -0.15547538f, 0.07218186f, -0.05297846f, 0.03779940f, 0.05150875f,
02259         -0.03802310f, 0.03870645f, -0.15250699f, -0.08696499f, -0.02021560f,
02260         0.04118926f, -0.15177974f, 0.01577647f, 0.10249301f, 7.50041893e-003f,
02261         0.01721806f, -0.06828983f, -0.02397596f, -0.06598977f, -0.04317593f,
02262         -0.08064980f, 6.66632550e-003f, 0.03333484f, 0.07093620f, 0.08231064f,
02263         -0.06577903f, -0.06698844f, -0.06984019f, -0.06508023f, -0.14145090f,
02264         -0.02393239f, 0.06485303f, 8.83263443e-003f, 0.09251080f, -0.07557579f,
02265         -0.05067699f, -0.09798748f, -0.06703258f, -0.14056294f, 0.03245994f,
02266         0.12554143f, 0.01761621f, 0.12980327f, -0.04081950f, -0.11906909f,
02267         -0.14813015f, -0.08376863f, -0.12200681f, 0.04988137f, 0.05424247f,
02268         -3.90952639e-003f, 0.03255733f, -0.12717837f, -0.07461493f,
02269         -0.05703964f, -0.01736189f, -0.08026433f, -0.05433894f, -0.01719359f,
02270         0.02886275f, 0.01772653f, -0.09163518f, 3.57789593e-003f, -0.10129993f,
02271         -0.02653764f, -0.08131415f, -0.03847986f, -7.62157550e-004f,
02272         0.06486648f, 0.19675669f, -0.04919156f, -0.07059129f, -0.04857785f,
02273         -0.01042383f, -0.08328653f, 0.03660302f, -0.03696846f, 0.04969259f,
02274         0.08241162f, -0.12514858f, -0.06122676f, -0.03750202f,
02275         6.52989605e-003f, -0.10247213f, 0.02568346f, 4.51781414e-003f,
02276         -0.03734229f, -0.01131264f, -0.05412074f, 8.89345480e-004f,
02277         -0.12388977f, -0.05959237f, -0.12418608f, -0.06151643f, -0.07310260f,
02278         0.02441575f, 0.07023528f, -0.07548289f, -7.57147965e-004f,
02279         -0.09061348f, -0.08112976f, -0.06920306f, 9.54394229e-003f,
02280         -0.01219902f, 1.21273217e-003f, -8.88989680e-003f, -0.08309301f,
02281         -0.04552661f, -0.10739882f, -0.05691034f, -0.13928030f, 0.09027749f,
02282         0.15123098f, 0.03175976f, 0.17763577f, 3.29913251e-004f, 0.05151888f,
02283         -0.09844074f, -0.09475287f, -0.08571247f, 0.16241577f, 0.19336018f,
02284         8.57454538e-003f, 0.11474732f, -0.01493934f, 0.03352379f, -0.08966240f,
02285         -0.02322310f, 0.02663568f, 0.05448750f, -0.03536883f, -0.07210463f,
02286         -0.06807277f, -0.03121621f, -0.05932408f, -0.17282860f, -0.15873498f,
02287         -0.04956378f, 0.01603377f, -0.12385946f, 0.13878587f, 0.21468069f,
02288         0.13510075f, 0.20992437f, 0.08845878f, 0.08104013f, 0.03754176f,
02289         0.12173114f, 0.11103114f, 0.10643122f, 0.13941477f, 0.11640384f,
02290         0.14786847f, 0.01218238f, 0.01160753f, 0.03547940f, 0.08794311f,
02291         -0.01695384f, -0.07692261f, -0.08236158f, 6.79194089e-003f,
02292         -0.02458403f, 0.13022894f, 0.10953187f, 0.09857773f, 0.04735930f,
02293         -0.04353498f, -0.15173385f, -0.17904443f, -0.10450364f, -0.13418166f,
02294         -0.06633098f, -0.03170381f, -0.06839000f, -0.11350126f, -0.06983913f,
02295         0.19083543f, 0.17604128f, 0.07730632f, 0.10022651f, 0.36428109f,
02296         0.28291923f, 0.12688625f, 0.15942036f, 0.14064661f, -0.11201853f,
02297         -0.13969108f, -0.09088077f, -0.14107047f, 0.05117374f,
02298         -2.63348082e-003f, -0.10794610f, -0.09715455f, -0.05284977f,
02299         0.01565668f, 0.05031200f, 0.07021113f, -0.02963028f, 0.01766960f,
02300         0.08333644f, -0.03211382f, 4.90096770e-003f, 0.05186674f, -0.05045737f,
02301         -0.09624767f, -0.02525997f, 0.06916669f, 0.01213916f, 0.05333899f,
02302         -0.03443280f, -0.10055527f, -0.06291115f, 5.42851724e-003f,
02303         -6.30360236e-003f, 0.02270257f, -0.01769792f, 0.03273688f, 0.07746078f,
02304         7.77099328e-003f, 0.05041346f, 0.01648103f, -0.02321534f, -0.09930186f,
02305         -0.02293853f, 0.02034990f, -0.08324204f, 0.08510064f, -0.03732836f,
02306         -0.06465405f, -0.06086946f, 0.13680504f, -0.11469388f, -0.03896406f,
02307         -0.07142810f, 2.67581246e-003f, -0.03639632f, -0.09849060f,
02308         -0.11014334f, 0.17489147f, 0.17610909f, -0.16091567f, -0.07248894f,
02309         0.01567141f, 0.23742996f, 0.07552249f, -0.06270349f, -0.07303379f,
02310         0.25442186f, 0.16903116f, -0.08168741f, -0.05913896f, -0.03954096f,
02311         6.81776879e-003f, -0.05615319f, -0.07303037f, -0.12176382f,
02312         0.12385108f, 0.22084464f, -0.05543206f, -0.03310431f, 0.05731593f,
02313         0.19481890f, 0.04016430f, -0.06480758f, -0.12353460f, 0.18733442f,
02314         -0.09631214f, -0.11192076f, 0.12404587f, 0.15671748f, 0.19256128f,
02315         0.10895617f, 0.03391477f, -0.13032004f, -0.05626907f, -0.09025607f,
02316         0.23485197f, 0.27812332f, 0.26725492f, 0.07255980f, 0.16565137f,
02317         0.22388470f, 0.07441066f, -0.21003133f, -0.08075339f, -0.15031935f,
02318         0.07023834f, 0.10872041f, 0.18156518f, 0.20037253f, 0.13571967f,
02319         -0.11915682f, -0.11131983f, -0.18878011f, 0.06074620f, 0.20578890f,
02320         0.12413109f, 0.03930207f, 0.29176015f, 0.29502738f, 0.27856228f,
02321         -0.01803601f, 0.16646385f, 0.19268319f, 0.01900682f, 0.06026287f,
02322         2.35868432e-003f, 0.01558199f, 0.02707230f, 0.11383014f, 0.12103992f,
02323         0.03907350f, 0.04637353f, 0.09020995f, 0.11919726f, -3.63007211e-003f,
02324         0.02220155f, 0.10336831f, 0.17351882f, 0.12259731f, 0.18983354f,
02325         0.15736865f, 0.01160725f, -0.01690723f, -9.69582412e-004f, 0.07213813f,
02326         0.01161613f, 0.17864859f, 0.24486147f, 0.18208991f, 0.20177495f,
02327         0.05972528f, -8.93934630e-003f, -0.02316955f, 0.14436610f, 0.14114498f,
02328         0.05520950f, 0.06353590f, -0.19124921f, 0.10174713f, 0.29414919f,
02329         0.26448128f, 0.09344960f, 0.15284036f, 0.19797507f, 0.11369792f,
02330         -0.12722753f, -0.21396367f, -0.02008235f, -0.06566695f, -0.01662150f,
02331         -0.03937003f, 0.04778343f, 0.05017274f, -0.02299062f, -0.20208496f,
02332         -0.06395898f, 0.13721776f, 0.22544557f, 0.14888357f, 0.08687132f,
02333         0.27088094f, 0.32206613f, 0.09782200f, -0.18523243f, -0.17232181f,
02334         -0.01041531f, 0.04008654f, 0.04199702f, -0.08081299f, -0.03755421f,
02335         -0.04809646f, -0.05222081f, -0.21709201f, -0.06622940f, 0.02945281f,
02336         -0.04600435f, -0.05256077f, -0.08432942f, 0.02848100f, 0.03490564f,
02337         8.28621630e-003f, -0.11051246f, -0.11210597f, -0.01998289f,
02338         -0.05369405f, -0.08869293f, -0.18799506f, -0.05436598f, -0.05011634f,
02339         -0.05419716f, -0.06151857f, -0.10827805f, 0.04346735f, 0.04016083f,
02340         0.01520820f, -0.12173316f, -0.04880285f, -0.01101406f, 0.03250847f,
02341         -0.06009551f, -0.03082932f, -0.02295134f, -0.06856834f, -0.08775249f,
02342         -0.23793389f, -0.09174541f, -0.05538322f, -0.04321031f, -0.11874759f,
02343         -0.04221844f, -0.06070468f, 0.01194489f, 0.02608565f, -0.03892140f,
02344         -0.01643151f, -0.02602034f, -0.01305472f, 0.03920100f, -0.06514261f,
02345         0.01126918f, -6.27710763e-003f, -0.02720047f, -0.11133634f,
02346         0.03300330f, 0.02398472f, 0.04079665f, -0.10564448f, 0.05966159f,
02347         0.01195221f, -0.03179441f, -0.01692590f, -0.06177841f, 0.01841576f,
02348         -5.51078189e-003f, -0.06821765f, -0.03191888f, -0.09545476f,
02349         0.03030550f, -0.04896152f, -0.02914624f, -0.13283344f, -0.04783419f,
02350         6.07836898e-003f, -0.01449538f, -0.13358212f, -0.09687774f,
02351         -0.02813793f, 0.01213498f, 0.06650011f, -0.02039067f, 0.13356198f,
02352         0.05986415f, -9.12760664e-003f, -0.18780160f, -0.11992817f,
02353         -0.06342237f, 0.01229534f, 0.07143231f, 0.10713009f, 0.11085765f,
02354         0.06569190f, -0.02956399f, -0.16288325f, -0.13993549f, -0.01292515f,
02355         0.03833013f, 0.09130384f, -0.05086257f, 0.05617329f, -0.03896667f,
02356         -0.06282311f, -0.11490010f, -0.14264110f, -0.04530499f, 0.01598189f,
02357         0.09167797f, 0.08663294f, 0.04885277f, -0.05741219f, -0.07565769f,
02358         -0.17136464f, -0.02619422f, -0.02477579f, 0.02679587f, 0.11621952f,
02359         0.08788391f, 0.15520640f, 0.04709549f, 0.04504483f, -0.10214074f,
02360         -0.12293372f, -0.04820546f, -0.05484834f, 0.05473754f, 0.07346445f,
02361         0.05577277f, -0.08209965f, 0.03462975f, -0.20962234f, -0.09324598f,
02362         3.79481679e-003f, 0.03617633f, 0.16742408f, 0.07058107f, 0.10204960f,
02363         -0.06795346f, 3.22807301e-003f, -0.12589309f, -0.17496960f,
02364         0.02078314f, -0.07694324f, 0.12184640f, 0.08997164f, 0.04793497f,
02365         -0.11383379f, -0.08046359f, -0.25716835f, -0.08080962f,
02366         6.80711539e-003f, -0.02930280f, -3.04938294e-003f, -0.11106286f,
02367         -0.04628860f, -0.07821649f, 7.70127494e-003f, -0.10247706f,
02368         1.21042714e-003f, 0.20573859f, -0.03241005f, 8.42972286e-003f,
02369         0.01946464f, -0.01197973f, -0.14579976f, 0.04233614f,
02370         -4.14096704e-003f, -0.06866436f, -0.02431862f, -0.13529138f,
02371         1.25891645e-003f, -0.11425111f, -0.04303651f, -0.01694815f,
02372         0.05720210f, -0.16040207f, 0.02772896f, 0.05498345f, -0.15010567f,
02373         0.01450866f, 0.02350303f, -0.04301004f, -0.04951802f, 0.21702233f,
02374         -0.03159155f, -0.01963303f, 0.18232647f, -0.03263875f,
02375         -2.88476888e-003f, 0.01587562f, -1.94303901e-003f, -0.07789494f,
02376         0.04674156f, -6.25576358e-003f, 0.08925962f, 0.21353747f, 0.01254677f,
02377         -0.06999976f, -0.05931328f, -0.01884327f, -0.04306272f, 0.11794136f,
02378         0.03842728f, -0.03907030f, 0.05636114f, -0.09766009f, -0.02104000f,
02379         8.72711372e-003f, -0.02736877f, -0.05112274f, 0.16996814f, 0.02955785f,
02380         0.02094014f, 0.08414304f, -0.03335762f, -0.03617457f, -0.05808248f,
02381         -0.08872101f, 0.02927705f, 0.27077839f, 0.06075108f, 0.07478261f,
02382         0.15282831f, -0.03908454f, -0.05101782f, -9.51998029e-003f,
02383         -0.03272416f, -0.08735625f, 0.07633440f, -0.07185312f, 0.13841286f,
02384         0.07812646f, -0.12901451f, -0.05488589f, -0.05644578f, -0.03290703f,
02385         -0.11184757f, 0.03751570f, -0.05978153f, -0.09155276f, 0.05657315f,
02386         -0.04328186f, -0.03047933f, -0.01413135f, -0.10181040f, -0.01384013f,
02387         0.20132534f, -0.01536873f, -0.07641169f, 0.05906778f, -0.07833145f,
02388         -0.01523801f, -0.07502609f, -0.09461885f, -0.15013233f, 0.16050665f,
02389         0.09021381f, 0.08473236f, 0.03386267f, -0.09147339f, -0.09170618f,
02390         -0.08498498f, -0.05119187f, -0.10431040f, 0.01041618f, -0.03064913f,
02391         0.09340212f, 0.06448522f, -0.03881054f, -0.04985436f, -0.14794017f,
02392         -0.05200112f, -0.02144495f, 0.04000821f, 0.12420804f, -0.01851651f,
02393         -0.04116732f, -0.11951703f, -0.04879033f, -0.08722515f, -0.08454733f,
02394         -0.10549165f, 0.11251976f, 0.10766345f, 0.19201984f, 0.06128913f,
02395         -0.02734615f, -0.08834923f, -0.16999826f, -0.03548348f,
02396         -5.36092324e-003f, 0.08297954f, 0.07226378f, 0.04194529f, 0.04668673f,
02397         8.73902347e-003f, 0.06980139f, 0.05652480f, 0.05879445f, 0.02477076f,
02398         0.02451423f, 0.12433673f, 0.05600227f, 0.06886370f, 0.03863076f,
02399         0.07459056f, 0.02264139f, 0.01495469f, 0.06344220f, 0.06945208f,
02400         0.02931899f, 0.11719371f, 0.04527427f, 0.03248192f, 2.08271481e-003f,
02401         0.02044626f, 0.11403449f, 0.04303892f, 0.06444661f, 0.04959024f,
02402         0.08174094f, 0.09240247f, 0.04894639f, 0.02252937f, -0.01652530f,
02403         0.07587013f, 0.06064249f, 0.13954395f, 0.02772832f, 0.07093039f,
02404         0.08501238f, 0.01701301f, 0.09055722f, 0.33421436f, 0.20163782f,
02405         0.09821030f, 0.07951369f, 0.08695120f, -0.12757730f, -0.13865978f,
02406         -0.06610068f, -0.10985506f, 0.03406816f, -0.01116336f, -0.07281768f,
02407         -0.13525715f, -0.12844718f, 0.08956250f, 0.09171610f, 0.10092317f,
02408         0.23385370f, 0.34489515f, 0.09901748f, 0.02002922f, 0.12335990f,
02409         0.07606190f, -0.14899330f, -0.15634622f, -0.06494618f, -0.01760547f,
02410         0.03404277f, -0.13208845f, -0.12101169f, -0.18294574f, -0.16560709f,
02411         0.02183887f, -0.02752613f, 0.01813638f, 0.02000757f, 0.01319924f,
02412         0.08030242f, 0.01220535f, 2.98233377e-003f, -0.01307070f, 0.05970297f,
02413         -0.05345284f, -0.03381982f, -9.87543724e-003f, -0.06869387f,
02414         0.03956730f, -0.03108176f, -0.05732809f, 0.02172386f, 0.04159765f,
02415         2.62783933e-003f, 0.04813229f, 0.09358983f, -8.18389002e-003f,
02416         0.01724574f, -0.02547474f, -0.04967288f, -0.02390376f, 0.06640504f,
02417         -0.06306566f, 0.01137518f, 0.05589378f, -0.08237787f, 0.02455001f,
02418         -0.03059422f, -0.08953978f, 0.06851497f, 0.07190268f, -0.07610799f,
02419         7.87237938e-003f, -7.85830803e-003f, 0.06006952f, -0.01126728f,
02420         -2.85743061e-003f, -0.04772895f, 0.01884944f, 0.15005857f,
02421         -0.06268821f, -0.01989072f, 0.01138399f, 0.08760451f, 0.03879007f,
02422         -9.66926850e-003f, -0.08012961f, 0.06414555f, -0.01362950f,
02423         -0.09135523f, 0.01755159f, 0.04459474f, 0.09650917f, 0.05219948f,
02424         -2.19440833e-003f, -0.07037939f, -0.01599054f, 0.13103317f,
02425         -0.02492603f, -0.01032540f, -0.02903307f, 0.04489160f, 0.05148086f,
02426         0.01858173f, -0.02919228f, 0.08299296f, -0.04590359f, -0.15745632f,
02427         -0.09068198f, -0.02972453f, 0.12985018f, 0.22320485f, 0.24261914f,
02428         0.03642650f, -0.05506422f, 2.67413049e-003f, -0.03834032f, 0.06449424f,
02429         0.03834866f, 0.03816991f, 0.25039271f, 0.34212017f, 0.32433882f,
02430         0.18824573f, -0.08599839f, -0.17599408f, -0.15317015f, -0.09913155f,
02431         -0.02856072f, -0.05304699f, -1.06437842e-003f, -0.06641813f,
02432         -0.07509298f, 0.01463361f, -0.07551918f, -0.04510373f,
02433         -8.44620075e-003f, 0.01772176f, 0.04068235f, 0.20295307f, 0.15719447f,
02434         0.05712103f, 0.26296997f, 0.14657754f, 0.01547317f, -0.05052776f,
02435         -0.03881342f, -0.01437883f, -0.04930177f, 0.11719568f, 0.24098417f,
02436         0.26468599f, 0.31698579f, 0.10103608f, -0.01096375f, -0.01367013f,
02437         0.17104232f, 0.20065314f, 2.67622480e-003f, -0.01190034f, 0.18301608f,
02438         0.09459770f, -0.06357619f, -0.06473801f, 0.01377906f, -0.10032775f,
02439         -0.06388740f, 3.80393048e-003f, 0.06206078f, 0.10349120f, 0.26804337f,
02440         8.17918684e-003f, -0.02314351f, 9.34422202e-003f, 0.09198381f,
02441         0.03681326f, -8.77339672e-003f, -0.09662418f, -0.02715708f,
02442         0.13503517f, 0.08962728f, -6.57071499e-003f, -0.03201199f, 0.28510824f,
02443         0.32095715f, 0.18512695f, -0.14230858f, -0.14048551f, -0.07181299f,
02444         -0.08575408f, -0.08661680f, -0.17416079f, 7.54326640e-004f,
02445         0.05601677f, 0.13585392f, -0.04960437f, -0.07708392f, 0.10676333f,
02446         -0.04407546f, -0.07209078f, 0.03663663f, 0.28949317f, 0.41127121f,
02447         0.27431169f, -0.06900328f, -0.21474190f, -0.15578632f, -0.19555484f,
02448         -0.15209621f, -0.11269179f, 0.07416003f, 0.18991330f, 0.26858172f,
02449         0.01952259f, 0.01017922f, 0.02159843f, -4.95165400e-003f, -0.04368168f,
02450         -0.12721671f, -0.06673957f, -0.11275250f, 0.04413409f, 0.05578312f,
02451         0.03896771f, 0.03566417f, -0.05871816f, -0.07388090f, -0.17965563f,
02452         -0.08570268f, -0.15273231f, -0.06022318f, -0.06999847f,
02453         -6.81510568e-003f, 0.06294262f, -6.54901436e-004f, -0.01128654f,
02454         -0.02289657f, 0.04849290f, 0.04140804f, 0.23681939f, 0.14545733f,
02455         0.01989965f, 0.12032662f, 3.87463090e-003f, -6.02597650e-003f,
02456         -0.05919775f, -0.03067224f, -0.07787777f, 0.10834727f, 0.02153730f,
02457         0.02765649f, 0.03975543f, -0.12182906f, -0.04900113f, -0.09940100f,
02458         -0.06453611f, -0.13757215f, -0.03721382f, 0.02827376f, -0.04351249f,
02459         0.01907038f, -0.10284120f, -0.05671160f, -0.10760647f, -0.09624009f,
02460         -0.09565596f, -0.01303654f, 0.03080539f, 0.01416511f, 0.05846142f,
02461         -5.42971538e-003f, 0.06221476f, -0.03320325f, -0.06791797f,
02462         -0.05791342f, 0.12851369f, 0.14990346f, 0.03634374f, 0.14262885f,
02463         0.04330391f, 0.05032569f, -0.05631914f, 0.01606137f, 0.04387223f,
02464         0.22344995f, 0.15722635f, -0.04693628f, 0.03006579f, -2.52882647e-003f,
02465         0.05717621f, -0.07529724f, -0.02848588f, -0.06868757f,
02466         -4.51729307e-003f, 0.06466042f, -0.05935378f, -0.04704857f,
02467         -0.07363959f, 0.04843248f, -0.13421375f, -0.09789340f, -0.10255270f,
02468         0.03509852f, 0.04751543f, -0.03822323f, 0.09740467f, 0.04762916f,
02469         0.03940146f, -0.08283259f, 0.09552965f, 0.05038739f, 0.21258622f,
02470         0.09646992f, 0.03241193f, 0.05167701f, 0.04614570f, 0.04330090f,
02471         -0.02671840f, -0.06259909f, -0.02301898f, 0.18829170f, 0.10522786f,
02472         0.04313190f, 0.01670948f, -0.08421925f, 0.05911417f, -0.10582602f,
02473         -0.04855484f, -0.08373898f, 0.07775915f, 0.03723533f, -0.12047344f,
02474         4.86345543e-003f, -0.10520902f, 0.06571782f, -0.07528137f,
02475         -0.03245651f, -0.09869066f, -0.02917477f, -0.18293270f, 0.14810945f,
02476         9.24033765e-003f, -0.04354914f, 0.02266885f, -0.11872729f,
02477         -0.04016589f, 0.02830229f, 0.22539048f, 0.20565644f, 0.16701797f,
02478         0.09019924f, 0.01300652f, 0.09760600f, -0.03675831f, -0.01935448f,
02479         -0.06894835f, 0.08077277f, 0.19047537f, 0.11312226f, 0.04106043f,
02480         -0.11187182f, 0.04312806f, -0.18548580f, -0.11287174f, -0.08794551f,
02481         0.02078281f, -0.15295486f, 0.11806386f, -0.01103218f, -0.15971117f,
02482         0.02153538f, -0.05232147f, -0.10835317f, -0.13910367f, 0.05920752f,
02483         -0.10122602f, 0.20174250f, 0.09105796f, -0.01881348f, 0.09559010f,
02484         -0.03725745f, -0.09442931f, -0.09763174f, 0.05854454f, 0.08287182f,
02485         0.12919849f, 0.08594352f, -2.49806582e-003f, 0.02398440f,
02486         5.67950122e-003f, -0.06296340f, -0.12993270f, 0.03855852f, 0.05186560f,
02487         0.10839908f, -0.03380463f, -0.12654832f, -0.05399339f, -0.07456800f,
02488         -0.04736232f, -0.10164231f, 0.07496139f, 0.08125214f, 0.07656177f,
02489         -0.04999603f, -0.12823077f, -0.07692395f, -0.11317524f, -0.09118655f,
02490         -0.05695669f, 0.10477209f, 0.07468581f, 0.01630048f, -8.00961629e-003f,
02491         -0.06582128f, -0.04019095f, -0.04682907f, -0.01907842f, -0.10997720f,
02492         0.04911406f, 0.02931030f, 0.04197735f, -0.05773980f, -0.09670641f,
02493         -0.03594951f, -0.03402121f, -0.07149299f, -0.10566200f, 0.10601286f,
02494         0.06340689f, -0.01518632f, -5.96402306e-003f, -0.07628012f,
02495         -3.52779147e-003f, -0.02683854f, -0.10265494f, -0.02680815f,
02496         0.16338381f, 0.03103515f, 0.02296976f, 0.01624348f, -0.10831620f,
02497         -0.02314233f, -0.04789969f, -0.05530700f, -0.06461314f, 0.10494506f,
02498         0.04642856f, -0.07592955f, -0.06197905f, -0.09042154f, -0.01445521f,
02499         -0.04297818f, -0.11262015f, -0.11430512f, 0.03174541f, -0.03677487f,
02500         -0.02963996f, -0.06610169f, -0.13292049f, -0.07059067f, -0.08444111f,
02501         -0.02640536f, -0.07136250f, 0.04559967f, 0.01459980f, 0.17989251f,
02502         0.04435328f, -0.12464730f, -0.02871115f, -0.10752209f, -0.03393742f,
02503         -0.03791408f, 0.02548251f, 0.01956050f, 0.19245651f, 0.13963254f,
02504         -0.05904696f, -0.07424626f, -0.10411884f, 1.54176133e-003f,
02505         0.01797429f, 0.13025844f, 0.04547642f, -0.05710349f, -0.10697161f,
02506         -0.13489437f, -0.06515755f, -0.06406886f, -4.08572936e-003f,
02507         -0.01336483f, 0.04368737f, -0.11259720f, -0.05701635f, -0.06469971f,
02508         -0.08346602f, -0.04166770f, -0.05795543f, -0.08247511f, -0.05742628f,
02509         0.08452254f, -0.03350224f, 0.13980860f, 0.13252275f, 0.07589617f,
02510         0.07539988f, 0.12155797f, 0.19087289f, 0.15050751f, 0.21250245f,
02511         0.14206800f, 0.01298489f, 0.07450245f, 0.06559097f, 0.01700557f,
02512         0.04512971f, 0.16950700f, 0.10261577f, 0.16389982f, 0.05505059f,
02513         -0.03453077f, 0.08622462f, 0.07935954f, 0.03976260f, 0.02036091f,
02514         3.95744899e-003f, 0.03267065f, 0.15235919f, 0.01297494f, -0.08109194f,
02515         0.01407558f, 4.40693414e-003f, -0.15157418f, -0.11390478f,
02516         -0.07487597f, -7.81322457e-003f, -0.02749545f, -0.10181408f,
02517         0.13755716f, 0.14007211f, 0.13482562f, 0.27517235f, 0.34251109f,
02518         0.07639657f, 0.07268607f, 0.19823882f, 0.16135791f, -0.04186463f,
02519         -0.12784107f, -0.09846287f, 0.03169041f, 0.10974082f, -0.15051922f,
02520         -0.08916726f, -0.07138767f, -0.04153349f, 6.25418453e-003f,
02521         0.01266654f, 0.10533249f, 0.12749144f, 0.15148053f, 0.01498513f,
02522         0.06305949f, -0.01247123f, -0.08778401f, -0.08551880f, -0.11955146f,
02523         -0.08493572f, -0.02901620f, -0.02394859f, -0.13427313f, -0.11053200f,
02524         -0.14413260f, -0.15203285f, 0.03972760f, -3.72127310e-004f,
02525         -0.04200919f, 0.06105104f, 0.01904975f, -0.01106191f,
02526         -7.27445772e-003f, -0.01520341f, 1.10228511e-003f, -0.04949187f,
02527         -0.08013099f, 5.72071038e-003f, 0.08415454f, -0.06523152f, 0.03664081f,
02528         -0.02673042f, -0.12066154f, -0.03702074f, 0.06006580f, 0.01628682f,
02529         -6.17772620e-003f, 0.08192339f, -3.41629819e-003f, 0.02870512f,
02530         0.05807141f, 0.04959986f, 0.04618251f, -0.04901629f, -0.10579574f,
02531         0.02274442f, 0.12070961f, 2.23597488e-003f, 0.09831765f, -0.03019848f,
02532         -0.11181970f, -0.04961075f, 0.02498928f, -0.03714991f, -0.01619653f,
02533         0.02643486f, -7.62964319e-003f, -0.02882290f, -0.06242594f,
02534         -0.08439861f, 0.07220893f, 0.07263952f, 0.01561574f, 0.03091968f,
02535         0.01708712f, -0.03797151f, -3.18561122e-003f, 0.01624021f,
02536         -0.02828573f, 0.11284444f, -1.32280716e-003f, -0.07784860f,
02537         -0.07209100f, 0.03372242f, 0.12154529f, 0.02278104f, -0.05275500f,
02538         -0.01918484f, 0.12989293f, 0.05424401f, 0.02333086f, 0.04029022f,
02539         0.12392918f, 0.09495489f, 0.09190340f, 0.07935889f, 8.76816828e-003f,
02540         0.17148446f, -8.51302687e-003f, -0.08011249f, -0.06796283f,
02541         0.04884845f, 0.01112272f, -0.07835306f, -1.14811445e-003f,
02542         -0.03440760f, 0.02845243f, 0.07695542f, -0.07069533f, -0.01151784f,
02543         -8.53884313e-003f, -0.01662786f, -0.04163864f, 0.05400505f,
02544         0.02859163f, 0.02921852f, 0.05003135f, -6.85718050e-003f, -0.01632611f,
02545         0.07780217f, 0.04042810f, -0.01216440f, 3.60914599e-003f, -0.06322435f,
02546         0.09516726f, 0.12877031f, -9.69162490e-003f, 0.01031179f, 0.05180895f,
02547         -9.34659224e-003f, -0.01644533f, -0.04849347f, -0.04343236f,
02548         0.10514783f, 0.08046635f, -0.04615205f, -0.03975486f, -0.01485525f,
02549         0.13096830f, -0.01517950f, -0.06571898f, -0.04016372f, 0.01849786f,
02550         0.02439670f, 0.08067258f, 1.74824719e-003f, 0.07053747f, 0.08819518f,
02551         -5.08352555e-003f, -0.06550863f, -0.08266170f, -0.07780605f,
02552         0.01453450f, -0.08756890f, 0.01096501f, -8.71319138e-003f, 0.10110464f,
02553         0.02420769f, -0.06708383f, 0.02007811f, 5.93133038e-003f, 0.05398923f,
02554         0.07538138f, 0.02049227f, 0.02242589f, 0.04011070f, -1.44875818e-003f,
02555         -4.19115182e-003f, 0.06367654f, 0.02506934f, 0.02434536f, 0.05879405f,
02556         -8.22952855e-003f, -0.01242441f, 0.04224926f, -0.01754923f,
02557         0.05958161f, 0.03818886f, -0.01830363f, -0.04308917f, -0.04422197f,
02558         -0.02432721f, 0.02264866f, 2.03751423e-003f, 0.01197031f, 0.04439203f,
02559         0.12169247f, 0.03602713f, -0.02599251f, -1.98226492e-003f, 0.02046336f,
02560         -0.02639058f, -1.91242550e-003f, -0.09334669f, -0.03595153f,
02561         -9.88179818e-003f, -0.06848445f, -0.04666303f, -0.09955736f,
02562         -0.04206430f, 0.02609075f, 9.09005292e-003f, -0.07138551f,
02563         -4.22313227e-004f, 0.01766645f, 0.02756404f, 0.01308276f, 0.04052891f,
02564         0.02387515f, 0.05337298f, 0.02500631f, -0.04970853f, -0.12467445f,
02565         0.17604403f, 0.12256411f, -0.07512254f, 8.70451052e-003f, -0.05697548f,
02566         -0.03626474f, -8.76623299e-003f, -0.01210897f, -0.09451522f,
02567         0.07490732f, -0.02008001f, -0.02681278f, -0.06463405f, -0.01517507f,
02568         7.33757764e-003f, 6.07147906e-003f, -0.09316964f, -0.04575328f,
02569         0.13261597f, 0.15424870f, -0.01655918f, -0.02772390f, -0.05243644f,
02570         -0.02356456f, -0.02351753f, -0.10211615f, -0.12873036f, 0.14549787f,
02571         0.12519856f, 4.38762689e-003f, 0.02795992f, 0.05170322f, 0.09223596f,
02572         0.05890015f, 0.02376701f, -0.02777346f, 0.09506908f, 0.02328936f,
02573         -0.02319928f, -0.03218696f, -0.01527841f, -0.01016694f, -0.02674719f,
02574         0.05137179f, 0.01980666f, 0.06544447f, -0.01746171f, 0.01026380f,
02575         0.01561806f, 7.97004555e-004f, 0.07601810f, 0.01907250f, -0.03083035f,
02576         -0.05987392f, 0.09242783f, 0.14555025f, 0.01035827f, 0.03092401f,
02577         -0.09562709f, -0.03802354f, 0.02531144f, 0.03079449f, -0.07100715f,
02578         0.03330721f, -2.69116857e-003f, 0.03167490f, 0.05744999f, 0.03259895f,
02579         1.91266940e-003f, 0.03194578f, 0.07389776f, 0.02198060f, 0.07633314f,
02580         0.03293105f, -0.09103648f, 0.04718142f, 0.06102672f, -0.01003063f,
02581         5.85481385e-003f, -0.01522574f, 0.02323526f, 0.10584345f,
02582         4.35879454e-003f, 0.06107873f, 0.05868603f, -0.03115531f, 0.01214679f,
02583         0.08567052f, 3.93926632e-003f, -0.02521488f, -1.88425183e-003f,
02584         0.02038053f, -6.26854831e-004f, 0.04897438f, -0.04280585f,
02585         -0.04819689f, -0.04812867f, -0.01451186f, 0.05101469f,
02586         -9.01125465e-003f, -0.03333859f, 0.03917955f, 0.04196448f, 0.04292135f,
02587         0.02809529f, 0.02999715f, 0.04081348f, 9.10039060e-003f, 0.09703232f,
02588         0.10379741f, 0.02348725f, -4.72756615e-003f, 0.01027325f, 0.10402658f,
02589         0.12071823f, 0.09817299f, -0.02612033f, 0.03638414f, 0.05896405f,
02590         0.04865025f, 0.04793910f, -0.03882321f, -0.02962117f, -0.01222268f,
02591         0.04071597f, 0.01922777f, -0.02287866f, 0.03328381f, 0.01859092f,
02592         0.09024994f, 0.03804455f, -0.01424510f, 0.01953739f, 0.02509617f,
02593         -0.03390914f, -0.05663941f, -0.01641979f, 0.05848591f, 0.04639670f,
02594         0.02092116f, 0.12911791f, 0.19918139f, 0.07739855f, -7.25806039e-003f,
02595         0.04074838f, 0.03183993f, 1.39251316e-003f, -0.01428625f, 0.01865480f,
02596         0.08529541f, 0.13547510f, 0.11189661f, 0.03998901f, 0.09575938f,
02597         -0.02631102f, -0.03458253f, -0.04749985f, -0.06070716f,
02598         4.71884012e-003f, 0.06445789f, -0.02450038f, -0.05483776f,
02599         -0.04657237f, -0.02030717f, -0.03480766f, -0.09397731f, -0.06399718f,
02600         -0.01804585f, 5.62348310e-003f, -6.64811488e-003f, -0.06517869f,
02601         6.96210237e-003f, -0.01860148f, -0.04245830f, -0.05850367f,
02602         -3.24417115e-003f, 0.07700698f, 0.11290991f, 0.09923030f, -0.02970599f,
02603         0.05592411f, 0.04813979f, -0.09811195f, -0.09357996f, -0.03276114f,
02604         0.05218338f, 0.04141375f, 3.92977800e-003f, -0.05047480f, 0.15960084f,
02605         0.04612800f, -0.03114098f, -0.04650044f, -0.03249795f, -0.02425641f,
02606         -0.04311355f, 0.04307659f, -0.09401883f, -0.04742785f, -0.01254499f,
02607         -0.06598741f, 3.41369561e-003f, -0.05620445f, -7.28127593e-003f,
02608         -0.05998361f, -0.03274450f, -0.07376868f, 3.19015374e-003f,
02609         -0.07733069f, 0.05815864f, -0.02471071f, 0.03850617f, 0.13838784f,
02610         0.15399861f, 0.01731321f, -0.01477586f, 0.10393341f, 0.05159833f,
02611         -0.01945555f, -0.03427503f, -0.04867341f, 0.09237480f, 0.10732719f,
02612         0.06071450f, -0.01355071f, 0.01844356f, -0.03480803f, -0.03796671f,
02613         2.15628621e-004f, -0.05440186f, 0.01889855f, -0.01443413f,
02614         -0.02607902f, -0.02938001f, 0.02720689f, -0.06228397f, -0.02970936f,
02615         -0.03426210f, -0.10280876f, -0.06739304f, -0.05227850f, 0.03360292f,
02616         -0.11278441f, -0.06966180f, -0.13937433f, 9.10932291e-003f,
02617         2.52020749e-004f, -4.07359656e-003f, 0.12310639f, 0.09343060f,
02618         0.07302511f, 0.03222093f, 0.07532879f, 0.03792387f, -0.04985180f,
02619         0.01804602f, 0.02694195f, 0.13481498f, 0.04601225f, 0.04106982f,
02620         0.08511057f, 0.12314661f, 0.01320830f, 0.05044121f, -5.52943908e-003f,
02621         -0.08992624f, -0.02249301f, -0.08181777f, 0.06165213f, -0.03256603f,
02622         -0.01068920f, -0.01323473f, -0.11970232f, -0.04616347f, -0.12088681f,
02623         -0.06762606f, -0.08676834f, -0.06434575f, 0.01772529f, 0.03469615f,
02624         -0.10926618f, 0.03013873f, 0.14030397f, 0.16130108f, 0.17985588f,
02625         0.11281928f, 0.10530639f, 0.08905948f, 0.07733764f, 0.06695238f,
02626         0.02142088f, 0.06438877f, 0.09794453f, 0.05745072f, 0.02788557f,
02627         0.02632830f, 0.07985807f, 4.24902979e-003f, 8.47890321e-003f,
02628         -0.02679466f, -5.28812688e-003f, -0.02162580f, -0.07490715f,
02629         -0.08251337f, -0.02056576f, -0.01026194f, -1.15492963e-003f,
02630         -5.75720915e-004f, -0.07210591f, -0.07320981f, -0.04883312f,
02631         -0.10897151f, -0.07477258f, -0.08867134f, -0.09222437f, -0.10924666f,
02632         -0.10430276f, 0.07953499f, 0.02767959f, 0.11393359f, 0.18779543f,
02633         0.03313421f, 0.02143700f, 0.05852016f, -2.12067598e-003f,
02634         -3.76984011e-003f, 0.02774167f, -0.03124610f, 0.01465141f, 0.01616004f,
02635         -0.01391913f, -0.04404102f, -0.05444227f, -0.14684731f, -0.15016587f,
02636         0.04509468f, 1.29563001e-003f, 0.01398350f, 0.05610404f, -0.04868806f,
02637         -0.04776716f, -8.16873740e-003f, -2.30126386e-003f, -0.02286313f,
02638         0.11983398f, -0.04703261f, -0.08814441f, -0.07585249f, -0.10799607f,
02639         -0.03232087f, 0.01509786f, -0.04843464f, -0.03967846f, 0.09589416f,
02640         0.01352560f, -0.01458119f, 0.01050829f, -0.03038946f, 0.01608388f,
02641         1.11975556e-003f, -0.01250656f, 2.86211423e-003f, 0.04333691f,
02642         -0.14603497f, -0.01946543f, -0.02327525f, -0.01973944f, 0.07944400f,
02643         -0.02224544f, -0.06701808f, 0.03476532f, 0.11505594f, -0.02712801f,
02644         -0.01665113f, 0.06315716f, -0.08205860f, 0.07431999f, 0.04915778f,
02645         -0.04468752f, -0.01490402f, 0.07400476f, -0.11650901f, 0.05102430f,
02646         0.04559118f, -0.05916039f, 0.08840760f, -0.01587902f, -0.14890194f,
02647         0.07857784f, 0.04710254f, -0.05381983f, -0.07331945f, -0.03604643f,
02648         0.15611970f, 0.07649943f, -0.05959348f, -0.02776607f, 0.11098688f,
02649         0.03758875f, -0.04446875f, 0.04933187f, 0.01345535f, 0.06921103f,
02650         0.07364785f, 0.05518956f, 0.02899585f, 0.09375840f, 0.10518434f,
02651         -0.04420241f, 0.01915282f, -3.56386811e-003f, 0.14586878f, 0.10286101f,
02652         -0.04360626f, -0.12723237f, 0.09076386f, 0.11119842f, -0.06035013f,
02653         0.09674817f, 0.08938243f, 0.07065924f, 0.02603180f, 5.84815582e-003f,
02654         -0.05922065f, 0.12360309f, 3.59695964e-003f, 2.99844006e-003f,
02655         0.03697936f, 0.02043072f, 0.04168725f, 0.01025975f, -0.01359980f,
02656         -0.01600920f, 0.02581056f, 0.02329250f, 2.98100687e-003f, 0.01629762f,
02657         0.06652115f, 0.05855627f, 0.01237463f, -0.01297135f, 0.01761587f,
02658         0.05090865f, 0.06549342f, -0.04425945f, 2.43203156e-003f,
02659         3.07327788e-003f, 0.06678630f, -0.04303836f, 0.01082393f, -0.06476044f,
02660         0.04077786f, 0.12441979f, 0.08237778f, 0.07424165f, 0.04065890f,
02661         0.06905543f, 0.09556347f, 0.12724875f, -0.02132082f, 0.08514154f,
02662         -0.04175328f, -0.02666954f, 0.01897836f, 0.03317382f, 9.45465732e-003f,
02663         -0.01238974f, -0.04242500f, -0.01419479f, -0.03545213f, -0.02440874f,
02664         0.08684119f, 0.04212951f, 0.02462858f, -0.01104825f, -5.01706870e-003f,
02665         0.02968982f, 0.02597476f, -0.01568939f, 0.04514892f, 0.06974549f,
02666         0.08670278f, 0.06828108f, 0.10238872f, 0.05405957f, 0.06548470f,
02667         -0.03763957f, 0.01366090f, 0.07069602f, 0.05363748f, 0.04798120f,
02668         0.11706422f, 0.05466456f, -0.01869259f, 0.06344382f, 0.03106543f,
02669         0.08432506f, -0.02061096f, 0.03821088f, -6.92190882e-003f,
02670         6.40467042e-003f, -0.01271779f, 6.89014705e-005f, 0.04541415f,
02671         -0.01899539f, -0.05020239f, 0.03000903f, 0.01090422f, 4.52452758e-003f,
02672         0.02573632f, -0.02388454f, -0.04200457f, 1.72783900e-003f,
02673         -0.05978370f, -0.02720562f, 0.06573715f, 0.01154317f, 0.01265615f,
02674         0.07375994f, -9.19828378e-003f, -0.04914120f, 0.02124831f, 0.06455322f,
02675         0.04372910f, -0.03310043f, 0.03605788f, -6.78055827e-003f,
02676         9.36202332e-003f, 0.01747596f, -0.06406314f, -0.06812935f, 0.08080816f,
02677         -0.02778088f, 0.02735260f, 0.06393493f, 0.06652229f, 0.05676993f,
02678         0.08640018f, -7.59188086e-003f, -0.02012847f, -0.04741159f,
02679         -0.01657069f, -0.01624399f, 0.05547778f, -2.33309763e-003f,
02680         0.01120033f, 0.06141156f, -0.06285004f, -0.08732341f, -0.09313398f,
02681         -0.04267832f, 5.57443965e-003f, 0.04809862f, 0.01773641f,
02682         5.37361018e-003f, 0.14842421f, -0.06298012f, -0.02935147f, 0.11443478f,
02683         -0.05034208f, 5.65494271e-003f, 0.02076526f, -0.04577984f,
02684         -0.04735741f, 0.02961071f, -0.09307127f, -0.04417921f, -0.04990027f,
02685         -0.03940028f, 0.01306016f, 0.06267900f, 0.03758737f, 0.08460117f,
02686         0.13858789f, 0.04862388f, -0.06319809f, -0.05655516f, 0.01885816f,
02687         -0.03285607f, 0.03371567f, -0.07040928f, -0.04514049f, 0.01392166f,
02688         0.08184422f, -0.07230316f, 0.02386871f, 0.02184591f, 0.02605764f,
02689         -0.01033954f, 9.29878280e-003f, 7.67351175e-003f, 0.15189242f,
02690         0.02069071f, -0.09738296f, -0.08894105f, -0.07768748f, 0.02332268f,
02691         -0.01778995f, -0.03258888f, -0.08180822f, -0.08492987f, 0.02290156f,
02692         -0.11368170f, -0.03554465f, -0.04533844f, -0.02861580f, 0.06782424f,
02693         0.01113123f, 0.02453644f, 0.12721945f, 0.08084814f, -0.03607795f,
02694         0.01109122f, 0.04803548f, -0.03489929f, 0.03399536f, -0.05682014f,
02695         8.59533902e-003f, -4.27904585e-003f, 0.03230887f, -0.01300198f,
02696         -0.01038137f, -0.07930113f, 8.33097473e-003f, 0.02296994f,
02697         -0.01306500f, -0.01881626f, 0.04413369f, 0.05729880f, -0.03761553f,
02698         0.01942326f, 1.64540811e-003f, -0.03811319f, 0.04190650f, -0.14978096f,
02699         -0.04514487f, 0.01209545f, -5.46460645e-003f, -0.01647195f,
02700         7.63064111e-003f, -0.07494587f, 0.08415288f, 0.10020141f, -0.01228561f,
02701         0.06553826f, 0.04554005f, 0.07890417f, 0.03041138f, 0.01752007f,
02702         0.09208256f, -3.74419295e-004f, 0.10549527f, 0.04686913f, 0.01894833f,
02703         -0.02651412f, -4.34682379e-003f, 5.44942822e-003f, 0.01444484f,
02704         0.05882156f, -0.03336544f, 0.04603891f, -0.10432546f, 0.01923928f,
02705         0.01842845f, -0.01712168f, -0.02222766f, 0.04693324f, -0.06202956f,
02706         -0.01422159f, 0.08732220f, -0.07706107f, 0.02661049f, -0.04300238f,
02707         -0.03092422f, -0.03552184f, -0.01886088f, -0.04979934f, 0.03906401f,
02708         0.04608644f, 0.04966111f, 0.04275464f, -0.04621769f, -0.02653212f,
02709         8.57011229e-003f, 0.03839684f, 0.05818764f, 0.03880796f,
02710         -2.76100676e-004f, 0.03076511f, -0.03266929f, -0.05374557f,
02711         0.04986527f, -9.45429131e-003f, 0.03582499f, -2.64564669e-003f,
02712         -1.07461517e-003f, 0.02962313f, -0.01483363f, 0.03060869f, 0.02448327f,
02713         0.01845641f, 0.03282966f, -0.03534438f, -0.01084059f, -0.01119136f,
02714         -1.85360224e-003f, -5.94652840e-004f, -0.04451817f, 2.98327743e-003f,
02715         0.06272484f, -0.02152076f, -3.05971340e-003f, -0.05070828f,
02716         0.01531762f, 0.01282815f, 0.05167150f, 9.46266949e-003f,
02717         -3.34558333e-003f, 0.11442288f, -0.03906701f, -2.67325155e-003f,
02718         0.03069184f, -0.01134165f, 0.02949462f, 0.02879886f, 0.03855566f,
02719         -0.03450781f, 0.09142872f, -0.02156654f, 0.06075062f, -0.06220816f,
02720         0.01944680f, 6.68372354e-003f, -0.06656796f, 8.70784000e-003f,
02721         0.03456013f, 0.02434320f, -0.13236357f, -0.04177035f, -0.02069627f,
02722         0.01068112f, 0.01505432f, -0.07517391f, -3.83571628e-003f,
02723         -0.06298508f, -0.02881260f, -0.13101046f, -0.07221562f,
02724         -5.79945277e-003f, -8.57300125e-003f, 0.03782469f, 0.02762164f,
02725         0.04942456f, -0.02936396f, 0.09597211f, 0.01921411f, 0.06101191f,
02726         -0.04787507f, -0.01379578f, -7.40224449e-003f, -0.02220136f,
02727         -0.01313756f, 7.77558051e-003f, 0.12296968f, 0.02939998f, 0.03594062f,
02728         -0.07788624f, -0.01133144f, 3.99316690e-004f, -0.06090347f,
02729         -0.01122066f, -4.68682544e-003f, 0.07633100f, -0.06748922f,
02730         -0.05640298f, -0.05265681f, -0.01139122f, -0.01624347f, -0.04715714f,
02731         -0.01099092f, 0.01048561f, 3.28499987e-003f, -0.05810167f,
02732         -0.07699911f, -0.03330683f, 0.04185145f, 0.03478536f, 0.02275165f,
02733         0.02304766f, 6.66040834e-003f, 0.10968148f, -5.93013782e-003f,
02734         -0.04858336f, -0.04203213f, -0.09316786f, -6.13074889e-003f,
02735         -0.02544625f, 0.01366201f, 9.18555818e-003f, -0.01846578f,
02736         -0.05622401f, -0.03989377f, -0.07810296f, 6.91275718e-003f,
02737         0.05957597f, -0.03901334f, 0.01572002f, -0.01193903f,
02738         -6.89400872e-003f, -0.03093356f, -0.04136098f, -0.01562869f,
02739         -0.04604580f, 0.02865234f, -0.08678447f, -0.03232484f, -0.05364593f,
02740         -0.01445016f, -0.07003860f, -0.08669746f, -0.04520775f, 0.04274122f,
02741         0.03117515f, 0.08175703f, 0.01081109f, 0.06379741f, 0.06199206f,
02742         0.02865988f, 0.02360346f, 0.06725410f, -0.03248780f, -9.37702879e-003f,
02743         0.08265898f, -0.02245839f, 0.05125763f, -0.01862395f, 0.01973453f,
02744         -0.01994494f, -0.10770868f, 0.03180375f, 3.23935156e-003f,
02745         -0.02142080f, -0.04256190f, 0.04760900f, 0.04282863f, 0.05635953f,
02746         -0.01870849f, 0.05540622f, -0.03042666f, 0.01455277f, -0.06630179f,
02747         -0.05843807f, -0.03739681f, -0.09739155f, -0.03220233f, -0.05620182f,
02748         -0.10381401f, 0.07400211f, 4.20676917e-003f, 0.03258535f,
02749         2.14308966e-003f, 0.05121966f, -0.01274337f, 0.02384761f, 0.06335578f,
02750         -0.07905591f, 0.08375625f, -0.07898903f, -0.06508528f, -0.02498444f,
02751         0.06535810f, 0.03970535f, 0.04895468f, -0.01169566f, -0.03980601f,
02752         0.05682293f, 0.05925463f, -0.01165808f, -0.07936699f, -0.04208954f,
02753         0.01333987f, 0.09051196f, 0.10098671f, -0.03974256f, 0.01238771f,
02754         -0.07501741f, -0.03655440f, -0.04301528f, 0.09216860f,
02755         4.63579083e-004f, 0.02851115f, 0.02142735f, 1.28244064e-004f,
02756         0.02879687f, -0.08554889f, -0.04838862f, 0.08135369f, -0.05756533f,
02757         0.01413900f, 0.03451880f, -0.06619488f, -0.03053130f, 0.02961676f,
02758         -0.07384635f, 0.01135692f, 0.05283910f, -0.07778034f, -0.02107482f,
02759         -0.05511716f, -0.13473752f, 0.03030157f, 0.06722020f, -0.06218817f,
02760         -0.05826827f, 0.06254654f, 0.02895772f, -0.01664000f, -0.03620280f,
02761         -0.01612278f, -1.46097376e-003f, 0.14013411f, -8.96181818e-003f,
02762         -0.03250246f, 3.38630192e-003f, 2.64779478e-003f, 0.03359732f,
02763         -0.02411991f, -0.04229729f, 0.10666174f, -6.66579151f };
02764     return std::vector<float>(detector, detector + sizeof(detector)/sizeof(detector[0]));
02765 }
02766 
02767 // This function renurn 1981 SVM coeffs obtained from daimler's base.
02768 // To use these coeffs the detection window size should be (48,96)
02769 std::vector<float> HOGDescriptor::getDaimlerPeopleDetector()
02770 {
02771     static const float detector[] = {
02772         0.294350f, -0.098796f, -0.129522f, 0.078753f,
02773         0.387527f, 0.261529f, 0.145939f, 0.061520f,
02774         0.328699f, 0.227148f, -0.066467f, -0.086723f,
02775         0.047559f, 0.106714f, 0.037897f, 0.111461f,
02776         -0.024406f, 0.304769f, 0.254676f, -0.069235f,
02777         0.082566f, 0.147260f, 0.326969f, 0.148888f,
02778         0.055270f, -0.087985f, 0.261720f, 0.143442f,
02779         0.026812f, 0.238212f, 0.194020f, 0.056341f,
02780         -0.025854f, -0.034444f, -0.156631f, 0.205174f,
02781         0.089008f, -0.139811f, -0.100147f, -0.037830f,
02782         -0.029230f, -0.055641f, 0.033248f, -0.016512f,
02783         0.155244f, 0.247315f, -0.124694f, -0.048414f,
02784         -0.062219f, 0.193683f, 0.004574f, 0.055089f,
02785         0.093565f, 0.167712f, 0.167581f, 0.018895f,
02786         0.215258f, 0.122609f, 0.090520f, -0.067219f,
02787         -0.049029f, -0.099615f, 0.241804f, -0.094893f,
02788         -0.176248f, 0.001727f, -0.134473f, 0.104442f,
02789         0.050942f, 0.081165f, 0.072156f, 0.121646f,
02790         0.002656f, -0.297974f, -0.133587f, -0.060121f,
02791         -0.092515f, -0.048974f, -0.084754f, -0.180111f,
02792         -0.038590f, 0.086283f, -0.134636f, -0.107249f,
02793         0.132890f, 0.141556f, 0.249425f, 0.130273f,
02794         -0.030031f, 0.073212f, -0.008155f, 0.019931f,
02795         0.071688f, 0.000300f, -0.019525f, -0.021725f,
02796         -0.040993f, -0.086841f, 0.070124f, 0.240033f,
02797         0.265350f, 0.043208f, 0.166754f, 0.091453f,
02798         0.060916f, -0.036972f, -0.091043f, 0.079873f,
02799         0.219781f, 0.158102f, -0.140618f, -0.043016f,
02800         0.124802f, 0.093668f, 0.103208f, 0.094872f,
02801         0.080541f, 0.137711f, 0.160566f, -0.169231f,
02802         0.013983f, 0.309508f, -0.004217f, -0.057200f,
02803         -0.064489f, 0.014066f, 0.361009f, 0.251328f,
02804         -0.080983f, -0.044183f, 0.061436f, -0.037381f,
02805         -0.078786f, 0.030993f, 0.066314f, 0.037683f,
02806         0.152325f, -0.091683f, 0.070203f, 0.217856f,
02807         0.036435f, -0.076462f, 0.006254f, -0.094431f,
02808         0.154829f, -0.023038f, -0.196961f, -0.024594f,
02809         0.178465f, -0.050139f, -0.045932f, -0.000965f,
02810         0.109112f, 0.046165f, -0.159373f, -0.008713f,
02811         0.041307f, 0.097129f, -0.057211f, -0.064599f,
02812         0.077165f, 0.176167f, 0.138322f, 0.065753f,
02813         -0.104950f, 0.017933f, 0.136255f, -0.011598f,
02814         0.047007f, 0.080550f, 0.068619f, 0.084661f,
02815         -0.035493f, -0.091314f, -0.041411f, 0.060971f,
02816         -0.101912f, -0.079870f, -0.085977f, -0.022686f,
02817         0.079788f, -0.098064f, -0.054603f, 0.040383f,
02818         0.300794f, 0.128603f, 0.094844f, 0.047407f,
02819         0.101825f, 0.061832f, -0.162160f, -0.204553f,
02820         -0.035165f, 0.101450f, -0.016641f, -0.027140f,
02821         -0.134392f, -0.008743f, 0.102331f, 0.114853f,
02822         0.009644f, 0.062823f, 0.237339f, 0.167843f,
02823         0.053066f, -0.012592f, 0.043158f, 0.002305f,
02824         0.065001f, -0.038929f, -0.020356f, 0.152343f,
02825         0.043469f, -0.029967f, -0.042948f, 0.032481f,
02826         0.068488f, -0.110840f, -0.111083f, 0.111980f,
02827         -0.002072f, -0.005562f, 0.082926f, 0.006635f,
02828         -0.108153f, 0.024242f, -0.086464f, -0.189884f,
02829         -0.017492f, 0.191456f, -0.007683f, -0.128769f,
02830         -0.038017f, -0.132380f, 0.091926f, 0.079696f,
02831         -0.106728f, -0.007656f, 0.172744f, 0.011576f,
02832         0.009883f, 0.083258f, -0.026516f, 0.145534f,
02833         0.153924f, -0.130290f, -0.108945f, 0.124490f,
02834         -0.003186f, -0.100485f, 0.015024f, -0.060512f,
02835         0.026288f, -0.086713f, -0.169012f, 0.076517f,
02836         0.215778f, 0.043701f, -0.131642f, -0.012585f,
02837         -0.045181f, -0.118183f, -0.241544f, -0.167293f,
02838         -0.020107f, -0.019917f, -0.101827f, -0.107096f,
02839         -0.010503f, 0.044938f, 0.189680f, 0.217119f,
02840         -0.046086f, 0.044508f, 0.199716f, -0.036004f,
02841         -0.148927f, 0.013355f, -0.078279f, 0.030451f,
02842         0.056301f, -0.024609f, 0.083224f, 0.099533f,
02843         -0.039432f, -0.138880f, 0.005482f, -0.024120f,
02844         -0.140468f, -0.066381f, -0.017057f, 0.009260f,
02845         -0.058004f, -0.028486f, -0.061610f, 0.007483f,
02846         -0.158309f, -0.150687f, -0.044595f, -0.105121f,
02847         -0.045763f, -0.006618f, -0.024419f, -0.117713f,
02848         -0.119366f, -0.175941f, -0.071542f, 0.119027f,
02849         0.111362f, 0.043080f, 0.034889f, 0.093003f,
02850         0.007842f, 0.057368f, -0.108834f, -0.079968f,
02851         0.230959f, 0.020205f, 0.011470f, 0.098877f,
02852         0.101310f, -0.030215f, -0.018018f, -0.059552f,
02853         -0.106157f, 0.021866f, -0.036471f, 0.080051f,
02854         0.041165f, -0.082101f, 0.117726f, 0.030961f,
02855         -0.054763f, -0.084102f, -0.185778f, -0.061305f,
02856         -0.038089f, -0.110728f, -0.264010f, 0.076675f,
02857         -0.077111f, -0.137644f, 0.036232f, 0.277995f,
02858         0.019116f, 0.107738f, 0.144003f, 0.080304f,
02859         0.215036f, 0.228897f, 0.072713f, 0.077773f,
02860         0.120168f, 0.075324f, 0.062730f, 0.122478f,
02861         -0.049008f, 0.164912f, 0.162450f, 0.041246f,
02862         0.009891f, -0.097827f, -0.038700f, -0.023027f,
02863         -0.120020f, 0.203364f, 0.248474f, 0.149810f,
02864         -0.036276f, -0.082814f, -0.090343f, -0.027143f,
02865         -0.075689f, -0.320310f, -0.000500f, -0.143334f,
02866         -0.065077f, -0.186936f, 0.129372f, 0.116431f,
02867         0.181699f, 0.170436f, 0.418854f, 0.460045f,
02868         0.333719f, 0.230515f, 0.047822f, -0.044954f,
02869         -0.068086f, 0.140179f, -0.044821f, 0.085550f,
02870         0.092483f, -0.107296f, -0.130670f, -0.206629f,
02871         0.114601f, -0.317869f, -0.076663f, 0.038680f,
02872         0.212753f, -0.016059f, -0.126526f, -0.163602f,
02873         0.210154f, 0.099887f, -0.126366f, 0.118453f,
02874         0.019309f, -0.021611f, -0.096499f, -0.111809f,
02875         -0.200489f, 0.142854f, 0.228840f, -0.353346f,
02876         -0.179151f, 0.116834f, 0.252389f, -0.031728f,
02877         -0.188135f, -0.158998f, 0.386523f, 0.122315f,
02878         0.209944f, 0.394023f, 0.359030f, 0.260717f,
02879         0.170335f, 0.013683f, -0.142596f, -0.026138f,
02880         -0.011878f, -0.150519f, 0.047159f, -0.107062f,
02881         -0.147347f, -0.187689f, -0.186027f, -0.208048f,
02882         0.058468f, -0.073026f, -0.236556f, -0.079788f,
02883         -0.146216f, -0.058563f, -0.101361f, -0.071294f,
02884         -0.071093f, 0.116919f, 0.234304f, 0.306781f,
02885         0.321866f, 0.240000f, 0.073261f, -0.012173f,
02886         0.026479f, 0.050173f, 0.166127f, 0.228955f,
02887         0.061905f, 0.156460f, 0.205990f, 0.120672f,
02888         0.037350f, 0.167884f, 0.290099f, 0.420900f,
02889         -0.012601f, 0.189839f, 0.306378f, 0.118383f,
02890         -0.095598f, -0.072360f, -0.132496f, -0.224259f,
02891         -0.126021f, 0.022714f, 0.284039f, 0.051369f,
02892         -0.000927f, -0.058735f, -0.083354f, -0.141254f,
02893         -0.187578f, -0.202669f, 0.048902f, 0.246597f,
02894         0.441863f, 0.342519f, 0.066979f, 0.215286f,
02895         0.188191f, -0.072240f, -0.208142f, -0.030196f,
02896         0.178141f, 0.136985f, -0.043374f, -0.181098f,
02897         0.091815f, 0.116177f, -0.126690f, -0.386625f,
02898         0.368165f, 0.269149f, -0.088042f, -0.028823f,
02899         0.092961f, 0.024099f, 0.046112f, 0.176756f,
02900         0.135849f, 0.124955f, 0.195467f, -0.037218f,
02901         0.167217f, 0.188938f, 0.053528f, -0.066561f,
02902         0.133721f, -0.070565f, 0.115898f, 0.152435f,
02903         -0.116993f, -0.110592f, -0.179005f, 0.026668f,
02904         0.080530f, 0.075084f, -0.070401f, 0.012497f,
02905         0.021849f, -0.139764f, -0.022020f, -0.096301f,
02906         -0.064954f, -0.127446f, -0.013806f, -0.108315f,
02907         0.156285f, 0.149867f, -0.011382f, 0.064532f,
02908         0.029168f, 0.027393f, 0.069716f, 0.153735f,
02909         0.038459f, 0.230714f, 0.253840f, 0.059522f,
02910         -0.045053f, 0.014083f, 0.071103f, 0.068747f,
02911         0.095887f, 0.005832f, 0.144887f, 0.026357f,
02912         -0.067359f, -0.044151f, -0.123283f, -0.019911f,
02913         0.005318f, 0.109208f, -0.003201f, -0.021734f,
02914         0.142025f, -0.066907f, -0.120070f, -0.188639f,
02915         0.012472f, -0.048704f, -0.012366f, -0.184828f,
02916         0.168591f, 0.267166f, 0.058208f, -0.044101f,
02917         0.033500f, 0.178558f, 0.104550f, 0.122418f,
02918         0.080177f, 0.173246f, 0.298537f, 0.064173f,
02919         0.053397f, 0.174341f, 0.230984f, 0.117025f,
02920         0.166242f, 0.227781f, 0.120623f, 0.176952f,
02921         -0.011393f, -0.086483f, -0.008270f, 0.051700f,
02922         -0.153369f, -0.058837f, -0.057639f, -0.060115f,
02923         0.026349f, -0.160745f, -0.037894f, -0.048575f,
02924         0.041052f, -0.022112f, 0.060365f, 0.051906f,
02925         0.162657f, 0.138519f, -0.050185f, -0.005938f,
02926         0.071301f, 0.127686f, 0.062342f, 0.144400f,
02927         0.072600f, 0.198436f, 0.246219f, -0.078185f,
02928         -0.036169f, 0.075934f, 0.047328f, -0.013601f,
02929         0.087205f, 0.019900f, 0.022606f, -0.015365f,
02930         -0.092506f, 0.075275f, -0.116375f, 0.050500f,
02931         0.045118f, 0.166567f, 0.072073f, 0.060371f,
02932         0.131747f, -0.169863f, -0.039352f, -0.047486f,
02933         -0.039797f, -0.204312f, 0.021710f, 0.129443f,
02934         -0.021173f, 0.173416f, -0.070794f, -0.063986f,
02935         0.069689f, -0.064099f, -0.123201f, -0.017372f,
02936         -0.206870f, 0.065863f, 0.113226f, 0.024707f,
02937         -0.071341f, -0.066964f, -0.098278f, -0.062927f,
02938         0.075840f, 0.014716f, 0.019378f, 0.132699f,
02939         -0.074191f, -0.089557f, -0.078446f, -0.197488f,
02940         -0.173665f, 0.052583f, 0.044361f, 0.113549f,
02941         0.098492f, 0.077379f, -0.011146f, -0.192593f,
02942         -0.164435f, 0.045568f, 0.205699f, 0.049187f,
02943         -0.082281f, 0.134874f, 0.185499f, 0.034968f,
02944         -0.119561f, -0.112372f, -0.115091f, -0.054042f,
02945         -0.183816f, -0.078100f, 0.190695f, 0.091617f,
02946         0.004257f, -0.041135f, -0.061453f, -0.141592f,
02947         -0.194809f, -0.120638f, 0.020168f, 0.109672f,
02948         0.067398f, -0.015238f, -0.239145f, -0.264671f,
02949         -0.185176f, 0.050472f, 0.020793f, 0.035678f,
02950         0.022839f, -0.052055f, -0.127968f, -0.113049f,
02951         -0.228416f, -0.258281f, -0.053437f, 0.076424f,
02952         0.061450f, 0.237478f, 0.003618f, -0.055865f,
02953         -0.108087f, -0.028937f, 0.045585f, 0.052829f,
02954         -0.001471f, 0.022826f, 0.059565f, -0.104430f,
02955         -0.077266f, -0.211882f, -0.212078f, 0.028074f,
02956         0.075846f, 0.016265f, 0.161879f, 0.134477f,
02957         0.008935f, -0.048041f, 0.074692f, 0.004928f,
02958         -0.025156f, 0.192874f, 0.074410f, 0.308732f,
02959         0.267400f, 0.094208f, -0.005251f, 0.042041f,
02960         -0.032148f, 0.015588f, 0.252869f, 0.175302f,
02961         0.022892f, 0.081673f, 0.063208f, 0.162626f,
02962         0.194426f, 0.233890f, 0.262292f, 0.186930f,
02963         0.084079f, -0.286388f, -0.213034f, -0.048867f,
02964         -0.207669f, -0.170050f, 0.011673f, -0.092958f,
02965         -0.192786f, -0.273536f, 0.230904f, 0.266732f,
02966         0.320519f, 0.297155f, 0.548169f, 0.304922f,
02967         0.132687f, 0.247333f, 0.212488f, -0.271472f,
02968         -0.142105f, -0.002627f, -0.119215f, 0.128383f,
02969         0.100079f, -0.057490f, -0.121902f, -0.228892f,
02970         0.202292f, -0.399795f, -0.371326f, -0.095836f,
02971         -0.063626f, -0.161375f, -0.311180f, -0.294797f,
02972         0.242122f, 0.011788f, 0.095573f, 0.322523f,
02973         0.511840f, 0.322880f, 0.313259f, 0.173331f,
02974         0.002542f, -0.029802f, 0.324766f, -0.326170f,
02975         -0.340547f, -0.138288f, -0.002963f, -0.114060f,
02976         -0.377312f, -0.442570f, 0.212446f, -0.007759f,
02977         -0.011576f, 0.169711f, 0.308689f, 0.317348f,
02978         0.539390f, 0.332845f, 0.057331f, -0.068180f,
02979         0.101994f, 0.266995f, 0.209570f, 0.355730f,
02980         0.091635f, 0.170238f, 0.125215f, 0.274154f,
02981         0.070223f, 0.025515f, 0.049946f, -0.000550f,
02982         0.043715f, -0.141843f, 0.020844f, 0.129871f,
02983         0.256588f, 0.105015f, 0.148339f, 0.170682f,
02984         0.028792f, 0.074037f, 0.160042f, 0.405137f,
02985         0.246187f, 0.352160f, 0.168951f, 0.222263f,
02986         0.264439f, 0.065945f, 0.021963f, -0.075084f,
02987         0.093105f, 0.027318f, 0.098864f, 0.057566f,
02988         -0.080282f, 0.185032f, 0.314419f, 0.333727f,
02989         0.125798f, 0.294919f, 0.386002f, 0.217619f,
02990         -0.183517f, -0.278622f, -0.002342f, -0.027821f,
02991         -0.134266f, -0.331843f, -0.008296f, 0.124564f,
02992         0.053712f, -0.369016f, -0.095036f, 0.209381f,
02993         0.423760f, 0.371760f, 0.106397f, 0.369408f,
02994         0.485608f, 0.231201f, -0.138685f, -0.349208f,
02995         -0.070083f, 0.028991f, -0.081630f, -0.395992f,
02996         -0.146791f, -0.027354f, 0.063396f, -0.272484f,
02997         0.058299f, 0.338207f, 0.110767f, -0.052642f,
02998         -0.233848f, -0.027448f, 0.030328f, 0.155572f,
02999         -0.093826f, 0.019331f, 0.120638f, 0.006292f,
03000         -0.106083f, -0.236290f, -0.140933f, -0.088067f,
03001         -0.025138f, -0.208395f, -0.025502f, 0.144192f,
03002         -0.048353f, -0.106144f, -0.305121f, -0.114147f,
03003         0.090963f, 0.327727f, 0.035606f, -0.093779f,
03004         0.002651f, -0.171081f, -0.188131f, -0.216571f,
03005         -0.209101f, -0.054402f, 0.157147f, -0.057127f,
03006         0.066584f, 0.008988f, 0.041191f, 0.034456f,
03007         -0.078255f, 0.052099f, -0.022239f, 0.066981f,
03008         -0.117520f, -0.072637f, 0.062512f, 0.037570f,
03009         -0.057544f, -0.312359f, 0.034357f, -0.031549f,
03010         0.002566f, -0.207375f, -0.070654f, -0.018786f,
03011         -0.044815f, -0.012814f, -0.076320f, 0.078183f,
03012         0.023877f, 0.117078f, 0.022292f, -0.205424f,
03013         -0.060430f, -0.017296f, -0.004827f, -0.321036f,
03014         -0.092155f, 0.038837f, 0.073190f, -0.067513f,
03015         0.026521f, 0.171945f, 0.087318f, 0.034495f,
03016         -0.034089f, 0.154410f, -0.061431f, 0.007435f,
03017         -0.111094f, -0.095976f, 0.014741f, -0.132324f,
03018         -0.029517f, -0.192160f, 0.098667f, 0.020762f,
03019         0.177050f, -0.064510f, -0.054437f, -0.058678f,
03020         -0.001858f, 0.167602f, 0.015735f, 0.054338f,
03021         0.016477f, 0.186381f, -0.010667f, 0.054692f,
03022         0.126742f, 0.013140f, 0.090353f, -0.133608f,
03023         -0.018017f, -0.152619f, 0.027600f, -0.138700f,
03024         -0.050274f, 0.045141f, -0.118731f, 0.094797f,
03025         -0.167605f, 0.097461f, -0.009131f, 0.199920f,
03026         -0.052976f, 0.158194f, 0.178568f, -0.107600f,
03027         0.009671f, -0.084072f, -0.040258f, -0.205673f,
03028         0.102891f, 0.223511f, 0.042699f, 0.118548f,
03029         -0.021274f, 0.110997f, -0.155121f, 0.027696f,
03030         -0.149968f, 0.051552f, -0.129219f, 0.173524f,
03031         0.073972f, -0.189045f, -0.034523f, -0.106655f,
03032         -0.011843f, -0.197381f, 0.219413f, 0.183197f,
03033         -0.054920f, 0.144955f, 0.036517f, -0.085412f,
03034         -0.229070f, -0.143710f, -0.049486f, 0.156634f,
03035         -0.008673f, -0.064778f, 0.082344f, 0.145673f,
03036         0.002912f, -0.210121f, -0.116564f, 0.078425f,
03037         0.220908f, -0.067594f, 0.048610f, 0.084912f,
03038         -0.066202f, -0.112515f, -0.217767f, -0.082640f,
03039         -0.017414f, 0.230265f, -0.070735f, 0.066073f,
03040         0.215256f, 0.071157f, -0.087220f, -0.202235f,
03041         -0.011918f, 0.099562f, 0.174716f, -0.063845f,
03042         -0.121055f, 0.014367f, 0.132709f, -0.005060f,
03043         -0.244606f, -0.179693f, -0.134690f, 0.023239f,
03044         -0.193116f, -0.076975f, -0.021164f, -0.001938f,
03045         -0.163799f, -0.111437f, -0.210362f, -0.166376f,
03046         0.034754f, 0.010036f, -0.021917f, 0.068014f,
03047         -0.086893f, -0.251746f, -0.267171f, 0.037383f,
03048         0.003966f, 0.033571f, -0.151506f, 0.025437f,
03049         -0.020626f, -0.308454f, -0.343143f, -0.092263f,
03050         -0.026261f, -0.028345f, 0.036036f, 0.035169f,
03051         0.129470f, 0.122205f, 0.015661f, -0.070612f,
03052         -0.094333f, -0.066055f, -0.041083f, 0.159146f,
03053         0.073184f, 0.110044f, 0.174471f, 0.078069f,
03054         -0.014881f, 0.008116f, 0.013209f, 0.075857f,
03055         0.195605f, 0.062714f, 0.067955f, 0.056544f,
03056         -0.153908f, -0.141749f, -0.072550f, 0.033523f,
03057         -0.024665f, 0.134487f, 0.079076f, 0.133562f,
03058         0.227130f, 0.018054f, 0.004928f, 0.169162f,
03059         0.065152f, 0.072160f, 0.131631f, 0.096303f,
03060         0.054288f, 0.106256f, 0.114632f, 0.119038f,
03061         0.515200f, 0.247429f, 0.199134f, 0.211957f,
03062         0.127558f, -0.294684f, -0.194890f, -0.049988f,
03063         -0.112247f, -0.008122f, -0.006176f, 0.037035f,
03064         -0.110881f, -0.249989f, 0.152434f, 0.234621f,
03065         0.153340f, 0.349283f, 0.683049f, 0.157174f,
03066         0.124844f, 0.099136f, 0.064407f, -0.248400f,
03067         -0.155323f, -0.026498f, -0.023450f, 0.049051f,
03068         -0.114187f, 0.007195f, -0.176825f, -0.376926f,
03069         0.366159f, -0.179938f, -0.148508f, 0.006043f,
03070         0.170048f, 0.097866f, -0.102658f, -0.260430f,
03071         0.248868f, 0.037019f, -0.118111f, 0.078176f,
03072         0.194171f, 0.211328f, 0.368612f, 0.361213f,
03073         0.130013f, 0.094650f, 0.227396f, -0.178058f,
03074         -0.114782f, -0.008093f, 0.231080f, -0.011843f,
03075         -0.097917f, -0.325788f, 0.141879f, 0.119738f,
03076         -0.230427f, -0.117419f, -0.114153f, 0.037903f,
03077         0.116383f, 0.218773f, -0.101884f, 0.059466f,
03078         0.119255f, 0.010874f, -0.031449f, 0.045996f,
03079         0.119931f, 0.273760f, 0.311700f, 0.261794f,
03080         0.194809f, 0.339829f, 0.239449f, 0.064140f,
03081         0.077597f, 0.098996f, 0.143534f, 0.184602f,
03082         0.037507f, 0.225494f, 0.096142f, -0.147370f,
03083         -0.207833f, -0.174742f, -0.086391f, -0.038942f,
03084         0.159577f, -0.088492f, -0.000989f, 0.108154f,
03085         -0.025890f, -0.072713f, 0.025997f, -0.006803f,
03086         -0.086879f, -0.011290f, -0.269200f, -0.103450f,
03087         -0.124910f, -0.116340f, 0.141459f, 0.208800f,
03088         0.042268f, 0.265034f, 0.516474f, 0.217591f,
03089         -0.018843f, -0.313328f, -0.168363f, 0.047129f,
03090         0.090480f, -0.109852f, -0.018761f, 0.210669f,
03091         0.281269f, -0.043591f, -0.034147f, -0.237772f,
03092         -0.134843f, -0.072481f, -0.103831f, 0.038355f,
03093         0.308619f, 0.148023f, -0.045867f, -0.123950f,
03094         -0.210860f, -0.064973f, -0.036308f, -0.046731f,
03095         -0.022099f, 0.095776f, 0.409423f, 0.060635f,
03096         -0.065196f, 0.051828f, 0.027981f, -0.009609f,
03097         -0.137681f, -0.095011f, -0.019045f, 0.177278f,
03098         0.009759f, -0.092119f, -0.016958f, -0.133860f,
03099         -0.118421f, -0.032039f, -0.006214f, -0.084541f,
03100         0.063971f, -0.073642f, 0.165676f, 0.110443f,
03101         0.044131f, 0.046568f, 0.053292f, -0.055466f,
03102         0.015512f, 0.371947f, 0.232102f, -0.016923f,
03103         0.103979f, -0.091758f, 0.005907f, 0.209100f,
03104         0.157433f, 0.030518f, 0.250366f, 0.062322f,
03105         0.036720f, 0.094676f, 0.017306f, -0.010328f,
03106         -0.079012f, 0.016781f, -0.112435f, 0.061795f,
03107         0.042543f, -0.126799f, -0.009975f, -0.056760f,
03108         0.046424f, -0.194712f, -0.139399f, -0.037731f,
03109         0.157989f, -0.016261f, 0.123345f, 0.230563f,
03110         0.083300f, -0.016392f, 0.059567f, -0.016035f,
03111         -0.064767f, 0.231945f, 0.156629f, 0.034602f,
03112         0.145628f, 0.041315f, 0.034535f, 0.019967f,
03113         -0.089188f, -0.012091f, 0.307857f, 0.211405f,
03114         -0.025091f, -0.148249f, -0.129384f, 0.063536f,
03115         -0.068603f, -0.067941f, -0.035104f, 0.210832f,
03116         0.063810f, 0.062764f, -0.089889f, -0.030554f,
03117         0.014791f, -0.053362f, -0.037818f, -0.196640f,
03118         0.008388f, -0.082654f, 0.143056f, 0.064221f,
03119         0.069795f, 0.191040f, 0.097321f, -0.028679f,
03120         0.075794f, 0.313154f, 0.086240f, 0.207643f,
03121         0.017809f, 0.122867f, 0.224586f, 0.167403f,
03122         -0.023884f, 0.047434f, 0.344091f, 0.187745f,
03123         0.136177f, 0.141738f, 0.063799f, 0.045233f,
03124         -0.077342f, -0.003525f, -0.165041f, -0.025616f,
03125         -0.073745f, 0.164439f, 0.011200f, -0.145896f,
03126         -0.027954f, -0.061987f, -0.039874f, -0.142775f,
03127         0.151042f, -0.038238f, 0.053152f, 0.078615f,
03128         0.086061f, 0.100593f, 0.128046f, -0.071006f,
03129         -0.116558f, 0.208445f, 0.051086f, 0.076843f,
03130         0.023191f, -0.084781f, -0.011790f, 0.147807f,
03131         -0.048554f, -0.113932f, 0.283322f, 0.190934f,
03132         0.092789f, 0.033018f, -0.142428f, -0.142480f,
03133         -0.099023f, -0.041020f, -0.042760f, 0.203295f,
03134         -0.053475f, 0.042424f, 0.222839f, -0.019167f,
03135         -0.133176f, -0.276216f, -0.031998f, 0.117290f,
03136         0.177827f, -0.059973f, -0.064744f, -0.117040f,
03137         -0.155482f, -0.099531f, 0.164121f, -0.026682f,
03138         -0.093810f, 0.238993f, -0.006506f, 0.007830f,
03139         0.065819f, -0.203643f, -0.100925f, -0.053652f,
03140         -0.130770f, 0.026277f, 0.131796f, 0.032742f,
03141         0.127186f, 0.116694f, -0.161122f, -0.279773f,
03142         -0.252515f, -0.002638f, 0.042812f, 0.096776f,
03143         -0.123280f, 0.064858f, -0.010455f, -0.219760f,
03144         -0.239331f, -0.104363f, -0.058022f, -0.053584f,
03145         0.025611f, 0.005129f, -0.100418f, -0.045712f,
03146         -0.194418f, -0.126366f, -0.030530f, 0.051168f,
03147         0.215959f, 0.172402f, -0.054700f, -0.185995f,
03148         -0.278360f, -0.193693f, -0.040309f, 0.003735f,
03149         -0.007770f, 0.123556f, 0.190179f, -0.077315f,
03150         0.117403f, 0.212942f, 0.012160f, 0.000113f,
03151         0.027331f, 0.040202f, 0.033293f, 0.219438f,
03152         0.184174f, 0.259349f, 0.311206f, 0.082547f,
03153         -0.047875f, -0.078417f, 0.010746f, 0.082620f,
03154         0.311931f, 0.307605f, 0.003863f, 0.021405f,
03155         -0.026388f, -0.019572f, 0.020582f, -0.059353f,
03156         0.025199f, 0.261319f, 0.086316f, 0.143614f,
03157         0.107780f, 0.003900f, -0.188397f, -0.038563f,
03158         -0.106045f, -0.125154f, -0.010509f, 0.054021f,
03159         0.242130f, 0.279152f, 0.215546f, 0.346995f,
03160         0.440856f, 0.237452f, 0.234154f, 0.301646f,
03161         0.168929f, -0.208358f, -0.126848f, 0.010260f,
03162         0.121018f, -0.062975f, -0.052848f, 0.050341f,
03163         -0.061103f, -0.266482f, 0.107186f, 0.140221f,
03164         0.280065f, 0.287889f, 0.373198f, 0.151596f,
03165         0.013593f, 0.115616f, 0.014616f, -0.281710f,
03166         -0.237597f, -0.117305f, -0.000034f, -0.136739f,
03167         -0.196275f, -0.095225f, -0.125310f, -0.250514f,
03168         0.236804f, -0.071805f, -0.037421f, 0.048230f,
03169         0.321596f, 0.063632f, 0.024039f, -0.029133f,
03170         0.230983f, 0.160593f, -0.154355f, -0.013086f,
03171         -0.079929f, 0.094692f, 0.160391f, 0.180239f,
03172         0.053895f, 0.100759f, 0.288631f, 0.038191f,
03173         0.181692f, 0.229682f, 0.440166f, 0.063401f,
03174         0.006273f, 0.020865f, 0.338695f, 0.256244f,
03175         -0.043927f, 0.115617f, 0.003296f, 0.173965f,
03176         0.021318f, -0.040936f, -0.118932f, 0.182380f,
03177         0.235922f, -0.053233f, -0.015053f, -0.101057f,
03178         0.095341f, 0.051111f, 0.161831f, 0.032614f,
03179         0.159496f, 0.072375f, 0.025089f, 0.023748f,
03180         0.029151f, 0.161284f, -0.117717f, -0.036191f,
03181         -0.176822f, -0.162006f, 0.226542f, -0.078329f,
03182         0.043079f, -0.119172f, 0.054614f, -0.101365f,
03183         -0.064541f, -0.115304f, 0.135170f, 0.298872f,
03184         0.098060f, 0.089428f, -0.007497f, 0.110391f,
03185         -0.028824f, 0.020835f, -0.036804f, 0.125411f,
03186         0.192105f, -0.048931f, 0.003086f, -0.010681f,
03187         0.074698f, -0.016263f, 0.096063f, 0.060267f,
03188         -0.007277f, 0.139139f, -0.080635f, 0.036628f,
03189         0.086058f, 0.131979f, 0.085707f, 0.025301f,
03190         0.226094f, 0.194759f, 0.042193f, -0.157846f,
03191         -0.068402f, -0.141450f, -0.112659f, -0.076305f,
03192         -0.069085f, -0.114332f, -0.102005f, 0.132193f,
03193         -0.067042f, 0.106643f, 0.198964f, 0.171616f,
03194         0.167237f, -0.033730f, -0.026755f, 0.083621f,
03195         0.149459f, -0.002799f, -0.000318f, 0.011753f,
03196         0.065889f, -0.089375f, -0.049610f, 0.224579f,
03197         0.216548f, -0.034908f, -0.017851f, -0.088144f,
03198         0.007530f, 0.240268f, 0.073270f, 0.013263f,
03199         0.175323f, 0.012082f, 0.093993f, 0.015282f,
03200         0.105854f, 0.107990f, 0.077798f, -0.096166f,
03201         -0.079607f, 0.177820f, 0.142392f, 0.033337f,
03202         -0.078100f, -0.081616f, -0.046993f, 0.139459f,
03203         0.020272f, -0.123161f, 0.175269f, 0.105217f,
03204         0.057328f, 0.080909f, -0.012612f, -0.097081f,
03205         0.082060f, -0.096716f, -0.063921f, 0.201884f,
03206         0.128166f, -0.035051f, -0.032227f, -0.068139f,
03207         -0.115915f, 0.095080f, -0.086007f, -0.067543f,
03208         0.030776f, 0.032712f, 0.088937f, 0.054336f,
03209         -0.039329f, -0.114022f, 0.171672f, -0.112321f,
03210         -0.217646f, 0.065186f, 0.060223f, 0.192174f,
03211         0.055580f, -0.131107f, -0.144338f, 0.056730f,
03212         -0.034707f, -0.081616f, -0.135298f, -0.000614f,
03213         0.087189f, 0.014614f, 0.067709f, 0.107689f,
03214         0.225780f, 0.084361f, -0.008544f, 0.051649f,
03215         -0.048369f, -0.037739f, -0.060710f, 0.002654f,
03216         0.016935f, 0.085563f, -0.015961f, -0.019265f,
03217         0.111788f, 0.062376f, 0.202019f, 0.047713f,
03218         0.042261f, 0.069716f, 0.242913f, 0.021052f,
03219         -0.072812f, -0.155920f, -0.026436f, 0.035621f,
03220         -0.079300f, -0.028787f, -0.048329f, 0.084718f,
03221         -0.060565f, -0.083750f, -0.164075f, -0.040742f,
03222         -0.086219f, 0.015271f, -0.005204f, -0.016038f,
03223         0.045816f, -0.050433f, -0.077652f, 0.117109f,
03224         0.009611f, -0.009045f, -0.008634f, -0.055373f,
03225         -0.085968f, 0.028527f, -0.054736f, -0.168089f,
03226         0.175839f, 0.071205f, -0.023603f, 0.037907f,
03227         -0.004561f, -0.022634f, 0.123831f, 0.094469f,
03228         -0.072920f, -0.133642f, -0.014032f, -0.142754f,
03229         -0.026999f, -0.199409f, 0.013268f, 0.226989f,
03230         0.048650f, -0.170988f, -0.050141f, 0.007880f,
03231         0.061880f, 0.019078f, -0.043578f, -0.038139f,
03232         0.134814f, 0.054097f, -0.081670f, 0.176838f,
03233         0.047920f, -0.038176f, 0.050406f, -0.107181f,
03234         -0.036279f, 0.027060f, 0.081594f, -0.002820f,
03235         0.090507f, -0.033338f, -0.059571f, 0.013404f,
03236         -0.099860f, 0.073371f, 0.342805f, 0.098305f,
03237         -0.150910f, -0.020822f, -0.056960f, 0.046262f,
03238         -0.043413f, -0.149405f, -0.129105f, -0.010899f,
03239         -0.014229f, -0.179949f, -0.113044f, -0.049468f,
03240         -0.065513f, 0.090269f, -0.011919f, 0.087846f,
03241         0.095796f, 0.146127f, 0.101599f, 0.078066f,
03242         -0.084348f, -0.100002f, -0.020134f, -0.050169f,
03243         0.062122f, 0.014640f, 0.019143f, 0.036543f,
03244         0.180924f, -0.013976f, -0.066768f, -0.001090f,
03245         -0.070419f, -0.004839f, -0.001504f, 0.034483f,
03246         -0.044954f, -0.050336f, -0.088638f, -0.174782f,
03247         -0.116082f, -0.205507f, 0.015587f, -0.042839f,
03248         -0.096879f, -0.144097f, -0.050268f, -0.196796f,
03249         0.109639f, 0.271411f, 0.173732f, 0.108070f,
03250         0.156437f, 0.124255f, 0.097242f, 0.238693f,
03251         0.083941f, 0.109105f, 0.223940f, 0.267188f,
03252         0.027385f, 0.025819f, 0.125070f, 0.093738f,
03253         0.040353f, 0.038645f, -0.012730f, 0.144063f,
03254         0.052931f, -0.009138f, 0.084193f, 0.160272f,
03255         -0.041366f, 0.011951f, -0.121446f, -0.106713f,
03256         -0.047566f, 0.047984f, -0.255224f, -0.076116f,
03257         0.098685f, -0.150845f, -0.171513f, -0.156590f,
03258         0.058331f, 0.187493f, 0.413018f, 0.554265f,
03259         0.372242f, 0.237943f, 0.124571f, 0.110829f,
03260         0.010322f, -0.174477f, -0.067627f, -0.001979f,
03261         0.142913f, 0.040597f, 0.019907f, 0.025963f,
03262         -0.043585f, -0.120732f, 0.099937f, 0.091059f,
03263         0.247307f, 0.204226f, -0.042753f, -0.068580f,
03264         -0.119002f, 0.026722f, 0.034853f, -0.060934f,
03265         -0.025054f, -0.093026f, -0.035372f, -0.233209f,
03266         -0.049869f, -0.039151f, -0.022279f, -0.065380f,
03267         -9.063785f};
03268     return std::vector<float>(detector, detector + sizeof(detector)/sizeof(detector[0]));
03269 }
03270 
03271 class HOGConfInvoker :
03272     public ParallelLoopBody
03273 {
03274 public:
03275     HOGConfInvoker( const HOGDescriptor* _hog, const Mat& _img,
03276         double _hitThreshold, const Size& _padding,
03277         std::vector<DetectionROI>* locs,
03278         std::vector<Rect>* _vec, Mutex* _mtx )
03279     {
03280         hog = _hog;
03281         img = _img;
03282         hitThreshold = _hitThreshold;
03283         padding = _padding;
03284         locations = locs;
03285         vec = _vec;
03286         mtx = _mtx;
03287     }
03288 
03289     void operator()( const Range& range ) const
03290     {
03291         int i, i1 = range.start, i2 = range.end;
03292 
03293         Size maxSz(cvCeil(img.cols/(*locations)[0].scale), cvCeil(img.rows/(*locations)[0].scale));
03294         Mat smallerImgBuf(maxSz, img.type());
03295         std::vector<Point> dets;
03296 
03297         for( i = i1; i < i2; i++ )
03298         {
03299             double scale = (*locations)[i].scale;
03300 
03301             Size sz(cvRound(img.cols / scale), cvRound(img.rows / scale));
03302             Mat smallerImg(sz, img.type(), smallerImgBuf.ptr());
03303 
03304             if( sz == img.size() )
03305                 smallerImg = Mat(sz, img.type(), img.data, img.step);
03306             else
03307                 resize(img, smallerImg, sz);
03308 
03309             hog->detectROI(smallerImg, (*locations)[i].locations, dets, (*locations)[i].confidences, hitThreshold, Size(), padding);
03310             Size scaledWinSize = Size(cvRound(hog->winSize.width*scale), cvRound(hog->winSize.height*scale));
03311             mtx->lock();
03312             for( size_t j = 0; j < dets.size(); j++ )
03313                 vec->push_back(Rect(cvRound(dets[j].x*scale),
03314                                     cvRound(dets[j].y*scale),
03315                                     scaledWinSize.width, scaledWinSize.height));
03316             mtx->unlock();
03317         }
03318     }
03319 
03320     const HOGDescriptor* hog;
03321     Mat img;
03322     double hitThreshold;
03323     std::vector<DetectionROI>* locations;
03324     Size padding;
03325     std::vector<Rect>* vec;
03326     Mutex* mtx;
03327 };
03328 
03329 void HOGDescriptor::detectROI(const cv::Mat& img, const std::vector<cv::Point> &locations,
03330     CV_OUT std::vector<cv::Point>& foundLocations, CV_OUT std::vector<double>& confidences,
03331     double hitThreshold, cv::Size winStride, cv::Size padding) const
03332 {
03333     foundLocations.clear();
03334     confidences.clear();
03335 
03336     if( svmDetector.empty() || locations.empty())
03337         return;
03338 
03339     if( winStride == Size() )
03340         winStride = cellSize;
03341     Size cacheStride(gcd(winStride.width, blockStride.width),
03342                      gcd(winStride.height, blockStride.height));
03343 
03344     size_t nwindows = locations.size();
03345     padding.width = (int)alignSize(std::max(padding.width, 0), cacheStride.width);
03346     padding.height = (int)alignSize(std::max(padding.height, 0), cacheStride.height);
03347     Size paddedImgSize(img.cols + padding.width*2, img.rows + padding.height*2);
03348 
03349     // HOGCache cache(this, img, padding, padding, nwindows == 0, cacheStride);
03350     HOGCache cache(this, img, padding, padding, true, cacheStride);
03351     if( !nwindows )
03352         nwindows = cache.windowsInImage(paddedImgSize, winStride).area();
03353 
03354     const HOGCache::BlockData* blockData = &cache.blockData[0];
03355 
03356     int nblocks = cache.nblocks.area();
03357     int blockHistogramSize = cache.blockHistogramSize;
03358     size_t dsize = getDescriptorSize();
03359 
03360     double rho = svmDetector.size() > dsize ? svmDetector[dsize] : 0;
03361     std::vector<float> blockHist(blockHistogramSize);
03362 
03363 #if CV_SSE2
03364     float partSum[4];
03365 #endif
03366 
03367     for( size_t i = 0; i < nwindows; i++ )
03368     {
03369         Point pt0;
03370         pt0 = locations[i];
03371         if( pt0.x < -padding.width || pt0.x > img.cols + padding.width - winSize.width ||
03372                 pt0.y < -padding.height || pt0.y > img.rows + padding.height - winSize.height )
03373         {
03374             // out of image
03375             confidences.push_back(-10.0);
03376             continue;
03377         }
03378 
03379         double s = rho;
03380         const float* svmVec = &svmDetector[0];
03381         int j, k;
03382 
03383         for( j = 0; j < nblocks; j++, svmVec += blockHistogramSize )
03384         {
03385             const HOGCache::BlockData& bj = blockData[j];
03386             Point pt = pt0 + bj.imgOffset;
03387 
03388             // need to devide this into 4 parts!
03389             const float* vec = cache.getBlock(pt, &blockHist[0]);
03390 #if CV_SSE2
03391             __m128 _vec = _mm_loadu_ps(vec);
03392             __m128 _svmVec = _mm_loadu_ps(svmVec);
03393             __m128 sum = _mm_mul_ps(_svmVec, _vec);
03394 
03395             for( k = 4; k <= blockHistogramSize - 4; k += 4 )
03396             {
03397                 _vec = _mm_loadu_ps(vec + k);
03398                 _svmVec = _mm_loadu_ps(svmVec + k);
03399 
03400                 sum = _mm_add_ps(sum, _mm_mul_ps(_vec, _svmVec));
03401             }
03402 
03403             _mm_storeu_ps(partSum, sum);
03404             double t0 = partSum[0] + partSum[1];
03405             double t1 = partSum[2] + partSum[3];
03406             s += t0 + t1;
03407 #else
03408             for( k = 0; k <= blockHistogramSize - 4; k += 4 )
03409                 s += vec[k]*svmVec[k] + vec[k+1]*svmVec[k+1] +
03410                         vec[k+2]*svmVec[k+2] + vec[k+3]*svmVec[k+3];
03411 #endif
03412             for( ; k < blockHistogramSize; k++ )
03413                 s += vec[k]*svmVec[k];
03414         }
03415         confidences.push_back(s);
03416 
03417         if( s >= hitThreshold )
03418             foundLocations.push_back(pt0);
03419     }
03420 }
03421 
03422 void HOGDescriptor::detectMultiScaleROI(const cv::Mat& img,
03423     CV_OUT std::vector<cv::Rect>& foundLocations, std::vector<DetectionROI>& locations,
03424     double hitThreshold, int groupThreshold) const
03425 {
03426     std::vector<Rect> allCandidates;
03427     Mutex mtx;
03428 
03429     parallel_for_(Range(0, (int)locations.size()),
03430                   HOGConfInvoker(this, img, hitThreshold, Size(8, 8),
03431                                  &locations, &allCandidates, &mtx));
03432 
03433     foundLocations.resize(allCandidates.size());
03434     std::copy(allCandidates.begin(), allCandidates.end(), foundLocations.begin());
03435     cv::groupRectangles (foundLocations, groupThreshold, 0.2);
03436 }
03437 
03438 void HOGDescriptor::readALTModel(String modelfile)
03439 {
03440     // read model from SVMlight format..
03441     FILE *modelfl;
03442     if ((modelfl = fopen(modelfile.c_str(), "rb")) == NULL)
03443     {
03444         String eerr("file not exist");
03445         String efile(__FILE__);
03446         String efunc(__FUNCTION__);
03447         return;//throw Exception(Error::StsError, eerr, efile, efunc, __LINE__);
03448     }
03449     char version_buffer[10];
03450     if (!fread (&version_buffer,sizeof(char),10,modelfl))
03451     {
03452         String eerr("version?");
03453         String efile(__FILE__);
03454         String efunc(__FUNCTION__);
03455         return;//throw Exception(Error::StsError, eerr, efile, efunc, __LINE__);
03456     }
03457     if(strcmp(version_buffer,"V6.01")) {
03458         String eerr("version doesnot match");
03459         String efile(__FILE__);
03460         String efunc(__FUNCTION__);
03461         return;//throw Exception(Error::StsError, eerr, efile, efunc, __LINE__);
03462     }
03463     /* read version number */
03464     int version = 0;
03465     if (!fread (&version,sizeof(int),1,modelfl))
03466     { return;/*throw Exception();*/ }
03467     if (version < 200)
03468     {
03469         String eerr("version doesnot match");
03470         String efile(__FILE__);
03471         String efunc(__FUNCTION__);
03472         return;//throw Exception();
03473     }
03474     int kernel_type;
03475     size_t nread;
03476     nread=fread(&(kernel_type),sizeof(int),1,modelfl);
03477 
03478     {// ignore these
03479         int poly_degree;
03480         nread=fread(&(poly_degree),sizeof(int),1,modelfl);
03481 
03482         double rbf_gamma;
03483         nread=fread(&(rbf_gamma),sizeof(double), 1, modelfl);
03484         double coef_lin;
03485         nread=fread(&(coef_lin),sizeof(double),1,modelfl);
03486         double coef_const;
03487         nread=fread(&(coef_const),sizeof(double),1,modelfl);
03488         int l;
03489         nread=fread(&l,sizeof(int),1,modelfl);
03490         char* custom = new char[l];
03491         nread=fread(custom,sizeof(char),l,modelfl);
03492         delete[] custom;
03493     }
03494     int totwords;
03495     nread=fread(&(totwords),sizeof(int),1,modelfl);
03496     {// ignore these
03497         int totdoc;
03498         nread=fread(&(totdoc),sizeof(int),1,modelfl);
03499         int sv_num;
03500         nread=fread(&(sv_num), sizeof(int),1,modelfl);
03501     }
03502 
03503     double linearbias;
03504     nread=fread(&linearbias, sizeof(double), 1, modelfl);
03505 
03506     std::vector<float> detector;
03507     detector.clear();
03508     if(kernel_type == 0) { /* linear kernel */
03509         /* save linear wts also */
03510         double *linearwt = new double[totwords+1];
03511         int length = totwords;
03512         nread = fread(linearwt, sizeof(double), totwords + 1, modelfl);
03513         if(nread != static_cast<size_t>(length) + 1) {
03514             delete [] linearwt;
03515             return;//throw Exception();
03516         }
03517 
03518         for(int i = 0; i < length; i++)
03519             detector.push_back((float)linearwt[i]);
03520 
03521         detector.push_back((float)-linearbias);
03522         setSVMDetector(detector);
03523         delete [] linearwt;
03524     } else {
03525         return;//throw Exception();
03526     }
03527     fclose(modelfl);
03528 }
03529 
03530 void HOGDescriptor::groupRectangles (std::vector<cv::Rect>& rectList, std::vector<double>& weights, int groupThreshold, double eps) const
03531 {
03532     if( groupThreshold <= 0 || rectList.empty() )
03533     {
03534         return;
03535     }
03536 
03537     CV_Assert(rectList.size() == weights.size());
03538 
03539     std::vector<int> labels;
03540     int nclasses = partition(rectList, labels, SimilarRects(eps));
03541 
03542     std::vector<cv::Rect_<double> > rrects(nclasses);
03543     std::vector<int> numInClass(nclasses, 0);
03544     std::vector<double> foundWeights(nclasses, -std::numeric_limits<double>::max());
03545     int i, j, nlabels = (int)labels.size();
03546 
03547     for( i = 0; i < nlabels; i++ )
03548     {
03549         int cls = labels[i];
03550         rrects[cls].x += rectList[i].x;
03551         rrects[cls].y += rectList[i].y;
03552         rrects[cls].width += rectList[i].width;
03553         rrects[cls].height += rectList[i].height;
03554         foundWeights[cls] = max(foundWeights[cls], weights[i]);
03555         numInClass[cls]++;
03556     }
03557 
03558     for( i = 0; i < nclasses; i++ )
03559     {
03560         // find the average of all ROI in the cluster
03561         cv::Rect_<double> r = rrects[i];
03562         double s = 1.0/numInClass[i];
03563         rrects[i] = cv::Rect_<double>(cv::saturate_cast<double>(r.x*s),
03564             cv::saturate_cast<double>(r.y*s),
03565             cv::saturate_cast<double>(r.width*s),
03566             cv::saturate_cast<double>(r.height*s));
03567     }
03568 
03569     rectList.clear();
03570     weights.clear();
03571 
03572     for( i = 0; i < nclasses; i++ )
03573     {
03574         cv::Rect r1 = rrects[i];
03575         int n1 = numInClass[i];
03576         double w1 = foundWeights[i];
03577         if( n1 <= groupThreshold )
03578             continue;
03579         // filter out small rectangles inside large rectangles
03580         for( j = 0; j < nclasses; j++ )
03581         {
03582             int n2 = numInClass[j];
03583 
03584             if( j == i || n2 <= groupThreshold )
03585                 continue;
03586 
03587             cv::Rect r2 = rrects[j];
03588 
03589             int dx = cv::saturate_cast<int>( r2.width * eps );
03590             int dy = cv::saturate_cast<int>( r2.height * eps );
03591 
03592             if( r1.x >= r2.x - dx &&
03593                 r1.y >= r2.y - dy &&
03594                 r1.x + r1.width <= r2.x + r2.width + dx &&
03595                 r1.y + r1.height <= r2.y + r2.height + dy &&
03596                 (n2 > std::max(3, n1) || n1 < 3) )
03597                 break;
03598         }
03599 
03600         if( j == nclasses )
03601         {
03602             rectList.push_back(r1);
03603             weights.push_back(w1);
03604         }
03605     }
03606 }
03607 }
03608