00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
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
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
00240
00241
00242
00243
00244 #endif // APPMEDIA_APP_FFT_MANIPULATOR_C_DEFINED