Logo Search packages:      
Sourcecode: qtpfsgui version File versions

icip06.cpp

/**
 * This file is a part of Qtpfsgui package.
 * ---------------------------------------------------------------------- 
 * Copyright (C) 2006,2007 Giuseppe Rota
 * 
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * ---------------------------------------------------------------------- 
 *
 * @author Giuseppe Rota <grota@users.sourceforge.net>
 */

#include "icip06.h"
#include "debevec.h"
#include <iostream>
#define FLT_MIN 1e-6

void icip06_applyResponse( const float * arrayofexptime,
                          pfs::Array2D* Xj,
                          pfs::Array2D* Yj,
                          pfs::Array2D* Zj,
                          const float* Ir,
                          const float* Ig,
                          const float* Ib,
                          const float* w, const int iterations,
                          Array2DList &Ptemp,
                          Array2DList &P, const bool ldrinput, ... )  {
//TODO: here at least the hdr input is implemented, not so below.
assert(ldrinput);

QList<QImage*> *listldr=NULL;
Array2DList *listhdrR=NULL;
Array2DList *listhdrG=NULL;
Array2DList *listhdrB=NULL;
va_list arg_pointer;
va_start(arg_pointer,ldrinput); /* Initialize the argument list. */
int N=-1;

if (ldrinput) {
      listldr=va_arg(arg_pointer,QList<QImage*>*);
      // number of exposures
      N = listldr->count();
} else {
      listhdrR=va_arg(arg_pointer,Array2DList*);
      listhdrG=va_arg(arg_pointer,Array2DList*);
      listhdrB=va_arg(arg_pointer,Array2DList*);
      // number of exposures
      N = listhdrR->size();
}
va_end(arg_pointer); /* Clean up. */


int width = Xj->getCols();
int height = Yj->getRows();

// Create P and Ptemp, stacks of Array2DImpl; P will contain weigths computed by reinhard06_anti_ghosting funtion
for (int i=0;i<N;i++) {
      pfs::Array2D* toaddfinal = new pfs::Array2DImpl(width,height);
      pfs::Array2D* toaddtemp  = new pfs::Array2DImpl(width,height);
      assert(toaddfinal!=NULL);
      assert(toaddtemp!=NULL);
//    if (toaddfinal==NULL || toaddtemp==NULL)
//          throw pfs::Exception( "Cannot allocate memory for anti-ghosting weights" );
//    else {
      P.push_back(toaddfinal);
      Ptemp.push_back(toaddtemp);
//    }
}

//perform anti-ghosting
if (ldrinput) {
      reinhard06_anti_ghosting(w,iterations,Ptemp,P,true,listldr);
      //we don't need these anymore
      for(int i=0; i<N; i++ ) {
            delete Ptemp[i];
      }
      //apply debevec model to compute actual hdr image
      debevec_applyResponse(  arrayofexptime,
                        Xj, Ir,
                        Yj, Ig,
                        Zj, Ib, P,
                        true,listldr);
} else {
      reinhard06_anti_ghosting(w,iterations,Ptemp,P,false,listhdrR,listhdrG,listhdrB);
      //we don't need these anymore
      for(int i=0; i<N; i++ ) {
            delete Ptemp[i];
      }
      //apply debevec model to compute actual hdr image
      debevec_applyResponse(  arrayofexptime,
                        Xj, Ir,
                        Yj, Ig,
                        Zj, Ib, P,
                        false,listhdrR,listhdrG,listhdrB);
}


//we don't need these anymore
for(int i=0 ; i<N ; i++ )
      delete P[i];
}




