Home | History | Annotate | Download | only in traincascade
      1 #include "opencv2/core.hpp"
      2 #include "opencv2/imgproc.hpp"
      3 
      4 #include "HOGfeatures.h"
      5 #include "cascadeclassifier.h"
      6 
      7 using namespace std;
      8 using namespace cv;
      9 
     10 CvHOGFeatureParams::CvHOGFeatureParams()
     11 {
     12     maxCatCount = 0;
     13     name = HOGF_NAME;
     14     featSize = N_BINS * N_CELLS;
     15 }
     16 
     17 void CvHOGEvaluator::init(const CvFeatureParams *_featureParams, int _maxSampleCount, Size _winSize)
     18 {
     19     CV_Assert( _maxSampleCount > 0);
     20     int cols = (_winSize.width + 1) * (_winSize.height + 1);
     21     for (int bin = 0; bin < N_BINS; bin++)
     22     {
     23         hist.push_back(Mat(_maxSampleCount, cols, CV_32FC1));
     24     }
     25     normSum.create( (int)_maxSampleCount, cols, CV_32FC1 );
     26     CvFeatureEvaluator::init( _featureParams, _maxSampleCount, _winSize );
     27 }
     28 
     29 void CvHOGEvaluator::setImage(const Mat &img, uchar clsLabel, int idx)
     30 {
     31     CV_DbgAssert( !hist.empty());
     32     CvFeatureEvaluator::setImage( img, clsLabel, idx );
     33     vector<Mat> integralHist;
     34     for (int bin = 0; bin < N_BINS; bin++)
     35     {
     36         integralHist.push_back( Mat(winSize.height + 1, winSize.width + 1, hist[bin].type(), hist[bin].ptr<float>((int)idx)) );
     37     }
     38     Mat integralNorm(winSize.height + 1, winSize.width + 1, normSum.type(), normSum.ptr<float>((int)idx));
     39     integralHistogram(img, integralHist, integralNorm, (int)N_BINS);
     40 }
     41 
     42 //void CvHOGEvaluator::writeFeatures( FileStorage &fs, const Mat& featureMap ) const
     43 //{
     44 //    _writeFeatures( features, fs, featureMap );
     45 //}
     46 
     47 void CvHOGEvaluator::writeFeatures( FileStorage &fs, const Mat& featureMap ) const
     48 {
     49     int featIdx;
     50     int componentIdx;
     51     const Mat_<int>& featureMap_ = (const Mat_<int>&)featureMap;
     52     fs << FEATURES << "[";
     53     for ( int fi = 0; fi < featureMap.cols; fi++ )
     54         if ( featureMap_(0, fi) >= 0 )
     55         {
     56             fs << "{";
     57             featIdx = fi / getFeatureSize();
     58             componentIdx = fi % getFeatureSize();
     59             features[featIdx].write( fs, componentIdx );
     60             fs << "}";
     61         }
     62     fs << "]";
     63 }
     64 
     65 void CvHOGEvaluator::generateFeatures()
     66 {
     67     int offset = winSize.width + 1;
     68     Size blockStep;
     69     int x, y, t, w, h;
     70 
     71     for (t = 8; t <= winSize.width/2; t+=8) //t = size of a cell. blocksize = 4*cellSize
     72     {
     73         blockStep = Size(4,4);
     74         w = 2*t; //width of a block
     75         h = 2*t; //height of a block
     76         for (x = 0; x <= winSize.width - w; x += blockStep.width)
     77         {
     78             for (y = 0; y <= winSize.height - h; y += blockStep.height)
     79             {
     80                 features.push_back(Feature(offset, x, y, t, t));
     81             }
     82         }
     83         w = 2*t;
     84         h = 4*t;
     85         for (x = 0; x <= winSize.width - w; x += blockStep.width)
     86         {
     87             for (y = 0; y <= winSize.height - h; y += blockStep.height)
     88             {
     89                 features.push_back(Feature(offset, x, y, t, 2*t));
     90             }
     91         }
     92         w = 4*t;
     93         h = 2*t;
     94         for (x = 0; x <= winSize.width - w; x += blockStep.width)
     95         {
     96             for (y = 0; y <= winSize.height - h; y += blockStep.height)
     97             {
     98                 features.push_back(Feature(offset, x, y, 2*t, t));
     99             }
    100         }
    101     }
    102 
    103     numFeatures = (int)features.size();
    104 }
    105 
    106 CvHOGEvaluator::Feature::Feature()
    107 {
    108     for (int i = 0; i < N_CELLS; i++)
    109     {
    110         rect[i] = Rect(0, 0, 0, 0);
    111     }
    112 }
    113 
    114 CvHOGEvaluator::Feature::Feature( int offset, int x, int y, int cellW, int cellH )
    115 {
    116     rect[0] = Rect(x, y, cellW, cellH); //cell0
    117     rect[1] = Rect(x+cellW, y, cellW, cellH); //cell1
    118     rect[2] = Rect(x, y+cellH, cellW, cellH); //cell2
    119     rect[3] = Rect(x+cellW, y+cellH, cellW, cellH); //cell3
    120 
    121     for (int i = 0; i < N_CELLS; i++)
    122     {
    123         CV_SUM_OFFSETS(fastRect[i].p0, fastRect[i].p1, fastRect[i].p2, fastRect[i].p3, rect[i], offset);
    124     }
    125 }
    126 
    127 void CvHOGEvaluator::Feature::write(FileStorage &fs) const
    128 {
    129     fs << CC_RECTS << "[";
    130     for( int i = 0; i < N_CELLS; i++ )
    131     {
    132         fs << "[:" << rect[i].x << rect[i].y << rect[i].width << rect[i].height << "]";
    133     }
    134     fs << "]";
    135 }
    136 
    137 //cell and bin idx writing
    138 //void CvHOGEvaluator::Feature::write(FileStorage &fs, int varIdx) const
    139 //{
    140 //    int featComponent = varIdx % (N_CELLS * N_BINS);
    141 //    int cellIdx = featComponent / N_BINS;
    142 //    int binIdx = featComponent % N_BINS;
    143 //
    144 //    fs << CC_RECTS << "[:" << rect[cellIdx].x << rect[cellIdx].y <<
    145 //        rect[cellIdx].width << rect[cellIdx].height << binIdx << "]";
    146 //}
    147 
    148 //cell[0] and featComponent idx writing. By cell[0] it's possible to recover all block
    149 //All block is nessesary for block normalization
    150 void CvHOGEvaluator::Feature::write(FileStorage &fs, int featComponentIdx) const
    151 {
    152     fs << CC_RECT << "[:" << rect[0].x << rect[0].y <<
    153         rect[0].width << rect[0].height << featComponentIdx << "]";
    154 }
    155 
    156 
    157 void CvHOGEvaluator::integralHistogram(const Mat &img, vector<Mat> &histogram, Mat &norm, int nbins) const
    158 {
    159     CV_Assert( img.type() == CV_8U || img.type() == CV_8UC3 );
    160     int x, y, binIdx;
    161 
    162     Size gradSize(img.size());
    163     Size histSize(histogram[0].size());
    164     Mat grad(gradSize, CV_32F);
    165     Mat qangle(gradSize, CV_8U);
    166 
    167     AutoBuffer<int> mapbuf(gradSize.width + gradSize.height + 4);
    168     int* xmap = (int*)mapbuf + 1;
    169     int* ymap = xmap + gradSize.width + 2;
    170 
    171     const int borderType = (int)BORDER_REPLICATE;
    172 
    173     for( x = -1; x < gradSize.width + 1; x++ )
    174         xmap[x] = borderInterpolate(x, gradSize.width, borderType);
    175     for( y = -1; y < gradSize.height + 1; y++ )
    176         ymap[y] = borderInterpolate(y, gradSize.height, borderType);
    177 
    178     int width = gradSize.width;
    179     AutoBuffer<float> _dbuf(width*4);
    180     float* dbuf = _dbuf;
    181     Mat Dx(1, width, CV_32F, dbuf);
    182     Mat Dy(1, width, CV_32F, dbuf + width);
    183     Mat Mag(1, width, CV_32F, dbuf + width*2);
    184     Mat Angle(1, width, CV_32F, dbuf + width*3);
    185 
    186     float angleScale = (float)(nbins/CV_PI);
    187 
    188     for( y = 0; y < gradSize.height; y++ )
    189     {
    190         const uchar* currPtr = img.ptr(ymap[y]);
    191         const uchar* prevPtr = img.ptr(ymap[y-1]);
    192         const uchar* nextPtr = img.ptr(ymap[y+1]);
    193         float* gradPtr = grad.ptr<float>(y);
    194         uchar* qanglePtr = qangle.ptr(y);
    195 
    196         for( x = 0; x < width; x++ )
    197         {
    198             dbuf[x] = (float)(currPtr[xmap[x+1]] - currPtr[xmap[x-1]]);
    199             dbuf[width + x] = (float)(nextPtr[xmap[x]] - prevPtr[xmap[x]]);
    200         }
    201         cartToPolar( Dx, Dy, Mag, Angle, false );
    202         for( x = 0; x < width; x++ )
    203         {
    204             float mag = dbuf[x+width*2];
    205             float angle = dbuf[x+width*3];
    206             angle = angle*angleScale - 0.5f;
    207             int bidx = cvFloor(angle);
    208             angle -= bidx;
    209             if( bidx < 0 )
    210                 bidx += nbins;
    211             else if( bidx >= nbins )
    212                 bidx -= nbins;
    213 
    214             qanglePtr[x] = (uchar)bidx;
    215             gradPtr[x] = mag;
    216         }
    217     }
    218     integral(grad, norm, grad.depth());
    219 
    220     float* histBuf;
    221     const float* magBuf;
    222     const uchar* binsBuf;
    223 
    224     int binsStep = (int)( qangle.step / sizeof(uchar) );
    225     int histStep = (int)( histogram[0].step / sizeof(float) );
    226     int magStep = (int)( grad.step / sizeof(float) );
    227     for( binIdx = 0; binIdx < nbins; binIdx++ )
    228     {
    229         histBuf = histogram[binIdx].ptr<float>();
    230         magBuf = grad.ptr<float>();
    231         binsBuf = qangle.ptr();
    232 
    233         memset( histBuf, 0, histSize.width * sizeof(histBuf[0]) );
    234         histBuf += histStep + 1;
    235         for( y = 0; y < qangle.rows; y++ )
    236         {
    237             histBuf[-1] = 0.f;
    238             float strSum = 0.f;
    239             for( x = 0; x < qangle.cols; x++ )
    240             {
    241                 if( binsBuf[x] == binIdx )
    242                     strSum += magBuf[x];
    243                 histBuf[x] = histBuf[-histStep + x] + strSum;
    244             }
    245             histBuf += histStep;
    246             binsBuf += binsStep;
    247             magBuf += magStep;
    248         }
    249     }
    250 }
    251