Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <stdlib.h>
00013
00014 #include "HistogramUV.h"
00015 #include "../../Workers/Puma2/Y8UV8ToRGB8Operator.h"
00016
00017 #define THIS HistogramUV
00018
00019 #include <iostream>
00020 #include <limits>
00021 #include <math.h>
00022 #include <sstream>
00023
00024 using namespace puma2;
00025 using namespace std;
00026
00027 THIS::THIS( unsigned binSize )
00028 {
00029 m_BinSize = binSize;
00030 if ( 256%m_BinSize == 0 ) {
00031 m_NumBins=256/m_BinSize;
00032 } else {
00033 m_NumBins=256/binSize+1;
00034 }
00035 m_Matrix.resize( m_NumBins, m_NumBins );
00036 m_Data = ((EntryT**)(m_Matrix)) [0];
00037 m_DataLength = m_NumBins*m_NumBins;
00038 clear();
00039 }
00040
00041 THIS::THIS( )
00042 {
00043 m_BinSize = 0;
00044 }
00045
00046
00047 THIS::~THIS() {}
00048
00049 THIS::THIS( const HistogramUV& other )
00050 {
00051 m_BinSize=0;
00052 operator=(other);
00053 }
00054
00055 HistogramUV& THIS::operator=( const HistogramUV& other )
00056 {
00057 if (other.m_BinSize == 0) {
00058 m_BinSize=0;
00059 return *this;
00060 }
00061 if (m_BinSize != 0 && m_BinSize != other.m_BinSize) {
00062 std::ostringstream stream;
00063 stream << "Bin sizes do not match ( " << m_BinSize << " != " << other.m_BinSize << " )";
00064
00065 return *this;
00066 }
00067 m_BinSize=other.m_BinSize;
00068 m_NumBins=other.m_NumBins;
00069 m_Matrix.resize( m_NumBins, m_NumBins );
00070 m_Data = ((EntryT**)(m_Matrix)) [0];
00071 m_DataLength = m_NumBins*m_NumBins;
00072 memcpy( m_Data, other.m_Data, m_DataLength*sizeof(EntryT) );
00073 return *this;
00074 }
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 void THIS::printOn( ostream& strm )
00098 {
00099 strm << "Bin size: " << m_BinSize << endl;
00100 strm << "Histogram size: " << m_NumBins << " x " << m_NumBins << endl;
00101 strm << "Mean value: " << getMeanValue() << endl;
00102 strm << "Max value: " << getMaxValue() << endl;
00103 strm << "Deviation: " << getDeviation();
00104 }
00105
00106 bool THIS::checkInit() const {
00107 if (m_BinSize == 0) {
00108
00109 return false;
00110 }
00111 return true;
00112 }
00113
00114 void THIS::clear()
00115 {
00116 if (!checkInit()) { return; }
00117 memset( m_Data, 0, m_DataLength*sizeof(EntryT) );
00118 }
00119
00120
00121 int THIS::correct( int val, int y ) const
00122 {
00123 int result= ( val - 128 ) * 64 / y + 128;
00124 if (result<0) { result=0; }
00125 if (result>255) { result=255; }
00126 result/=m_BinSize;
00127 return result;
00128 }
00129
00130 void THIS::addImage( ColorImageUV8 &imageUV, GrayLevelImage8 &imageY, unsigned minY, unsigned maxY )
00131 {
00132 Box2D<int> bBox(0, 0, imageUV.getWidth()-1, imageUV.getHeight()-1);
00133 addImage(imageUV, imageY, bBox, minY, maxY);
00134 }
00135
00136 void THIS::addImage( ColorImageUV8 &imageUV, GrayLevelImage8 &imageY, Box2D<int> bBox, unsigned minY, unsigned maxY )
00137 {
00138 if (!checkInit()) { return; }
00139
00140 if (minY<1) { minY=1; }
00141 if (maxY>254) { maxY=254; }
00142
00143 ColorImageUV8::PixelType* currentUvPixel;
00144 unsigned char* currentYPixel;
00145
00146 for(int y = bBox.minY(); y <= bBox.maxY(); y++)
00147 for(int x = bBox.minX(); x <= bBox.maxX(); x++)
00148 {
00149 currentUvPixel=&(imageUV[y][x]);
00150 currentYPixel = &(imageY[y][x]);
00151 if( ( (*currentUvPixel)[0] != 255) && (*currentYPixel >= minY) && (*currentYPixel <= maxY) )
00152 {
00153
00154 m_Matrix[ correct( (*currentUvPixel)[0], (*currentYPixel) ) ][ correct( (*currentUvPixel)[1], (*currentYPixel) ) ] ++;
00155 }
00156 currentYPixel++;
00157 currentUvPixel++;
00158 }
00159
00160
00161 }
00162
00163
00164 void THIS::substract( float value )
00165 {
00166 for (unsigned i=0;i<m_DataLength;i++)
00167 {
00168 m_Data[i] -= value;
00169 if ( m_Data[i] < 0) { m_Data[i]=0; }
00170 }
00171 }
00172
00173
00174 void THIS::divideBy( const HistogramUV& divident )
00175 {
00176 if (!checkInit()) { return; }
00177
00178 if (m_BinSize != divident.getBinSize() ) {
00179
00180 return;
00181 }
00182
00183 const EntryT* dividentData=divident.getData();
00184
00185 for (unsigned i=0;i<m_DataLength;i++)
00186 {
00187 m_Data[i] /= dividentData[i]+1;
00188 }
00189 }
00190
00191 void THIS::add( const HistogramUV& other )
00192 {
00193 if (!checkInit()) { return; }
00194
00195 if (m_BinSize != other.getBinSize() ) {
00196
00197 return;
00198 }
00199
00200 const EntryT* dividentData=other.getData();
00201
00202 for (unsigned i=0;i<m_DataLength;i++)
00203 {
00204 m_Data[i] += dividentData[i];
00205 }
00206 }
00207
00208
00209 void THIS::applyThreshold( float thresholdFactor, float dilationRadius )
00210 {
00211 float threshold = thresholdFactor * float( getMeanValue() );
00212 ostringstream stream;
00213 stream << "Binarizing histogram. Threshold: " << threshold << " Dilation Radius: " << dilationRadius;
00214
00215 ImageMask dataCopyMask( m_NumBins, m_NumBins );
00216 unsigned char* dataCopy=dataCopyMask.getData();
00217 for (unsigned i=0;i<m_DataLength;i++)
00218 {
00219 if (m_Data[i] < threshold) { dataCopy[i]=0; }
00220 else { dataCopy[i]=255; }
00221 }
00222 dataCopyMask.dilate( dilationRadius );
00223 dataCopy=dataCopyMask.getData();
00224 for (unsigned i=0;i<m_DataLength;i++)
00225 {
00226 m_Data[i]=dataCopy[i];
00227 }
00228
00229 }
00230
00231
00232 void THIS::normalizeMax()
00233 {
00234 EntryT maxValue = getMaxValue();
00235
00236 if(maxValue == 0)
00237 {
00238
00239 return;
00240 }
00241
00242 for(unsigned i=0; i < m_DataLength; i++)
00243 {
00244 m_Data[i] /= maxValue;
00245 }
00246 }
00247
00248 void THIS::clearCenter(unsigned int range)
00249 {
00250 unsigned realRange = range/m_BinSize;
00251 if (realRange > m_NumBins/2)
00252 {
00253 realRange = m_NumBins/2;
00254 }
00255 for (unsigned y = m_NumBins/2 - range; y < m_NumBins/2 + range; y++)
00256 for (unsigned x = m_NumBins/2 - range; x < m_NumBins/2 + range; x++)
00257 {
00258 m_Matrix[y][x] = 0;
00259 }
00260 }
00261
00262 float THIS::getDeviation()
00263 {
00264 float weightedDistanceSum = 0;
00265 float totalSum = 0;
00266
00267 for(int y = 1; y < int(m_NumBins); y++ )
00268 for(int x = 1; x < int(m_NumBins); x++ )
00269 {
00270 if(m_Matrix[y][x] != 0)
00271 {
00272 int squareDistance = ( abs(y-128) * abs(y-128) ) + ( abs(x-128) * abs(x-128) );
00273 float distance = sqrt(squareDistance);
00274 weightedDistanceSum += float(m_Matrix[y][x]) * distance;
00275 totalSum+=m_Matrix[y][x];
00276 }
00277 }
00278
00279 return float(weightedDistanceSum) / float(totalSum) / sqrt(2.0);
00280 }
00281
00282 ImageMask* THIS::getMask( ColorImageUV8 &imageUV, GrayLevelImage8 &imageY, unsigned minY, unsigned maxY ) const
00283 {
00284 if (!checkInit()) { return 0; }
00285
00286 if (minY<1) { minY=1; }
00287 if (maxY>254) { maxY=254; }
00288
00289 unsigned width = imageUV.getWidth();
00290 unsigned height = imageUV.getHeight();
00291
00292 unsigned char* mask = new unsigned char[ width*height ];
00293 memset( mask, 0, width*height );
00294
00295 ColorImageUV8::PixelType* currentUvPixel=imageUV.unsafeRowPointerArray()[0];
00296 unsigned char* currentYPixel=imageY.unsafeRowPointerArray()[0];
00297 unsigned char* currentMaskPixel=mask;
00298 unsigned u,v;
00299
00300 for(unsigned y=0; y < height; y++)
00301 {
00302 for(unsigned x=0; x < width; x++)
00303 {
00304 u=(*currentUvPixel)[0]/m_BinSize;
00305 v=(*currentUvPixel)[1]/m_BinSize;
00306 if ( ( ( *currentYPixel < maxY ) && ( *currentYPixel > minY ) ) &&
00307 ( m_Matrix[ correct( (*currentUvPixel)[0], (*currentYPixel) ) ][ correct( (*currentUvPixel)[1], (*currentYPixel) ) ] ) )
00308 {
00309 *currentMaskPixel = 255;
00310 }
00311
00312 currentUvPixel++;
00313 currentYPixel++;
00314 currentMaskPixel++;
00315 }
00316 }
00317
00318 ImageMask* maskObj=new ImageMask( width, height, mask );
00319
00320 return maskObj;
00321 }
00322
00323
00324 void THIS::getImage( ColorImageRGB8& imageRGB, float exponent ) const
00325 {
00326 if (!checkInit()) { return; }
00327
00328 if ( (imageRGB.getWidth() == 0) && (imageRGB.getHeight() == 0) )
00329 {
00330 imageRGB.resize(m_NumBins,m_NumBins);
00331 }
00332
00333 if ( (unsigned(imageRGB.getWidth()) != m_NumBins) != (unsigned(imageRGB.getHeight()) != m_NumBins) )
00334 {
00335
00336 return;
00337 }
00338
00339
00340 EntryT maxValue=getMaxValue();
00341 EntryT* normalizedData=new EntryT[m_DataLength];
00342
00343 if ( exponent == 1.0 )
00344 {
00345 for (unsigned i=0;i<m_DataLength;i++) {
00346 normalizedData[i] = m_Data[i] / maxValue;
00347 }
00348 } else
00349 {
00350 for (unsigned i=0;i<m_DataLength;i++) {
00351 normalizedData[i] = pow( m_Data[i] / maxValue, exponent );
00352 }
00353 }
00354
00355
00356 ColorImageUV8 imageUV(m_NumBins,m_NumBins);
00357 GrayLevelImage8 imageY(m_NumBins,m_NumBins);
00358
00359 ColorImageUV8::PixelType* currentUvPixel=imageUV.unsafeRowPointerArray()[0];
00360
00361 memset( imageY.unsafeRowPointerArray()[0], 196, m_DataLength );
00362
00363 for (unsigned u=0; u < m_NumBins; u++)
00364 for (unsigned v=0; v < m_NumBins; v++)
00365 {
00366 (*currentUvPixel)[0]=u*m_BinSize;
00367 (*currentUvPixel)[1]=v*m_BinSize;
00368 currentUvPixel++;
00369 }
00370 Y8UV8ToRGB8Operator( imageY, imageUV, imageRGB );
00371
00372
00373 ColorImageRGB8::PixelType* currentRgbPixel=imageRGB.unsafeRowPointerArray()[0];
00374 EntryT* currentHistogramEntry=normalizedData;
00375 EntryT histGamma;
00376
00377 for (unsigned u=0; u < m_NumBins; u++)
00378 for (unsigned v=0; v < m_NumBins; v++)
00379 {
00380 histGamma=*currentHistogramEntry;
00381
00382 (*currentRgbPixel)[0] *= histGamma;
00383 (*currentRgbPixel)[1] *= histGamma;
00384 (*currentRgbPixel)[2] *= histGamma;
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399 currentRgbPixel++;
00400 currentHistogramEntry++;
00401 }
00402
00403 delete[] normalizedData;
00404
00405 }
00406
00407
00408 EntryT THIS::distance(HistogramUV& other) const
00409 {
00410 if(m_NumBins != other.m_NumBins)
00411 {
00412
00413 return 0;
00414 }
00415
00416 EntryT sumDiff=0;
00417 EntryT sum=0;
00418 EntryT thisMean=getMeanValue();
00419 EntryT otherMean=other.getMeanValue();
00420
00421
00422 for(unsigned i = 0; i < m_DataLength; i++)
00423 {
00424 EntryT thisNorm=m_Data[i] / thisMean;
00425 EntryT otherNorm=other.m_Data[i] / otherMean;
00426
00427 EntryT diff= thisNorm-otherNorm;
00428
00429 sum+= thisNorm+otherNorm;
00430 sumDiff+= diff*diff;
00431 }
00432
00433 return sumDiff/sum;
00434 }
00435
00436 EntryT THIS::getMeanValue() const
00437 {
00438 if (!checkInit()) { return 0; }
00439
00440 EntryT sum=0;
00441 for (unsigned i=0;i<m_DataLength;i++)
00442 {
00443 sum+=m_Data[i];
00444 }
00445 EntryT mean = sum / m_DataLength;
00446 return mean;
00447 }
00448
00449
00450 EntryT THIS::getMaxValue() const
00451 {
00452 if (!checkInit()) { return 0; }
00453
00454 EntryT max=0;
00455 for (unsigned i=0;i<m_DataLength;i++)
00456 {
00457 if (m_Data[i] > max) { max=m_Data[i]; }
00458 }
00459 ostringstream stream;
00460 stream << "Maximum " << max;
00461
00462 return max;
00463 }
00464
00465 #undef THIS