00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "Features/HistogramOfGradients.H"
00040 #include "Image/DrawOps.H"
00041 #include "Image/MathOps.H"
00042 #include "Image/Kernels.H"
00043 #include "Image/CutPaste.H"
00044 #include "Image/ColorOps.H"
00045 #include "Image/FilterOps.H"
00046 #include "Image/ShapeOps.H"
00047
00048
00049 HistogramOfGradients::HistogramOfGradients(bool normalize, Dims cellDims, bool fixedCells, int numOrientations, bool signedOrient) :
00050 itsNormalize(normalize),
00051 itsCellDims(cellDims),
00052 itsFixedDims(fixedCells),
00053 itsOriBins(numOrientations),
00054 itsOriSigned(signedOrient),
00055 itsEpsilon(0.0001F)
00056 {
00057
00058 }
00059
00060 HistogramOfGradients::~HistogramOfGradients()
00061 {
00062 }
00063
00064 std::vector<float> HistogramOfGradients::createHistogram(const Image<float>& img, const Image<float>& img2, const Image<float>& img3)
00065 {
00066 Image<float> gradmag, gradang;
00067 calculateGradient(img,img2,img3,gradmag,gradang);
00068 return createHistogramFromGradient(gradmag,gradang);
00069 }
00070
00071
00072 void HistogramOfGradients::calculateGradient(const Image<float>& img, const Image<float>& img2, const Image<float>& img3, Image<float>& gradmag, Image<float>&gradang)
00073 {
00074
00075 gradientSobel(img, gradmag, gradang);
00076
00077 if(img2.initialized())
00078 {
00079 Image<float> gradmag2, gradang2;
00080
00081 gradientSobel(img2,gradmag2,gradang2);
00082
00083 takeLinkedMax(gradmag,gradmag2,gradang,gradang2,gradmag,gradang);
00084 }
00085
00086 if(img3.initialized())
00087 {
00088 Image<float> gradmag3, gradang3;
00089
00090 gradientSobel(img3,gradmag3,gradang3);
00091
00092 takeLinkedMax(gradmag,gradmag3,gradang,gradang3,gradmag,gradang);
00093 }
00094
00095 }
00096
00097 std::vector<float> HistogramOfGradients::createHistogramFromGradient(const Image<float>& gradmag, const Image<float>& gradang)
00098 {
00099
00100
00101 Dims cells;
00102 if(itsFixedDims)
00103 cells = itsCellDims;
00104 else
00105 cells = Dims(int(round(float(gradmag.getWidth())/itsCellDims.w())),int(round(float(gradmag.getHeight())/itsCellDims.h())));
00106
00107 FeatureVector fv = FeatureVector(cells.w(),cells.h(),itsOriBins);
00108
00109
00110
00111 for (int rx=1; rx<gradmag.getWidth()-1; rx++)
00112 for (int ry=1; ry<gradmag.getHeight()-1; ry++)
00113 {
00114 if(!gradmag.coordsOk(rx,ry))
00115 continue;
00116
00117 const float xf = float(rx)/float(gradmag.getWidth())*cells.w();
00118 const float yf = float(ry)/float(gradmag.getHeight())*cells.h();
00119
00120 float gradMag = gradmag.getValInterp(rx, ry);
00121 float gradAng = gradang.getValInterp(rx, ry);
00122
00123
00124 addToBin(xf,yf,gradAng,gradMag,itsOriSigned,fv);
00125
00126 }
00127
00128 std::vector<float> returnVec;
00129
00130 if(itsNormalize)
00131 {
00132 LINFO("Normalizing feature vector");
00133 returnVec = normalizeFeatureVector(fv);
00134 }
00135 else
00136 returnVec = fv.getFeatureVector();
00137 LINFO("Calculated HOG of size %Zu",returnVec.size());
00138 return returnVec;
00139
00140 }
00141
00142 std::vector<float> HistogramOfGradients::normalizeFeatureVector(FeatureVector featureVector)
00143 {
00144 std::vector<float> fv = featureVector.getFeatureVector();
00145 const int xsize = featureVector.getXSize();
00146 const int ysize = featureVector.getYSize();
00147 const int zsize = featureVector.getZSize();
00148
00149 const int newxsize = xsize - 2;
00150 const int newysize = ysize - 2;
00151
00152 if(newxsize < 1 || newysize < 1)
00153 return fv;
00154 std::vector<float>::const_iterator ofv=fv.begin();
00155 std::vector<float> distfv=std::vector<float>(xsize*ysize);
00156 std::vector<float>::iterator dfv=distfv.begin();
00157
00158 for(int x=0;x<xsize;x++)
00159 for(int y=0;y<ysize;y++)
00160 {
00161 float dSq=0;
00162 for(int z=0;z<zsize;z++)
00163 {
00164
00165 dSq += *ofv * *ofv;
00166 ofv++;
00167 }
00168 *(dfv++)=dSq;
00169 }
00170 dfv=distfv.begin();
00171 ofv=fv.begin();
00172 std::vector<float> newfv=std::vector<float>(newxsize*newysize*zsize*4);
00173 std::vector<float>::iterator nfv=newfv.begin();
00174 const int h=newysize;
00175 for(int x=0;x<xsize;x++)
00176 for(int y=0;y<ysize;y++)
00177 {
00178 if(x<newxsize && y<newysize)
00179 {
00180
00181 float n1 = sqrt(*dfv + *(dfv+h) + *(dfv+1) + *(dfv+h+1) + itsEpsilon);
00182
00183 float n2 = sqrt(*(dfv+h) + *(dfv+2*h) + *(dfv+h+1) + *(dfv+2*h+1) + itsEpsilon);
00184
00185 float n3 = sqrt(*(dfv+1) + *(dfv+h+1) + *(dfv+2) + *(dfv+h+2) + itsEpsilon);
00186
00187 float n4 = sqrt(*(dfv+h+1) + *(dfv+2*h+1) + *(dfv+h+2) + *(dfv+2*h+2) + itsEpsilon);
00188
00189 for(int z=0;z<zsize;z++)
00190 {
00191
00192 *(nfv++)=*ofv/n1;
00193 *(nfv++)=*ofv/n2;
00194 *(nfv++)=*ofv/n3;
00195 *(nfv++)=*ofv/n4;
00196 ofv++;
00197 }
00198
00199 dfv++;
00200 }
00201 else
00202 {
00203 ofv+=zsize;
00204 dfv++;
00205 }
00206 }
00207
00208 return newfv;
00209 }
00210
00211 void HistogramOfGradients::addToBin(const float xf, const float yf, const float ang_in, const float mag, const bool oriSigned, FeatureVector &fv)
00212 {
00213 float ang=ang_in;
00214 float oriBin;
00215 int numBins = fv.getZSize();
00216 if(oriSigned)
00217 {
00218
00219 ang=fmod(ang,2*M_PI);
00220
00221 if (ang < 0.0)
00222 ang += 2*M_PI;
00223 oriBin = ang / 2.0 / M_PI * float(numBins);
00224 }
00225 else
00226 {
00227
00228 ang=fmod(ang,M_PI);
00229
00230 if (ang < 0.0)
00231 ang += M_PI;
00232 oriBin = ang / M_PI * float(numBins);
00233 }
00234 fv.addValue(xf, yf, oriBin, mag);
00235 }
00236
00237
00238
00239
00240
00241
00242