00001 /*!@file TIGS/Figures.C Generate illustration figures for TIGS programs */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00005 // by the 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: Rob Peters <rjpeters at usc dot edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/TIGS/Figures.C $ 00035 // $Id: Figures.C 9412 2008-03-10 23:10:15Z farhan $ 00036 // 00037 00038 #ifndef TIGS_FIGURES_C_DEFINED 00039 #define TIGS_FIGURES_C_DEFINED 00040 00041 #include "TIGS/Figures.H" 00042 00043 #include "Image/ColorOps.H" 00044 #include "Image/CutPaste.H" 00045 #include "Image/DrawOps.H" 00046 #include "Image/Image.H" 00047 #include "Image/FilterOps.H" 00048 #include "Image/MathOps.H" 00049 #include "Image/Pixels.H" 00050 #include "Image/Range.H" 00051 #include "Image/ShapeOps.H" 00052 #include "TIGS/TigsInputFrame.H" 00053 #include "TIGS/TrainingSet.H" 00054 #include "Util/sformat.H" 00055 #include "rutz/trace.h" 00056 00057 namespace 00058 { 00059 Image<PixRGB<byte> > makeBargraph(const Image<double>& src, 00060 const float factor, 00061 const int height, 00062 int intercept, 00063 const int bar_width, 00064 const PixRGB<byte>& back, 00065 const PixRGB<byte>& fore) 00066 { 00067 GVX_TRACE(__PRETTY_FUNCTION__); 00068 Image<PixRGB<byte> > result(bar_width*src.getSize(), height, NO_INIT); 00069 result.clear(back); 00070 00071 if (intercept < 0) intercept = 0; 00072 else if (intercept >= height) intercept = height-1; 00073 00074 for (int i = 0; i < src.getSize(); ++i) 00075 { 00076 const int val = int(factor * src[i]); 00077 00078 int pos = intercept-val; 00079 00080 if (pos < 0) pos = 0; 00081 else if (pos >= height) pos = height-1; 00082 00083 drawLine(result, 00084 Point2D<int>(bar_width*i, pos), 00085 Point2D<int>(bar_width*i, intercept), 00086 fore, bar_width); 00087 } 00088 00089 return result; 00090 } 00091 00092 Image<PixRGB<byte> > addLabel(const Image<PixRGB<byte> >& img, 00093 const PixRGB<byte>& color, 00094 const char* label) 00095 { 00096 Image<PixRGB<byte> > img2(std::max(img.getWidth(), 144), 00097 img.getHeight() + 30, NO_INIT); 00098 00099 img2.clear(color); 00100 00101 inplacePaste(img2, img, Point2D<int>(0,0)); 00102 00103 writeText(img2, Point2D<int>(0, img.getHeight()), 00104 label, PixRGB<byte>(0,0,0), color); 00105 00106 return img2; 00107 } 00108 00109 Image<PixRGB<byte> > stainImg(const Image<float>& img, const int zoom) 00110 { 00111 const Range<float> rr = rangeOf(img); 00112 00113 const PixRGB<float> background(5.0f, 5.0f, 5.0f); 00114 const PixRGB<float> pos_stain(100.0f, 255.0f, 150.0f); 00115 const PixRGB<float> neg_stain(255.0f, 100.0f, 100.0f); 00116 00117 return zoomXY(stainPosNeg(img, 00118 std::max(fabs(rr.max()), fabs(rr.min())), 00119 background, pos_stain, neg_stain), 00120 zoom, zoom); 00121 } 00122 00123 Point2D<int> findScaledMax(const Image<float>& img, const int zoom) 00124 { 00125 Point2D<int> loc; 00126 float maxval; 00127 findMax(img, loc, maxval); 00128 return Point2D<int>( int(zoom*(loc.i+0.5)), int(zoom*(loc.j+0.5)) ); 00129 } 00130 } 00131 00132 Image<PixRGB<byte> > 00133 makeSumoDisplay(const TigsInputFrame& fin, 00134 const Image<float>& eyeposmap, 00135 const TrainingSet& tdata, 00136 const Point2D<int>& eyepos, 00137 const Image<float>& features) 00138 { 00139 GVX_TRACE("makeSumoDisplay"); 00140 00141 if (fin.isGhost()) 00142 LFATAL("makeSumoDisplay() needs non-ghost frames"); 00143 00144 const PixRGB<byte> col_eyepos1(255, 127, 0); 00145 const PixRGB<byte> col_eyepos2(160, 160, 160); 00146 const PixRGB<byte> col_histo_back(0, 15, 15); 00147 const PixRGB<byte> col_histo_fore(0, 255, 255); 00148 00149 Image<PixRGB<byte> > drawframe(fin.origframe()); 00150 00151 drawPatch(drawframe, eyepos, 3, col_eyepos1); 00152 drawCircle(drawframe, eyepos, 30, col_eyepos1, 3); 00153 00154 const int pos = tdata.p2p(eyepos); 00155 00156 ASSERT(fin.lum().getDims() == fin.rg().getDims()); 00157 ASSERT(fin.rg().getDims() == fin.by().getDims()); 00158 00159 const Image<PixRGB<byte> > imgs[4] = 00160 { rescale(drawframe, fin.lum().getDims()/2), decXY(fin.lum(), 2), 00161 decXY(fin.rg(), 2), decXY(fin.by(), 2) }; 00162 00163 const Image<PixRGB<byte> > arr = concatArray(imgs, 4, 2); 00164 00165 Range<float> r = rangeOf(eyeposmap); 00166 00167 static Range<float> rr; 00168 rr.merge(r); 00169 00170 const PixRGB<float> background(15.0f, 15.0f, 15.0f); 00171 const PixRGB<float> pos_stain(15.0f, 255.0f, 100.0f); 00172 const PixRGB<float> neg_stain(255.0f, 15.0f, 50.0f); 00173 00174 Image<PixRGB<byte> > bbiasmap 00175 (zoomXY(stainPosNeg(eyeposmap, 00176 std::max(fabs(rr.max()), fabs(rr.min())), 00177 background, pos_stain, neg_stain), 00178 tdata.inputReduction(), 00179 tdata.inputReduction())); 00180 00181 drawPatch(bbiasmap, eyepos, 3, col_eyepos2); 00182 00183 Image<PixRGB<byte> > bbiasmap2(std::max(bbiasmap.getWidth(), 144), 00184 bbiasmap.getHeight() + 50, ZEROS); 00185 00186 inplacePaste(bbiasmap2, bbiasmap, Point2D<int>(0,0)); 00187 00188 writeText(bbiasmap2, Point2D<int>(0, bbiasmap.getHeight()), 00189 sformat("min: %g (%g)", r.min(), rr.min()).c_str(), 00190 PixRGB<byte>(neg_stain), PixRGB<byte>(0,0,0)); 00191 00192 writeText(bbiasmap2, Point2D<int>(0, bbiasmap.getHeight()+25), 00193 sformat("max: %g (%g)", r.max(), rr.max()).c_str(), 00194 PixRGB<byte>(pos_stain), PixRGB<byte>(0,0,0)); 00195 00196 const Image<PixRGB<byte> > fhisto = 00197 makeBargraph(features, 100.0f/255.0f, 100, 100, 1, 00198 col_histo_back, 00199 col_histo_fore); 00200 00201 const Image<float> resiz_features = 00202 tdata.getFeatures().getHeight() > 1000 00203 ? decY(tdata.getFeatures(), 1 + tdata.getFeatures().getHeight() / 1000) 00204 : tdata.getFeatures(); 00205 00206 const Image<PixRGB<byte> > sumo_features = concatY(fhisto, Image<PixRGB<byte> >(resiz_features)); 00207 00208 const Image<PixRGB<byte> > eyehisto = 00209 makeBargraph(eyeposmap, 00210 50.f/(std::max(fabs(r.min()), 00211 fabs(r.max()))), 00212 100, 50, 00213 1, 00214 col_histo_back, 00215 col_histo_fore); 00216 00217 const Image<float> resiz_positions = 00218 tdata.getPositions().getHeight() > 1000 00219 ? decY(tdata.getPositions(), 1 + tdata.getPositions().getHeight() / 1000) 00220 : tdata.getPositions(); 00221 00222 const Image<PixRGB<byte> > tp = resiz_positions * 255.0f; 00223 00224 Image<PixRGB<byte> > sumo_eyepos = concatY(eyehisto, tp); 00225 00226 drawLine(sumo_eyepos, 00227 Point2D<int>(pos, 0), 00228 Point2D<int>(pos, sumo_eyepos.getHeight()-1), 00229 col_eyepos1, 1); 00230 00231 return concatLooseX(concatLooseY(arr, bbiasmap2), 00232 concatX(sumo_features, sumo_eyepos)); 00233 } 00234 00235 Image<PixRGB<byte> > 00236 makeSumoDisplay2(const TigsInputFrame& fin, 00237 const Image<float>& tdmap, 00238 const Image<float>& bumap, 00239 const Image<float>& combomap, 00240 const TrainingSet& tdata, 00241 const Point2D<int>& eyepos) 00242 { 00243 GVX_TRACE("makeSumoDisplay2"); 00244 00245 if (fin.isGhost()) 00246 LFATAL("makeSumoDisplay2() needs non-ghost frames"); 00247 00248 const int zoom = tdata.inputReduction(); 00249 00250 const Point2D<int> tdpos = findScaledMax(tdmap, zoom); 00251 const Point2D<int> bupos = findScaledMax(bumap, zoom); 00252 const Point2D<int> combopos = findScaledMax(combomap, zoom); 00253 00254 Image<PixRGB<byte> > drawframe(fin.origframe()); 00255 00256 const PixRGB<byte> col_human(255, 127, 0); 00257 const PixRGB<byte> col_td(255, 64, 64); 00258 const PixRGB<byte> col_bu(64, 64, 255); 00259 const PixRGB<byte> col_combo(192, 0, 255); 00260 00261 #define DRAWPOS(img) \ 00262 drawPatch(img, tdpos, 3, col_td); \ 00263 drawCircle(img, tdpos, 18, col_td, 3); \ 00264 drawPatch(img, bupos, 3, col_bu); \ 00265 drawCircle(img, bupos, 18, col_bu, 3); \ 00266 drawPatch(img, combopos, 3, col_combo); \ 00267 drawCircle(img, combopos, 18, col_combo, 3); \ 00268 drawPatch(img, eyepos, 3, col_human); \ 00269 drawCircle(img, eyepos, 30, col_human, 3) 00270 00271 DRAWPOS(drawframe); 00272 00273 Image<PixRGB<byte> > btdmap = stainImg(tdmap, zoom); 00274 DRAWPOS(btdmap); 00275 00276 Image<PixRGB<byte> > bbumap = stainImg(bumap, zoom); 00277 DRAWPOS(bbumap); 00278 00279 Image<PixRGB<byte> > bcombomap = stainImg(combomap, zoom); 00280 DRAWPOS(bcombomap); 00281 00282 #undef DRAWPOS 00283 00284 return concatLooseY 00285 (concatLooseX(addLabel(decXY(lowPass3(drawframe)), col_human, "input"), 00286 addLabel(decXY(lowPass3(btdmap)), col_td, "top-down")), 00287 concatLooseX(addLabel(decXY(lowPass3(bbumap)), col_bu, "bottom-up"), 00288 addLabel(decXY(lowPass3(bcombomap)), col_combo, "bu*td combo"))); 00289 } 00290 00291 // ###################################################################### 00292 /* So things look consistent in everyone's emacs... */ 00293 /* Local Variables: */ 00294 /* mode: c++ */ 00295 /* indent-tabs-mode: nil */ 00296 /* End: */ 00297 00298 #endif // TIGS_FIGURES_C_DEFINED