00001 /*!@file TestSuite/retinafilt.C Apply a retinalike transformation to an image */ 00002 00003 ////////////////////////////////////////////////////////////////////////// 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00005 // University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 ////////////////////////////////////////////////////////////////////////// 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 ////////////////////////////////////////////////////////////////////////// 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 ////////////////////////////////////////////////////////////////////////// 00032 // 00033 // Primary maintainer for this file: Laurent Itti <itti@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/TestSuite/retinafilt.C $ 00035 // $Id: retinafilt.C 12074 2009-11-24 07:51:51Z itti $ 00036 // 00037 00038 #include "Image/Image.H" 00039 #include "Image/ImageSet.H" 00040 #include "Image/Pixels.H" 00041 #include "Image/PyramidOps.H" 00042 #include "Raster/Raster.H" 00043 00044 #include <algorithm> // for std::min 00045 #include <cmath> 00046 #include <cstdio> 00047 #include <typeinfo> 00048 00049 //! depth of the pyramid used to obtain the eccentricity-dependent resolution 00050 #define PYR_DEPTH 10 00051 00052 //! blind spot center, as a factor of image width and height, from center 00053 #define BLIND_X 0.15f 00054 #define BLIND_Y 0.00f 00055 00056 //! blind spot 2*sigma^2, in pixels 00057 #define BLIND_2S2 600.0f 00058 00059 //! fovea 2*sigma^2, in pixels: 00060 #define FOVEA_2S2 150.0f 00061 00062 00063 template <class T> 00064 void showtypeof(T t, const char* expr) 00065 { 00066 LINFO("type of %s is %s", expr, typeid(T).name()); 00067 } 00068 00069 #define SHOWTYPEOF(x) showtypeof(x, #x) 00070 00071 /* ###################################################################### */ 00072 int main(int argc, char **argv) 00073 { 00074 bool fovea_blue = false, blind_spot = false; 00075 if (argc < 3) { 00076 fprintf(stderr, 00077 "USAGE: %s [opts] <input.ppm> <output.ppm> [fov_x fov_y]\n" 00078 "options:\n" 00079 " -b implement blind spot\n" 00080 " -f no blue cones in fovea\n", argv[0]); 00081 exit(1); 00082 } 00083 int ar = 1; 00084 if (argv[ar][0] == '-') { 00085 for (unsigned int ii = 1; ii < strlen(argv[ar]); ii ++) { 00086 switch (argv[ar][ii]) { 00087 case 'b': blind_spot = true; break; 00088 case 'f': fovea_blue = true; break; 00089 default: LFATAL("Unknown option '%c'.", argv[ar][ii]); 00090 } 00091 } 00092 ar ++; 00093 } 00094 00095 // read input image: 00096 Image< PixRGB<byte> > input = Raster::ReadRGB(argv[ar++]); 00097 00098 // create gaussian pyramid and destination image: 00099 ImageSet< PixRGB<byte> > pyr = buildPyrGaussian(input, 0, PYR_DEPTH, 5); 00100 00101 // apply radial smoothing: 00102 int w = input.getWidth(), h = input.getHeight(), ci = w / 2, cj = h / 2; 00103 00104 // use given fovea center if present in params: 00105 if (argc - ar > 1) 00106 { 00107 ci = atoi(argv[ar + 1]); ci = std::max(0, std::min(w-1, ci)); 00108 cj = atoi(argv[ar + 2]); cj = std::max(0, std::min(h-1, cj)); 00109 LINFO("Using (%d, %d) for fovea center", ci, cj); 00110 } 00111 00112 Image< PixRGB<byte> > output(w, h, NO_INIT); 00113 float rstep = float(std::max(w, h) / PYR_DEPTH); 00114 int bi = ci + int(w * BLIND_X), bj = cj + int(h * BLIND_Y); 00115 00116 for (int i = 0; i < w; i ++) 00117 for (int j = 0; j < h; j ++) 00118 { 00119 float dist = sqrtf((i-ci)*(i-ci) + (j-cj)*(j-cj)); 00120 00121 // determine resolution from which this pixel will be taken: 00122 float d = dist / rstep; 00123 00124 // get the pixel value from depth d: 00125 int di = int(d); 00126 float dd = d - float(di); 00127 00128 // uncomment these 2 lines for radial pixelization: 00129 //int ii=(i/(1<<di))*(1<<di), jj=(j/(1<<di))*(1<<di); 00130 //if (ii-i<(1<<di) && jj-j<(1<<di)) d=0.0f; else d=1.0f; 00131 00132 Point2D<int> loc(i, j); 00133 PixRGB<byte> pix0 = getPyrPixel(pyr, loc, di); 00134 PixRGB<byte> pix1 = getPyrPixel(pyr, loc, std::min(di+1, PYR_DEPTH-1)); 00135 00136 float blind = 1.0f; 00137 if (blind_spot) 00138 blind = 1.0f - expf(-((i-bi)*(i-bi) + (j-bj)*(j-bj)) / BLIND_2S2); 00139 00140 static bool didit = false; 00141 00142 if (!didit) 00143 { 00144 SHOWTYPEOF(pix0); 00145 SHOWTYPEOF(pix1); 00146 SHOWTYPEOF(pix1-pix0); 00147 SHOWTYPEOF((pix1-pix0)*dd); 00148 SHOWTYPEOF(pix0 + (pix1-pix0)*dd); 00149 SHOWTYPEOF((pix0 + (pix1-pix0)*dd) * blind); 00150 didit = true; 00151 } 00152 00153 PixRGB<byte> pix( (pix0 + (pix1 - pix0) * dd) * blind ); 00154 if (fovea_blue) 00155 pix.setBlue(pix.blue() * (1.0f - expf(-dist * dist / FOVEA_2S2))); 00156 00157 // for Nature Reviews Neuroscience paper: neuron-cam mode 00158 //if (dist > 20.0) { 00159 //pix /= exp((dist - 20.0f) / 10.0f); 00160 //} 00161 00162 // store: 00163 output.setVal(loc, pix); 00164 } 00165 00166 // write out result: 00167 Raster::WriteRGB(output, argv[ar], RASFMT_PNM); 00168 return 0; 00169 } 00170 00171 00172 // ###################################################################### 00173 /* So things look consistent in everyone's emacs... */ 00174 /* Local Variables: */ 00175 /* indent-tabs-mode: nil */ 00176 /* End: */