00001 /*!@file AppMedia/app-fft-manipulator.C Manipulate an image in the fft 00002 domain. Used to remove phase or magnitude from an image or movie */ 00003 00004 // //////////////////////////////////////////////////////////////////// // 00005 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00006 // by the University of Southern California (USC) and the iLab at USC. // 00007 // See http://iLab.usc.edu for information about this project. // 00008 // //////////////////////////////////////////////////////////////////// // 00009 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00010 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00011 // in Visual Environments, and Applications'' by Christof Koch and // 00012 // Laurent Itti, California Institute of Technology, 2001 (patent // 00013 // pending; application number 09/912,225 filed July 23, 2001; see // 00014 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00015 // //////////////////////////////////////////////////////////////////// // 00016 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00017 // // 00018 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00019 // redistribute it and/or modify it under the terms of the GNU General // 00020 // Public License as published by the Free Software Foundation; either // 00021 // version 2 of the License, or (at your option) any later version. // 00022 // // 00023 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00024 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00025 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00026 // PURPOSE. See the GNU General Public License for more details. // 00027 // // 00028 // You should have received a copy of the GNU General Public License // 00029 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00030 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00031 // Boston, MA 02111-1307 USA. // 00032 // //////////////////////////////////////////////////////////////////// // 00033 // 00034 // Primary maintainer for this file: David J. Berg <dberg@usc.edu> 00035 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/AppMedia/app-fft-manipulator.C $ 00036 00037 #ifndef APPMEDIA_APP_FFT_MANIPULATOR_C_DEFINED 00038 #define APPMEDIA_APP_FFT_MANIPULATOR_C_DEFINED 00039 00040 #include "Component/ModelManager.H" 00041 #include "Component/ModelOptionDef.H" 00042 00043 #include "Image/ColorOps.H" 00044 #include "Image/FourierEngine.H" 00045 #include "Image/Image.H" 00046 #include "Image/Normalize.H" 00047 #include "Image/MathOps.H" 00048 #include "Media/FrameSeries.H" 00049 #include "Raster/GenericFrame.H" 00050 #include "Raster/Raster.H" 00051 #include "Transport/FrameInfo.H" 00052 #include "Util/Pause.H" 00053 #include "Util/csignals.H" 00054 #include "Util/Timer.H" 00055 00056 #include <complex> 00057 00058 00059 static const ModelOptionCateg MOC_FFTMANIP = { 00060 MOC_SORTPRI_2, "Options for fft manipulation" }; 00061 00062 static const ModelOptionDef OPT_RemovePhase = 00063 { MODOPT_FLAG, "RemovePhase", &MOC_FFTMANIP, OPTEXP_CORE, 00064 "remove the phase component of an image", 00065 "remove-phase", '\0', "--[no]remove-phase", "false" }; 00066 00067 static const ModelOptionDef OPT_RemoveMagnitude = 00068 { MODOPT_FLAG, "RemoveMagnitude", &MOC_FFTMANIP, OPTEXP_CORE, 00069 "remove the phase component of an image", 00070 "remove-magnitude", '\0', "--[no]remove-phase", "false" }; 00071 00072 static const ModelOptionDef OPT_AdjustMagnitude = 00073 { MODOPT_ARG(float), "AdjustMagnitude", &MOC_FFTMANIP, OPTEXP_CORE, 00074 "adjust the power spectrum of an image by 1/frequency^a", 00075 "adjust-magnitude", '\0', "<float>", "0.0" }; 00076 00077 00078 double compute_factor(const complexd& val, const double& mag) 00079 { 00080 return mag*mag / sqrt(val.real()*val.real() + val.imag()*val.imag()); 00081 } 00082 00083 int submain(int argc, const char** argv) 00084 { 00085 volatile int signum = 0; 00086 catchsignals(&signum); 00087 00088 ModelManager manager("FFT-manipulator"); 00089 00090 OModelParam<bool> remPhase(&OPT_RemovePhase, &manager); 00091 OModelParam<bool> remMag(&OPT_RemoveMagnitude, &manager); 00092 OModelParam<float> adjMag(&OPT_AdjustMagnitude, &manager); 00093 00094 nub::soft_ref<InputFrameSeries> ifs(new InputFrameSeries(manager)); 00095 manager.addSubComponent(ifs); 00096 00097 nub::soft_ref<OutputFrameSeries> ofs(new OutputFrameSeries(manager)); 00098 manager.addSubComponent(ofs); 00099 00100 if (manager.parseCommandLine(argc, argv, "", 0, 0) == false) 00101 return(1); 00102 00103 manager.start(); 00104 00105 ifs->startStream(); 00106 00107 int c = 0; 00108 00109 PauseWaiter p; 00110 00111 SimTime tm = SimTime::ZERO(); 00112 00113 while (true) 00114 { 00115 if (signum != 0) 00116 { 00117 LINFO("quitting because %s was caught", signame(signum)); 00118 return -1; 00119 } 00120 00121 if (ofs->becameVoid()) 00122 { 00123 LINFO("quitting because output stream was closed or became void"); 00124 return 0; 00125 } 00126 00127 if (p.checkPause()) 00128 continue; 00129 00130 const FrameState is = ifs->updateNext(); 00131 if (is == FRAME_COMPLETE) 00132 break; 00133 00134 GenericFrame input = ifs->readFrame(); 00135 if (!input.initialized()) 00136 break; 00137 00138 const Image<PixRGB<byte> > rgbin = input.asRgb(); 00139 const Image<float> lin = luminance(rgbin); 00140 const Image<double> lind = lin; 00141 00142 const FrameState os = ofs->updateNext(); 00143 00144 //manipulation here 00145 FourierEngine<double> itsTransform(lind.getDims()); 00146 Image<complexd> fimage = itsTransform.fft(lind); 00147 00148 if (remPhase.getVal()) 00149 { 00150 Image<complexd>::iterator i = fimage.beginw(); 00151 while (i != fimage.endw()) 00152 { 00153 const double mag = abs(*i); 00154 const complexd conj(i->real(), -1 * i->imag()); 00155 const complexd temp = *i * conj; 00156 const double fac = compute_factor(temp, mag); 00157 *i++ = complexd(fac * temp.real(), fac * temp.imag()); 00158 } 00159 } 00160 00161 if (remMag.getVal()) 00162 { 00163 Image<complexd>::iterator i = fimage.beginw(); 00164 while (i != fimage.endw()) 00165 { 00166 const double fac = compute_factor(*i, 1.0); 00167 *i = complexd(fac * i->real(), fac * i->imag()); 00168 ++i; 00169 } 00170 } 00171 00172 if(adjMag.getVal() > 0.0F) 00173 { 00174 const float exp = -1.0 * adjMag.getVal() / 2.0; 00175 00176 Image<double> mask(fimage.getDims(), NO_INIT); 00177 Image<double>::iterator i = mask.beginw(); 00178 for (int v = 0; v < fimage.getHeight(); ++v) 00179 for (int u = 0; u < fimage.getWidth(); ++u) 00180 if ((v == 0) && (u == 0)) 00181 *i++ = 1.0; 00182 else 00183 *i++ = pow(u*u + v*v, exp); 00184 00185 Image<complexd>::iterator f = fimage.beginw(); 00186 Image<double>::const_iterator m = mask.begin(); 00187 while (f != fimage.endw()) 00188 { 00189 const double fac = compute_factor(*f, *m); 00190 *f = complexd(fac * f->real(), fac * f->imag()); 00191 ++f; ++m; 00192 } 00193 } 00194 00195 FourierInvEngine<double> itsInvTransform(lind.getDims()); 00196 const Image<double> ifimage = itsInvTransform.ifft(fimage); 00197 Image<double> out = ifimage / ifimage.getSize(); 00198 00199 double mn,mx; 00200 getMinMax(out,mn,mx); 00201 out = out - mn; 00202 getMinMax(out,mn,mx); 00203 out /= mx; 00204 out *= 255.0; 00205 00206 00207 const Image<float> outf = out; 00208 ofs->writeFloat(outf, FLOAT_NORM_PRESERVE, "output"); 00209 00210 if (os == FRAME_FINAL) 00211 break; 00212 00213 LDEBUG("frame %d", c++); 00214 00215 if (ifs->shouldWait() || ofs->shouldWait()) 00216 Raster::waitForKey(); 00217 00218 tm += SimTime::HERTZ(30); 00219 } 00220 00221 return 0; 00222 } 00223 00224 int main(const int argc, const char **argv) 00225 { 00226 try 00227 { 00228 return submain(argc, argv); 00229 } 00230 catch (...) 00231 { 00232 REPORT_CURRENT_EXCEPTION; 00233 } 00234 00235 return 1; 00236 } 00237 00238 // ###################################################################### 00239 /* So things look consistent in everyone's emacs... */ 00240 /* Local Variables: */ 00241 /* indent-tabs-mode: nil */ 00242 /* End: */ 00243 00244 #endif // APPMEDIA_APP_FFT_MANIPULATOR_C_DEFINED