opencv/apps/traincascade/HOGfeatures.cpp
Andrey Kamaev 2a6fb2867e Remove all using directives for STL namespace and members
Made all STL usages explicit to be able automatically find all usages of
particular class or function.
2013-02-25 15:04:17 +04:00

250 lines
7.7 KiB
C++

#include "opencv2/core/core.hpp"
#include "opencv2/core/internal.hpp"
#include "HOGfeatures.h"
#include "cascadeclassifier.h"
using namespace std;
CvHOGFeatureParams::CvHOGFeatureParams()
{
maxCatCount = 0;
name = HOGF_NAME;
featSize = N_BINS * N_CELLS;
}
void CvHOGEvaluator::init(const CvFeatureParams *_featureParams, int _maxSampleCount, Size _winSize)
{
CV_Assert( _maxSampleCount > 0);
int cols = (_winSize.width + 1) * (_winSize.height + 1);
for (int bin = 0; bin < N_BINS; bin++)
{
hist.push_back(Mat(_maxSampleCount, cols, CV_32FC1));
}
normSum.create( (int)_maxSampleCount, cols, CV_32FC1 );
CvFeatureEvaluator::init( _featureParams, _maxSampleCount, _winSize );
}
void CvHOGEvaluator::setImage(const Mat &img, uchar clsLabel, int idx)
{
CV_DbgAssert( !hist.empty());
CvFeatureEvaluator::setImage( img, clsLabel, idx );
vector<Mat> integralHist;
for (int bin = 0; bin < N_BINS; bin++)
{
integralHist.push_back( Mat(winSize.height + 1, winSize.width + 1, hist[bin].type(), hist[bin].ptr<float>((int)idx)) );
}
Mat integralNorm(winSize.height + 1, winSize.width + 1, normSum.type(), normSum.ptr<float>((int)idx));
integralHistogram(img, integralHist, integralNorm, (int)N_BINS);
}
//void CvHOGEvaluator::writeFeatures( FileStorage &fs, const Mat& featureMap ) const
//{
// _writeFeatures( features, fs, featureMap );
//}
void CvHOGEvaluator::writeFeatures( FileStorage &fs, const Mat& featureMap ) const
{
int featIdx;
int componentIdx;
const Mat_<int>& featureMap_ = (const Mat_<int>&)featureMap;
fs << FEATURES << "[";
for ( int fi = 0; fi < featureMap.cols; fi++ )
if ( featureMap_(0, fi) >= 0 )
{
fs << "{";
featIdx = fi / getFeatureSize();
componentIdx = fi % getFeatureSize();
features[featIdx].write( fs, componentIdx );
fs << "}";
}
fs << "]";
}
void CvHOGEvaluator::generateFeatures()
{
int offset = winSize.width + 1;
Size blockStep;
int x, y, t, w, h;
for (t = 8; t <= winSize.width/2; t+=8) //t = size of a cell. blocksize = 4*cellSize
{
blockStep = Size(4,4);
w = 2*t; //width of a block
h = 2*t; //height of a block
for (x = 0; x <= winSize.width - w; x += blockStep.width)
{
for (y = 0; y <= winSize.height - h; y += blockStep.height)
{
features.push_back(Feature(offset, x, y, t, t));
}
}
w = 2*t;
h = 4*t;
for (x = 0; x <= winSize.width - w; x += blockStep.width)
{
for (y = 0; y <= winSize.height - h; y += blockStep.height)
{
features.push_back(Feature(offset, x, y, t, 2*t));
}
}
w = 4*t;
h = 2*t;
for (x = 0; x <= winSize.width - w; x += blockStep.width)
{
for (y = 0; y <= winSize.height - h; y += blockStep.height)
{
features.push_back(Feature(offset, x, y, 2*t, t));
}
}
}
numFeatures = (int)features.size();
}
CvHOGEvaluator::Feature::Feature()
{
for (int i = 0; i < N_CELLS; i++)
{
rect[i] = Rect(0, 0, 0, 0);
}
}
CvHOGEvaluator::Feature::Feature( int offset, int x, int y, int cellW, int cellH )
{
rect[0] = Rect(x, y, cellW, cellH); //cell0
rect[1] = Rect(x+cellW, y, cellW, cellH); //cell1
rect[2] = Rect(x, y+cellH, cellW, cellH); //cell2
rect[3] = Rect(x+cellW, y+cellH, cellW, cellH); //cell3
for (int i = 0; i < N_CELLS; i++)
{
CV_SUM_OFFSETS(fastRect[i].p0, fastRect[i].p1, fastRect[i].p2, fastRect[i].p3, rect[i], offset);
}
}
void CvHOGEvaluator::Feature::write(FileStorage &fs) const
{
fs << CC_RECTS << "[";
for( int i = 0; i < N_CELLS; i++ )
{
fs << "[:" << rect[i].x << rect[i].y << rect[i].width << rect[i].height << "]";
}
fs << "]";
}
//cell and bin idx writing
//void CvHOGEvaluator::Feature::write(FileStorage &fs, int varIdx) const
//{
// int featComponent = varIdx % (N_CELLS * N_BINS);
// int cellIdx = featComponent / N_BINS;
// int binIdx = featComponent % N_BINS;
//
// fs << CC_RECTS << "[:" << rect[cellIdx].x << rect[cellIdx].y <<
// rect[cellIdx].width << rect[cellIdx].height << binIdx << "]";
//}
//cell[0] and featComponent idx writing. By cell[0] it's possible to recover all block
//All block is nessesary for block normalization
void CvHOGEvaluator::Feature::write(FileStorage &fs, int featComponentIdx) const
{
fs << CC_RECT << "[:" << rect[0].x << rect[0].y <<
rect[0].width << rect[0].height << featComponentIdx << "]";
}
void CvHOGEvaluator::integralHistogram(const Mat &img, vector<Mat> &histogram, Mat &norm, int nbins) const
{
CV_Assert( img.type() == CV_8U || img.type() == CV_8UC3 );
int x, y, binIdx;
Size gradSize(img.size());
Size histSize(histogram[0].size());
Mat grad(gradSize, CV_32F);
Mat qangle(gradSize, CV_8U);
AutoBuffer<int> mapbuf(gradSize.width + gradSize.height + 4);
int* xmap = (int*)mapbuf + 1;
int* ymap = xmap + gradSize.width + 2;
const int borderType = (int)BORDER_REPLICATE;
for( x = -1; x < gradSize.width + 1; x++ )
xmap[x] = borderInterpolate(x, gradSize.width, borderType);
for( y = -1; y < gradSize.height + 1; y++ )
ymap[y] = borderInterpolate(y, gradSize.height, borderType);
int width = gradSize.width;
AutoBuffer<float> _dbuf(width*4);
float* dbuf = _dbuf;
Mat Dx(1, width, CV_32F, dbuf);
Mat Dy(1, width, CV_32F, dbuf + width);
Mat Mag(1, width, CV_32F, dbuf + width*2);
Mat Angle(1, width, CV_32F, dbuf + width*3);
float angleScale = (float)(nbins/CV_PI);
for( y = 0; y < gradSize.height; y++ )
{
const uchar* currPtr = img.data + img.step*ymap[y];
const uchar* prevPtr = img.data + img.step*ymap[y-1];
const uchar* nextPtr = img.data + img.step*ymap[y+1];
float* gradPtr = (float*)grad.ptr(y);
uchar* qanglePtr = (uchar*)qangle.ptr(y);
for( x = 0; x < width; x++ )
{
dbuf[x] = (float)(currPtr[xmap[x+1]] - currPtr[xmap[x-1]]);
dbuf[width + x] = (float)(nextPtr[xmap[x]] - prevPtr[xmap[x]]);
}
cartToPolar( Dx, Dy, Mag, Angle, false );
for( x = 0; x < width; x++ )
{
float mag = dbuf[x+width*2];
float angle = dbuf[x+width*3];
angle = angle*angleScale - 0.5f;
int bidx = cvFloor(angle);
angle -= bidx;
if( bidx < 0 )
bidx += nbins;
else if( bidx >= nbins )
bidx -= nbins;
qanglePtr[x] = (uchar)bidx;
gradPtr[x] = mag;
}
}
integral(grad, norm, grad.depth());
float* histBuf;
const float* magBuf;
const uchar* binsBuf;
int binsStep = (int)( qangle.step / sizeof(uchar) );
int histStep = (int)( histogram[0].step / sizeof(float) );
int magStep = (int)( grad.step / sizeof(float) );
for( binIdx = 0; binIdx < nbins; binIdx++ )
{
histBuf = (float*)histogram[binIdx].data;
magBuf = (const float*)grad.data;
binsBuf = (const uchar*)qangle.data;
memset( histBuf, 0, histSize.width * sizeof(histBuf[0]) );
histBuf += histStep + 1;
for( y = 0; y < qangle.rows; y++ )
{
histBuf[-1] = 0.f;
float strSum = 0.f;
for( x = 0; x < qangle.cols; x++ )
{
if( binsBuf[x] == binIdx )
strSum += magBuf[x];
histBuf[x] = histBuf[-histStep + x] + strSum;
}
histBuf += histStep;
binsBuf += binsStep;
magBuf += magStep;
}
}
}