void reinhard06_anti_ghosting(  const float* w, const int iterations,
                                Array2DList &Ptemp,
                                Array2DList &P,
                                const bool ldrinput, ... ) {


int N=-1; int width=-1; int height=-1;
QList<QImage*> *list=NULL;
// Array2DList *listhdrR=NULL;
// Array2DList *listhdrG=NULL;
// Array2DList *listhdrB=NULL;
va_list arg_pointer;
va_start(arg_pointer,ldrinput); /* Initialize the argument list. */

// if (ldrinput) {
//TODO hdr input...
      assert(ldrinput);
      list=va_arg(arg_pointer,QList<QImage*>*);
      // number of exposures
      N = list->count();
      // frame size
      width = (list->at(0))->width();
      height = (list->at(0))->height();
// } else {
//    listhdrR=va_arg(arg_pointer,Array2DList*);
//    listhdrG=va_arg(arg_pointer,Array2DList*);
//    listhdrB=va_arg(arg_pointer,Array2DList*);
//    // number of exposures
//    N = listhdrR->size();
//    // frame size
//    width= ((*listhdrR)[0].yi)->getCols();
//    height=((*listhdrR)[0].yi)->getRows();
// }
va_end(arg_pointer); /* Clean up. */


//First step, initialize the List of Weights Ptemp to its initial values, obtained via w
//for all pixels
// for all exposures for each pixel
for( int i=0 ; i<N ; i++ ) {
      QImage *p=list->at(i);
      for ( int j=0 ; j<width*height ; j++ ) {
            (*Ptemp[i])(j)=(float)(w[qRed(* ( (QRgb*)(p->bits()) +j) )]+w[qGreen(* ( (QRgb*)(p->bits()) +j) )]+w[qBlue(* ( (QRgb*)(p->bits()) +j) )])/3.0f;
      }
}


// constant used in next step
float k=pow(2.0f*M_PI,-2.5f);

//COMPUTE weightslist P for ITER iterations.
for ( int ITER=0; ITER<iterations; ITER++ ) { // for all the iterations ITER

      // update ALL the Ptemp stack using previous P*w[rgb]/3
      if (ITER!=0) {
            for ( int exposure=0; exposure<N; exposure++ )  {//for all the exposures
                  QImage *p=list->at(exposure);
                  for ( int j=0; j<width*height; j++ ) {
                  (*Ptemp[exposure])(j) = (*P[exposure])(j) * (float)(w[qRed(* ((QRgb*)(p->bits()) +j) )]+w[qGreen(* ((QRgb*)(p->bits()) +j) )]+w[qBlue(* ((QRgb*)(p->bits()) +j) )])/3.0f;
                  }
            }
      }

      for ( int exposure=0 ; exposure<N ; exposure++ ) { //for all the exposures
            QImage *cur_exposure=list->at(exposure);
            for ( int row=0 ; row<height; row++ ) { //for all the rows row (from 0 to height-1)
            for ( int col=0 ; col<width;  col++ ) { //for all the columns col (from 0 to width-1)

                  // cumulative values for (*P[i])(col,row)
                  float sum=0;
                  float div=0;
                  // get the 3 channel values for the current pixel, exposure, location col,row
//                float Ch1x=logf(FLT_MIN+  qRed(cur_exposure->pixel(col,row)) );
//                float Ch2x=logf(FLT_MIN+qGreen(cur_exposure->pixel(col,row)) );
//                float Ch3x=logf(FLT_MIN+ qBlue(cur_exposure->pixel(col,row)) );
                  float Ch1x=qRed(cur_exposure->pixel(col,row))/255.0;
                  float Ch2x=qGreen(cur_exposure->pixel(col,row))/255.0;
                  float Ch3x=qBlue(cur_exposure->pixel(col,row))/255.0;
                  float Ch1y,Ch2y,Ch3y;

                  // go through neighborhood, deep into the exposures, to update weight.
                  // use Ptemp to read current values, and write in P -at the end of the for-.
                  for ( int I=0 ; I<N ; I++ ) {
                        QImage *exposure_in_neighb=list->at(I);
                        // if top-left is in boundaries
                        if (col-1>=0 && row-1>=0) {
//                            Ch1y=logf(FLT_MIN+  qRed(exposure_in_neighb->pixel(col-1,row-1)) );
//                            Ch2y=logf(FLT_MIN+qGreen(exposure_in_neighb->pixel(col-1,row-1)) );
//                            Ch3y=logf(FLT_MIN+ qBlue(exposure_in_neighb->pixel(col-1,row-1)) );
                              Ch1y=qRed(exposure_in_neighb->pixel(col-1,row-1))/255.0;
                              Ch2y=qGreen(exposure_in_neighb->pixel(col-1,row-1))/255.0;
                              Ch3y=qBlue(exposure_in_neighb->pixel(col-1,row-1))/255.0;
                              sum+=(*Ptemp[I])(col-1,row-1)*k*expf(-0.5*((Ch1x-Ch1y)*(Ch1x-Ch1y) + (Ch2x-Ch2y)*(Ch2x-Ch2y) + (Ch3x-Ch3y)*(Ch3x-Ch3y) + 2.0f ));
                              div+=(*Ptemp[I])(col-1,row-1);
                        }
                        //if top is in boundaries
                        if (row-1>=0) {
//                            Ch1y=logf(FLT_MIN+  qRed(exposure_in_neighb->pixel(col,row-1)) );
//                            Ch2y=logf(FLT_MIN+qGreen(exposure_in_neighb->pixel(col,row-1)) );
//                            Ch3y=logf(FLT_MIN+ qBlue(exposure_in_neighb->pixel(col,row-1)) );
                              Ch1y=qRed(exposure_in_neighb->pixel(col,row-1))/255.0;
                              Ch2y=qGreen(exposure_in_neighb->pixel(col,row-1))/255.0;
                              Ch3y=qBlue(exposure_in_neighb->pixel(col,row-1))/255.0;
                              float a=(*Ptemp[I])(col,row-1)*k*expf(-0.5*((Ch1x-Ch1y)*(Ch1x-Ch1y) + (Ch2x-Ch2y)*(Ch2x-Ch2y) + (Ch3x-Ch3y)*(Ch3x-Ch3y) + 1.0f ));
                              float b=(*Ptemp[I])(col,row-1);
                              sum+=a;
                              div+=b;
                        }
                        // if top-right is in boundaries
                        if (col+1<width && row-1>=0) {
//                            Ch1y=logf(FLT_MIN+  qRed(exposure_in_neighb->pixel(col+1,row-1)) );
//                            Ch2y=logf(FLT_MIN+qGreen(exposure_in_neighb->pixel(col+1,row-1)) );
//                            Ch3y=logf(FLT_MIN+ qBlue(exposure_in_neighb->pixel(col+1,row-1)) );
                              Ch1y=qRed(exposure_in_neighb->pixel(col+1,row-1))/255.0;
                              Ch2y=qGreen(exposure_in_neighb->pixel(col+1,row-1))/255.0;
                              Ch3y=qBlue(exposure_in_neighb->pixel(col+1,row-1))/255.0;
                              sum+=(*Ptemp[I])(col+1,row-1)*k*expf(-0.5*((Ch1x-Ch1y)*(Ch1x-Ch1y) + (Ch2x-Ch2y)*(Ch2x-Ch2y) + (Ch3x-Ch3y)*(Ch3x-Ch3y) + 2.0f ));
                              div+=(*Ptemp[I])(col+1,row-1);
                        }
                        // if left is in boundaries
                        if (col-1>=0) {
//                            Ch1y=logf(FLT_MIN+  qRed(exposure_in_neighb->pixel(col-1,row)) );
//                            Ch2y=logf(FLT_MIN+qGreen(exposure_in_neighb->pixel(col-1,row)) );
//                            Ch3y=logf(FLT_MIN+ qBlue(exposure_in_neighb->pixel(col-1,row)) );
                              Ch1y=qRed(exposure_in_neighb->pixel(col-1,row))/255.0;
                              Ch2y=qGreen(exposure_in_neighb->pixel(col-1,row))/255.0;
                              Ch3y=qBlue(exposure_in_neighb->pixel(col-1,row))/255.0;
                              sum+=(*Ptemp[I])(col-1,row)*k*expf(-0.5*((Ch1x-Ch1y)*(Ch1x-Ch1y) + (Ch2x-Ch2y)*(Ch2x-Ch2y) + (Ch3x-Ch3y)*(Ch3x-Ch3y) + 1.0f ));
                              div+=(*Ptemp[I])(col-1,row);
                        }
                        // if right is in boundaries
                        if (col+1<width) {
//                            Ch1y=logf(FLT_MIN+  qRed(exposure_in_neighb->pixel(col+1,row)) );
//                            Ch2y=logf(FLT_MIN+qGreen(exposure_in_neighb->pixel(col+1,row)) );
//                            Ch3y=logf(FLT_MIN+ qBlue(exposure_in_neighb->pixel(col+1,row)) );
                              Ch1y=qRed(exposure_in_neighb->pixel(col+1,row))/255.0;
                              Ch2y=qGreen(exposure_in_neighb->pixel(col+1,row))/255.0;
                              Ch3y=qBlue(exposure_in_neighb->pixel(col+1,row))/255.0;
                              sum+=(*Ptemp[I])(col+1,row)*k*expf(-0.5*((Ch1x-Ch1y)*(Ch1x-Ch1y) + (Ch2x-Ch2y)*(Ch2x-Ch2y) + (Ch3x-Ch3y)*(Ch3x-Ch3y) + 1.0f ));
                              div+=(*Ptemp[I])(col+1,row);
                        }
                        // if bottom-left is in boundaries
                        if (col-1>=0 && row+1<height) {
//                            Ch1y=logf(FLT_MIN+  qRed(exposure_in_neighb->pixel(col-1,row+1)) );
//                            Ch2y=logf(FLT_MIN+qGreen(exposure_in_neighb->pixel(col-1,row+1)) );
//                            Ch3y=logf(FLT_MIN+ qBlue(exposure_in_neighb->pixel(col-1,row+1)) );
                              Ch1y=qRed(exposure_in_neighb->pixel(col-1,row+1))/255.0;
                              Ch2y=qGreen(exposure_in_neighb->pixel(col-1,row+1))/255.0;
                              Ch3y=qBlue(exposure_in_neighb->pixel(col-1,row+1))/255.0;
                              sum+=(*Ptemp[I])(col-1,row+1)*k*expf(-0.5*((Ch1x-Ch1y)*(Ch1x-Ch1y) + (Ch2x-Ch2y)*(Ch2x-Ch2y) + (Ch3x-Ch3y)*(Ch3x-Ch3y) + 2.0f ));
                              div+=(*Ptemp[I])(col-1,row+1);
                        }
                        // if bottom is in boundaries
                        if (row+1<height) {
//                            Ch1y=logf(FLT_MIN+  qRed(exposure_in_neighb->pixel(col,row+1)) );
//                            Ch2y=logf(FLT_MIN+qGreen(exposure_in_neighb->pixel(col,row+1)) );
//                            Ch3y=logf(FLT_MIN+ qBlue(exposure_in_neighb->pixel(col,row+1)) );
                              Ch1y=qRed(exposure_in_neighb->pixel(col,row+1))/255.0;
                              Ch2y=qGreen(exposure_in_neighb->pixel(col,row+1))/255.0;
                              Ch3y=qBlue(exposure_in_neighb->pixel(col,row+1))/255.0;
                              sum+=(*Ptemp[I])(col,row+1)*k*expf(-0.5*((Ch1x-Ch1y)*(Ch1x-Ch1y) + (Ch2x-Ch2y)*(Ch2x-Ch2y) + (Ch3x-Ch3y)*(Ch3x-Ch3y) + 1.0f ));
                              div+=(*Ptemp[I])(col,row+1);
                        }
                        // if bottom-right is in boundaries
                        if (col+1<width && row+1<height) {
//                            Ch1y=logf(FLT_MIN+  qRed(exposure_in_neighb->pixel(col+1,row+1)) );
//                            Ch2y=logf(FLT_MIN+qGreen(exposure_in_neighb->pixel(col+1,row+1)) );
//                            Ch3y=logf(FLT_MIN+ qBlue(exposure_in_neighb->pixel(col+1,row+1)) );
                              Ch1y=qRed(exposure_in_neighb->pixel(col+1,row+1))/255.0;
                              Ch2y=qGreen(exposure_in_neighb->pixel(col+1,row+1))/255.0;
                              Ch3y=qBlue(exposure_in_neighb->pixel(col+1,row+1))/255.0;
                              sum+=(*Ptemp[I])(col+1,row+1)*k*expf(-0.5*((Ch1x-Ch1y)*(Ch1x-Ch1y) + (Ch2x-Ch2y)*(Ch2x-Ch2y) + (Ch3x-Ch3y)*(Ch3x-Ch3y) + 2.0f ));
                              div+=(*Ptemp[I])(col+1,row+1);
                        }
                  } // exposure-wise neighborood
                  if (div!=0.0f)
                        (*P[exposure])(col,row)=(sum/div);
                  else
                        (*P[exposure])(col,row)=0.0f;
            } //rows in pixel col,row
            } //cols in pixel col,row
      } //exposures in iteration ITER
std::cerr << "finished iteration " << ITER+1 << " of " << iterations << std::endl;
} //iterations

}

Generated by  Doxygen 1.6.0   Back to index