Ejemplo n.º 1
0
SpencerOTF::SpencerOTF( const ViewingConditions &viewCond, int cols, int rows, float adaptationLuminance ) : filter( cols, rows )
{
  const float pixelsPerDeg = viewCond.getPixelsPerDegree( (viewCond.maxDistance +
                                                            viewCond.minDistance)/2. );
  std::cerr << "Creating OTF filter ";

  const float SCOTOPIC = 0.01, PHOTOPIC = 3;

  float w[4];
  
  const float scotopicW[4] = { 0.282, 0.478, 0.207, 0.033 };
//  const float mesopicW[4] = { 0.368, 0.478, 0.138, 0.016 };
  const float photopicW[4] = { 0.384, 0.478, 0.138, 0 };

  if( adaptationLuminance > PHOTOPIC ) {
    for( int i = 0; i < 4; i++ )
      w[i] = photopicW[i];
    std::cerr << "for photopic conditions..";
  } else if( adaptationLuminance <= SCOTOPIC ) {
    for( int i = 0; i < 4; i++ )
      w[i] = scotopicW[i];
    std::cerr << "for scotopic conditions..";
  } else {
    float ad = (log( adaptationLuminance ) - log( SCOTOPIC )) /
      (log(PHOTOPIC)-log(SCOTOPIC));
    for( int i = 0; i < 4; i++ )
      w[i] = scotopicW[i]*(1-ad) + photopicW[i]*ad;
    std::cerr << "for mesopic conditions..";    
  }

  pfs::Array2DImpl f( cols, rows );
  pfs::Array2D *filterSpatial = filter.setSpatial();
  pfs::setArray( filterSpatial, 0 );
  
  createVisDegDigitalFilter( spencerPSF0, &f, pixelsPerDeg );
  normalizeToSum( &f );
  multiplyAndAddArray( filterSpatial, &f, w[0] );

  createVisDegDigitalFilter( spencerPSF1, &f, pixelsPerDeg );
  normalizeToSum( &f );
  multiplyAndAddArray( filterSpatial, &f, w[1] );

  createVisDegDigitalFilter( spencerPSF2, &f, pixelsPerDeg );
  normalizeToSum( &f );
  multiplyAndAddArray( filterSpatial, &f, w[2] );

  createVisDegDigitalFilter( spencerPSF3_Y, &f, pixelsPerDeg );
  normalizeToSum( &f );
  multiplyAndAddArray( filterSpatial, &f, w[3] );
  
  normalizeToSum( filterSpatial );
  
  dumpImageAspect->dump( "filter_otf.pfs", filterSpatial, "Y" );
  dumpImageAspect->dumpFrequency( "filter_otf_fft.pfs", &filter );  
  std::cerr << ".\n";
}
Ejemplo n.º 2
0
MultiAdaptationCSF::MultiAdaptationCSF( int cols, int rows,
  const ViewingConditions &viewCond ) 
{
  
  // TODO: Find min, max and decide what adaptation levels should be used
//   float amMin = 9999999;
//   float amMax = -9999999;
//   const int size = in->getRows()*in->getCols();
//   for( int i = 0; i < size; i++ ) {
//     const float v = (*adaptationMap)(i);
//     if( amMin > v ) amMin = v;
//     else if( amMax < v ) amMax = v;
//   }
  
//   static const float templateAdaptationLevels[] = 
//     {
//       0.0001, 0.01, 0.1, 1, 10, 100
//     };
//   for( int i = 0; i < sizeof( templateAdaptationLevels ) / sizeof( float ); i++ ) {
//     if( templateAdaptationLevels[i+1]
//   }

  static const float templateAdaptationLevels[] = 
    {
      0.0001, 0.01, 0.1, 1, 10, 100
    };
  const int templateAdaptationLevelsCount = sizeof( templateAdaptationLevels ) / sizeof( float );
  
  for( int i = 0; i < templateAdaptationLevelsCount; i++ ) 
    adaptationLevels[i] = templateAdaptationLevels[i];
  adaptationLevelsCount = templateAdaptationLevelsCount;

  //NOT compatible with new Cygwin version of gcc.
  //filters = new (pfs::Array2DImpl*)[adaptationLevelsCount]; 
  filters = new pfs::Array2DImpl*[adaptationLevelsCount];
  
  // Prepare CSF filters
  for( int i = 0; i < adaptationLevelsCount; i++ ) { // For each adaptation level
    std::cerr << "Creating CSF filter: ";
    // Build CSF filter for the viewing conditions
    filters[i] = new pfs::Array2DImpl( cols/2+1, rows/2+1 );

    float meanObserverDistance = (viewCond.minDistance + viewCond.maxDistance)/2;
    float pixelsPerDeg = viewCond.getPixelsPerDegree( meanObserverDistance );
    float imgSizeVD = ((float)viewCond.xResolution / pixelsPerDeg) *
      ((float)viewCond.yResolution / pixelsPerDeg);
    createCSFFilter( filters[i], adaptationLevels[i], imgSizeVD,
      pixelsPerDeg, meanObserverDistance, CSF_DALY_NORMALIZED );
  }  
}
Ejemplo n.º 3
0
VDPCSF::VDPCSF( int cols, int rows, const ViewingConditions &viewCond, const float Y_adapt )
{
  // Build CSF filter for the viewing conditions
  filter = new pfs::Array2DImpl( cols/2+1, rows/2+1 );

  float meanObserverDistance = (viewCond.minDistance + viewCond.maxDistance)/2;
  float pixelsPerDeg = viewCond.getPixelsPerDegree( meanObserverDistance );
  float imgSizeVD = ((float)viewCond.xResolution / pixelsPerDeg) *
    ((float)viewCond.yResolution / pixelsPerDeg);
  createCSFFilter( filter, Y_adapt, imgSizeVD,
    pixelsPerDeg, meanObserverDistance, CSF_DALY );

  dumpImageAspect->dump( "filter_csf.pfs", filter, "Y" );
  
}
Ejemplo n.º 4
0
WestheimerOTF::WestheimerOTF( const ViewingConditions &viewCond, int cols, int rows ) : filter( cols, rows )
{
  pfs::Array2D *filterSpatial = filter.setSpatial();
  const float pixelsPerDeg = viewCond.getPixelsPerDegree(
    (viewCond.maxDistance + viewCond.minDistance)/2. );
  
  std::cerr << "Creating OTF filter..";
  
  WestheimerOTFFunc normannBaxterOTFFunc;
  createVisDegDigitalFilter( &normannBaxterOTFFunc, filterSpatial, pixelsPerDeg );

  dumpImageAspect->dump( "filter_otf.pfs", filterSpatial, "Y" );
  dumpImageAspect->dumpFrequency( "filter_otf_fft.pfs", &filter );
  
  std::cerr << ".\n";
  
}
Ejemplo n.º 5
0
DeeleyOTF::DeeleyOTF( const ViewingConditions &viewCond, int cols, int rows, float adaptationLuminance )
{

  filter = new pfs::Array2DImpl( cols/2+1, rows/2+1 );

  int filterWidth=filter->getCols();
  int filterHeight=filter->getRows();
  
  float meanObserverDistance = (viewCond.minDistance + viewCond.maxDistance)/2;
  float pix_per_deg = viewCond.getPixelsPerDegree( meanObserverDistance );

  float x_norm = 0.5 / filterWidth, y_norm = 0.5 / filterHeight;

  float dx, dy;
  int x, y;

  float p = getPupilDiameter( adaptationLuminance );
  float p_mm = p * 1e3;

  std::cerr << "Creating OTF filter..";


    std::cerr << "(pupil diameter " << p_mm << "mm for adaptation lum " << adaptationLuminance << "cd/m^2)";  

  for (y = 0, dy = 0.0; y < filterHeight; y ++, dy += y_norm)
  {
    for (x = 0, dx = 0.0; x < filterWidth; x ++, dx += x_norm)
    {
      float v = pix_per_deg * sqrtf((float)(dx * dx + dy * dy));
      if( v == 0 ) v = 0.1;
      
      (*filter)(x,y) = expf( -pow(v/ (20.9 - 2.1*p_mm), 1.3-0.07*p_mm) );
      
    }
  }

  (*filter)(0,0) = max( (*filter)(1,0), (*filter)(0,1) );

  normalizeToMax( filter );

  dumpImageAspect->dump( "filter_otf.pfs", filter, "Y" );
  
  std::cerr << ".\n";
}
Ejemplo n.º 6
0
MarimontOTF::MarimontOTF( const ViewingConditions &viewCond,
  int cols, int rows, float adaptationLuminance )
{
  const float n_p = 1.336;
  const float f_p = 22.2888e-3;
  const float D0 = n_p/f_p;

  const float c = 3.434e3;

  const float q1 = 1.7312;
  const float q2 = 0.63346;
  const float q3 = 0.21410;

  filter = new pfs::Array2DImpl( cols/2+1, rows/2+1 );

  
  int filterWidth=filter->getCols();
  int filterHeight=filter->getRows();
  
  float meanObserverDistance = (viewCond.minDistance + viewCond.maxDistance)/2;
  float pix_per_deg = viewCond.getPixelsPerDegree( meanObserverDistance );

  float x_norm = 0.5 / (filterWidth-1), y_norm = 0.5 / (filterHeight-1);

  float dx, dy;
  int x, y;

  float p = getPupilDiameter( adaptationLuminance )/2; // Pupil radius in meters

  std::cerr << "Creating OTF filter..";

  std::cerr << "(pupil diameter " << p*1e3*2 << "mm for adaptation lum " << adaptationLuminance << "cd/m^2)";  

  for (y = 0, dy = 0.0; y < filterHeight; y ++, dy += y_norm)
  {
    for (x = 0, dx = 0.0; x < filterWidth; x ++, dx += x_norm)
    {
      float v = pix_per_deg * sqrtf((float)(dx * dx + dy * dy));
      if( v == 0 ) v = 0.1;

      const int lefSize = sizeof( luminanceEfficiencyFunction ) / sizeof( SpectralSensitivity );
      float H = 0;
      for( int l = 0; l < lefSize; l++ ) {
        
        const float lambda = luminanceEfficiencyFunction[l].lambda*1e-9;
    
        const float s = c*(lambda / (D0*p)) * v;
        
        const float D_lambda = q1 - (q2/(lambda*1e6-q3));
        const float w20 = p*p/2 * D0 * D_lambda / (D0 + D_lambda);
        const float alpha = 4*M_PI/lambda * w20 * fabsf( s );
        const float py_max = sqrtf( (1-(s/2))*(1-(s/2)) );

        const float dpy = py_max/10;
        float h = 0;
        for( float py = 0; py <= py_max; py += dpy ) {  
          h += 4/(M_PI*alpha)*sinf( alpha*(sqrtf(1 - py*py) - fabsf(s)/2) )*dpy;
        }
        H += h*luminanceEfficiencyFunction[l].weight;
      }      

      (*filter)(x,y) = H * (0.3481+0.6519*exp(-0.1212*v));
      
    }
  }

  (*filter)(0,0) = max( (*filter)(1,0), (*filter)(0,1) );

  normalizeToMax( filter );

  dumpImageAspect->dump( "filter_otf.pfs", filter, "Y" );
  
  std::cerr << ".\n";  
   
}