HistogramUV.cpp
Go to the documentation of this file.
00001 /*******************************************************************************
00002  *  HistogramUV.cpp
00003  *
00004  *  (C) 2007 AG Aktives Sehen <agas@uni-koblenz.de>
00005  *           Universitaet Koblenz-Landau
00006  *
00007  *  Additional information:
00008  *  $Id: HistogramUV.cpp 24234 2008-04-12 17:32:23Z dgossow $
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     // TRACE_ERROR(stream.str()); // TODO use ros
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 // TODO
00077 //THIS::THIS( ExtendedInStream& extStrm )
00078 //{
00079 //  short version;
00080 //  extStrm >> version;
00081 //  extStrm >> m_BinSize;
00082 //  extStrm >> m_NumBins;
00083 //  extStrm >> m_Matrix;
00084 //  m_Data = ((EntryT**)(m_Matrix)) [0];
00085 //  m_DataLength = m_NumBins*m_NumBins;
00086 //}
00087 
00088 //void THIS::storer( ExtendedOutStream& extStrm )
00089 //{
00090 //  short version=10;
00091 //  extStrm << version;
00092 //  extStrm << m_BinSize;
00093 //  extStrm << m_NumBins;
00094 //  extStrm << m_Matrix;
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     //TRACE_ERROR("This histogram has not been initialized (bin size=0)."); // TODO use ros
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       //center around 0, divide by y, uncenter, divide by bin size
00154       m_Matrix[ correct( (*currentUvPixel)[0], (*currentYPixel) ) ][ correct( (*currentUvPixel)[1], (*currentYPixel) ) ] ++;
00155     }
00156     currentYPixel++;
00157     currentUvPixel++;
00158   }
00159 
00160 //  m_Matrix[m_NumBins-1][m_NumBins-1]=0;
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     // TRACE_ERROR("Bin sizes do not match."); // TODO use ros
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     // TRACE_ERROR("Bin sizes do not match."); // TODO use ros
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   // TRACE_SYSTEMINFO( stream.str() ) // TODO use ros
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   //note: the ImageMask deletes dataCopy
00229 }
00230 
00231 
00232 void THIS::normalizeMax()
00233 {
00234   EntryT maxValue = getMaxValue();
00235 
00236   if(maxValue == 0)
00237   {
00238     // TRACE_SYSTEMINFO( "Histogram is zero. Nothing to do." ) // TODO use ros
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     // TRACE_ERROR("Wrong image size."); // TODO use ros
00336     return;
00337   }
00338 
00339   //Calculate normalized values
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   //Create UV image map
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   //Multiply by histogram values
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 /*    if ( histGamma != 0.0 )
00387     {
00388       white=unsigned( (1.0-histGamma)*255.0 );
00389       (*currentRgbPixel)[0]= white + unsigned( float( (*currentRgbPixel)[0] ) * histGamma );
00390       (*currentRgbPixel)[1]= white + unsigned( float( (*currentRgbPixel)[1] ) * histGamma );
00391       (*currentRgbPixel)[2]= white + unsigned( float( (*currentRgbPixel)[2] ) * histGamma );
00392     }
00393     else
00394     {
00395       (*currentRgbPixel)[0]= 0;
00396       (*currentRgbPixel)[1]= 0;
00397       (*currentRgbPixel)[2]= 0;
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     // TRACE_ERROR( "Size mismatch."); // TODO use ros
00413     return 0;
00414   }
00415 
00416   EntryT sumDiff=0;
00417   EntryT sum=0;
00418   EntryT thisMean=getMeanValue();
00419   EntryT otherMean=other.getMeanValue();
00420 
00421   //calculate standard deviation of normalized histograms
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   // TRACE_SYSTEMINFO( stream.str() ) //// TODO use ros
00462   return max;
00463 }
00464 
00465 #undef THIS


obj_rec_gui
Author(s): AGAS/agas@uni-koblenz.de
autogenerated on Mon Oct 6 2014 02:53:43