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
00038 #ifndef TIGS_FOURIERFEATUREEXTRACTOR_C_DEFINED
00039 #define TIGS_FOURIERFEATUREEXTRACTOR_C_DEFINED
00040
00041 #include "TIGS/FourierFeatureExtractor.H"
00042
00043 #include "Image/CutPaste.H"
00044 #include "Image/DrawOps.H"
00045 #include "Image/FourierEngine.H"
00046 #include "Image/MathOps.H"
00047 #include "Image/Normalize.H"
00048 #include "Image/Range.H"
00049 #include "Image/ShapeOps.H"
00050 #include "TIGS/Drawing.H"
00051 #include "TIGS/TigsOpts.H"
00052 #include "Transport/FrameOstream.H"
00053 #include "Util/log.H"
00054 #include "rutz/trace.h"
00055
00056 FourierFeatureExtractor::FourierFeatureExtractor(OptionManager& mgr) :
00057 FeatureExtractor(mgr, "ffx"),
00058 itsEngine(0),
00059 itsSaveIllustrations(&OPT_FxSaveIllustrations, this),
00060 itsSaveRawMaps(&OPT_FxSaveRawMaps, this)
00061 {}
00062
00063 FourierFeatureExtractor::~FourierFeatureExtractor() { itsEngine = 0; }
00064
00065 Image<PixRGB<byte> > FourierFeatureExtractor::
00066 illustrate(const TigsInputFrame& fin) const
00067 {
00068 GVX_TRACE(__PRETTY_FUNCTION__);
00069
00070 if (fin.isGhost())
00071 LFATAL("FourierFeatureExtractor needs non-ghost frames");
00072
00073 using tigs::labelImage;
00074 using tigs::boxify;
00075
00076 const PixRGB<byte> bg(255, 255, 255);
00077
00078 if (itsEngine == 0)
00079 itsEngine = new FourierEngine<double>(fin.lum().getDims());
00080
00081 const PixRGB<byte> red(255, 64, 64);
00082 const PixRGB<byte> green(96, 192, 96);
00083 const PixRGB<byte> blue(128, 128, 255);
00084 const PixRGB<byte> yellow(160, 160, 0);
00085
00086 const Image<float> lum = fin.lum();
00087 const Image<complexd> fft = itsEngine->fft(fin.lum());
00088
00089 Image<float> logmag = logmagnitude(fft);
00090
00091 logmag *= 15.0f;
00092
00093 {
00094 const Range<float> r = rangeOf(logmag);
00095 LINFO("log(mag(fft)) range: [%f .. %f]", r.min(), r.max());
00096 }
00097
00098 const int flags = 0;
00099
00100 Image<PixRGB<byte> > cart =
00101 normalizeFloat(zoomXY(cartesian(logmag, Dims(128, 128)), 2, 4),
00102 flags);
00103
00104 drawRect(cart, Rectangle::tlbrI(0, 96, 511, 193), red, 1);
00105
00106 Image<float> cropped =
00107 zoomXY(crop(cartesian(logmag, Dims(64, 16)),
00108 Point2D<int>(24, 0), Dims(24, 16)),
00109 8, 32);
00110
00111 cropped -= 80.0f;
00112 cropped *= 5.0f;
00113
00114 {
00115 const Range<float> r = rangeOf(cropped);
00116 LINFO("cropped range: [%f .. %f]", r.min(), r.max());
00117 }
00118
00119 Image<PixRGB<byte> > result =
00120 labelImage(boxify(lum, 4, green), "luminance", green, bg);
00121
00122 result =
00123 concatLooseX(result,
00124 labelImage(boxify(normalizeFloat(logmag, flags),
00125 4, blue),
00126 "log(|fft|)", blue, bg));
00127
00128 result =
00129 concatLooseX(result,
00130 labelImage(boxify(cart, 4, yellow),
00131 "cartesian(log(|fft|))", yellow, bg));
00132
00133 result =
00134 concatLooseX(result,
00135 labelImage(boxify(normalizeFloat(cropped, flags),
00136 4, red),
00137 "cropped(cartesian)", red, bg));
00138
00139 return result;
00140 }
00141
00142 void FourierFeatureExtractor::
00143 saveRawIllustrationParts(const TigsInputFrame& fin,
00144 FrameOstream& ofs) const
00145 {
00146 if (itsEngine == 0)
00147 itsEngine = new FourierEngine<double>(fin.lum().getDims());
00148
00149 const Image<float> lum = fin.lum();
00150 const Image<complexd> fft = itsEngine->fft(fin.lum());
00151
00152 const Image<float> logmag = logmagnitude(fft);
00153
00154 const Image<float> cart = cartesian(logmag, Dims(128, 128));
00155
00156 const Image<float> cropped = crop(cartesian(logmag, Dims(64, 16)),
00157 Point2D<int>(24, 0), Dims(24, 16));
00158
00159 ofs.writeFloat(lum, FLOAT_NORM_PRESERVE, "ffx-luminance");
00160 ofs.writeFloat(logmag, FLOAT_NORM_PRESERVE, "ffx-logmag");
00161 ofs.writeFloat(cart, FLOAT_NORM_PRESERVE, "ffx-cartesian");
00162 ofs.writeFloat(cropped, FLOAT_NORM_PRESERVE, "ffx-cropped");
00163 }
00164
00165 void FourierFeatureExtractor::saveResults(const TigsInputFrame& fin,
00166 FrameOstream& ofs) const
00167 {
00168 if (itsSaveIllustrations.getVal())
00169 ofs.writeRGB(this->illustrate(fin), "ffx");
00170
00171 if (itsSaveRawMaps.getVal())
00172 this->saveRawIllustrationParts(fin, ofs);
00173 }
00174
00175 Image<float> FourierFeatureExtractor::doExtract(const TigsInputFrame& fin)
00176 {
00177 GVX_TRACE(__PRETTY_FUNCTION__);
00178
00179 if (fin.isGhost())
00180 LFATAL("VisualCortexFeatureExtractor needs non-ghost frames");
00181
00182 if (itsEngine == 0)
00183 itsEngine = new FourierEngine<double>(fin.lum().getDims());
00184
00185 const Image<complexd> res = itsEngine->fft(fin.lum());
00186
00187 const Image<float> cart =
00188 cartesian(logmagnitude(res), Dims(64, 16));
00189
00190 Image<float> result =
00191 crop(cart, Point2D<int>(24, 0), Dims(24, 16));
00192
00193 result -= 5.5f;
00194 result *= 80.0f;
00195
00196 const Range<float> r = rangeOf(result);
00197
00198 LINFO("log(mag(fft)) range: [%f .. %f]", r.min(), r.max());
00199
00200 return result;
00201 }
00202
00203
00204
00205
00206
00207
00208
00209
00210 #endif // TIGS_FOURIERFEATUREEXTRACTOR_C_DEFINED