Logo Search packages:      
Sourcecode: qtpfsgui version File versions

void tmo_fattal02 ( pfs::Array2D Y,
pfs::Array2D L,
float  alfa,
float  beta,
float  _opt_noiseredux,
bool  newfattal 
)

Gradient Domain High Dynamic Range Compression.

Implementation of Gradient Domain High Dynamic Range Compression by Raanan Fattal, Dani Lischinski, Michael Werman.

Parameters:
Y [in] image luminance values
L [out] tone mapped values
alfa parameter alfa (refer to the paper)
beta parameter beta (refer to the paper)

Definition at line 261 of file tmo_fattal02.cpp.

References pfs::Array2D::getCols(), pfs::Array2D::getRows(), and solve_pde_multigrid().

{
  const int MSIZE = 32;         // minimum size of gaussian pyramid
      
  int width = Y->getCols();   // +2 for boundaries
  int height = Y->getRows();
  int size = width*height;
  int x,y,i,k;

  // find max & min values, normalize to range 0..100 and take logarithm
  float minLum = (*Y)(0,0);
  float maxLum = (*Y)(0,0);
  for( i=0 ; i<size ; i++ )
  {
    minLum = ( (*Y)(i)<minLum ) ? (*Y)(i) : minLum;
    maxLum = ( (*Y)(i)>maxLum ) ? (*Y)(i) : maxLum;
  }
  pfs::Array2D* H = new pfs::Array2DImpl(width, height);
  for( i=0 ; i<size ; i++ )
    (*H)(i) = log( 100.0f*(*Y)(i)/maxLum + 1e-4 );

//   DEBUG_STR << "tmo_fattal02: calculating attenuation matrix" << endl;
  
  // create gaussian pyramids
  int mins = (width<height) ? width : height;   // smaller dimension
  int nlevels = 0;
  while( mins>=MSIZE )
  {
    nlevels++;
    mins /= 2;
  }
  pfs::Array2D** pyramids = new pfs::Array2D*[nlevels];
  createGaussianPyramids(H, pyramids, nlevels);

  // calculate gradients and its average values on pyramid levels
  pfs::Array2D** gradients = new pfs::Array2D*[nlevels];
  float* avgGrad = new float[nlevels];
  for( k=0 ; k<nlevels ; k++ )
  {
    gradients[k] = new pfs::Array2DImpl(pyramids[k]->getCols(), pyramids[k]->getRows());
    avgGrad[k] = calculateGradients(pyramids[k],gradients[k], k);
  }

  // calculate fi matrix
  pfs::Array2D* FI = new pfs::Array2DImpl(width, height);
  calculateFiMatrix(FI, gradients, avgGrad, nlevels, alfa, beta, noise, newfattal);

//  dumpPFS( "FI.pfs", FI, "Y" );

  // attenuate gradients
  pfs::Array2D* Gx = new pfs::Array2DImpl(width, height);
  pfs::Array2D* Gy = new pfs::Array2DImpl(width, height);
  for( y=0 ; y<height ; y++ )
    for( x=0 ; x<width ; x++ )
    {
      int s, e;
      s = (y+1 == height ? y : y+1);
      e = (x+1 == width ? x : x+1);

      (*Gx)(x,y) = ((*H)(e,y)-(*H)(x,y)) * (*FI)(x,y);        
      (*Gy)(x,y) = ((*H)(x,s)-(*H)(x,y)) * (*FI)(x,y);      
    }

//   dumpPFS( "Gx.pfs", Gx, "Y" );
//   dumpPFS( "Gy.pfs", Gy, "Y" );
  
//   DEBUG_STR << "tmo_fattal02: compressing gradients" << endl;
  
  // calculate divergence
  pfs::Array2D* DivG = new pfs::Array2DImpl(width, height);
  for( y=0 ; y<height ; y++ )
    for( x=0 ; x<width ; x++ )
    {
      (*DivG)(x,y) = (*Gx)(x,y) + (*Gy)(x,y);
      if( x > 0 ) (*DivG)(x,y) -= (*Gx)(x-1,y);
      if( y > 0 ) (*DivG)(x,y) -= (*Gy)(x,y-1);
    }

//  dumpPFS( "DivG.pfs", DivG, "Y" );
  
//   DEBUG_STR << "tmo_fattal02: recovering image" << endl;
  
  // solve pde and exponentiate (ie recover compressed image)
  pfs::Array2D* U = new pfs::Array2DImpl(width, height);
  solve_pde_multigrid( DivG, U );
//  solve_pde_sor( DivG, U );

  for( y=0 ; y<height ; y++ )
    for( x=0 ; x<width ; x++ )
      (*L)(x,y) = exp( (*U)(x,y) ) - 1e-4;
      
  // remove percentile of min and max values and renormalize
  findMaxMinPercentile(L, 0.001f, minLum, 0.995f, maxLum);
  maxLum -= minLum;
  for( y=0 ; y<height ; y++ )
    for( x=0 ; x<width ; x++ )
    {
      (*L)(x,y) = ((*L)(x,y)-minLum) / maxLum;
      if( (*L)(x,y)<=0.0f )
        (*L)(x,y) = 1e-4;
    }

  // clean up
//   DEBUG_STR << "tmo_fattal02: clean up" << endl;
  delete H;
  for( i=0 ; i<nlevels ; i++ )
  {
    delete pyramids[i];
    delete gradients[i];
  }
  delete[] pyramids;
  delete[] gradients;
  delete[] avgGrad;
  delete FI;
  delete Gx;
  delete Gy;
  delete DivG;
  delete U;
}


Generated by  Doxygen 1.6.0   Back to index