00001 /*!@file Raster/DpxParser.C */ 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/Raster/DpxParser.C $ 00035 // $Id: DpxParser.C 9229 2008-02-07 02:31:25Z rjpeters $ 00036 // 00037 00038 #ifndef RASTER_DPXPARSER_C_DEFINED 00039 #define RASTER_DPXPARSER_C_DEFINED 00040 00041 #include "Raster/DpxParser.H" 00042 00043 #include "Image/Image.H" 00044 #include "Image/MathOps.H" 00045 #include "Image/Pixels.H" 00046 #include "Image/Range.H" 00047 #include "Raster/DpxFile.H" 00048 #include "Raster/GenericFrame.H" 00049 00050 #include <vector> 00051 00052 namespace 00053 { 00054 Image<PixRGB<float> > deBayer(const Image<float>& bayer) 00055 { 00056 Image<PixRGB<float> > result(bayer.getDims(), NO_INIT); 00057 00058 const int w = bayer.getWidth(); 00059 const int h = bayer.getHeight(); 00060 00061 ASSERT(w % 2 == 0); 00062 ASSERT(h % 2 == 0); 00063 00064 Image<float>::const_iterator sptr = bayer.begin(); 00065 Image<PixRGB<float> >::iterator dptr = result.beginw(); 00066 00067 for (int y = 0; y < h; y += 2) 00068 { 00069 for (int x = 0; x < w; x += 2) 00070 { 00071 if (x < 2 || x >= w-2 || y < 2 || y >= h-2) 00072 { 00073 const float r = sptr[0]; 00074 const float g = 0.5f * (sptr[1] + sptr[w]); 00075 const float b = sptr[w+1]; 00076 00077 dptr[0].p[0] = r; 00078 dptr[1].p[0] = r; 00079 dptr[w].p[0] = r; 00080 dptr[w+1].p[0] = r; 00081 00082 dptr[0].p[1] = g; 00083 dptr[1].p[1] = g; 00084 dptr[w].p[1] = g; 00085 dptr[w+1].p[1] = g; 00086 00087 dptr[0].p[2] = b; 00088 dptr[1].p[2] = b; 00089 dptr[w].p[2] = b; 00090 dptr[w+1].p[2] = b; 00091 } 00092 else 00093 { 00094 /* 00095 00096 +------+------+------+------+ 00097 :-w-1 :-w :-w+1 :-w+2 : 00098 : : : : : 00099 : B : G : B : G : 00100 +------+======+======+------+ 00101 :-1 |0 |1 |2 : 00102 : | | | : 00103 : G | R | G | R : 00104 +------+======+======+------+ 00105 :w-1 |w |w+1 |w+2 : 00106 : | | | : 00107 : B | G | B | G : 00108 +------+======+======+------+ 00109 :w*2-1 :w*2 :w*2+1 :w*2+2 : 00110 : : : : : 00111 : G : R : G : R : 00112 +------+------+------+------+ 00113 00114 */ 00115 00116 dptr[0].p[0] = sptr[0]; 00117 dptr[1].p[0] = 0.5f * (sptr[0] + sptr[2]); 00118 dptr[w].p[0] = 0.5f * (sptr[0] + sptr[w*2]); 00119 dptr[w+1].p[0] = 0.25f * (sptr[0] + sptr[2] + sptr[w*2] + sptr[w*2+2]); 00120 00121 dptr[0].p[1] = 0.25f * (sptr[-w] + sptr[-1] + sptr[1] + sptr[w]); 00122 dptr[1].p[1] = 0.5f * sptr[1] + 0.125f * (sptr[-w] + sptr[-w+2] + sptr[w] + sptr[w+2]); 00123 dptr[w].p[1] = 0.5f * sptr[w] + 0.125f * (sptr[-1] + sptr[1] + sptr[w*2-1] + sptr[w*2+1]); 00124 dptr[w+1].p[1] = 0.25f * (sptr[1] + sptr[w] + sptr[w+2] + sptr[w*2+1]); 00125 00126 dptr[0].p[2] = 0.25f * (sptr[-w-1] + sptr[-w+1] + sptr[w-1] + sptr[w+1]); 00127 dptr[1].p[2] = 0.5f * (sptr[w+1] + sptr[-w+1]); 00128 dptr[w].p[2] = 0.5f * (sptr[w+1] + sptr[w-1]); 00129 dptr[w+1].p[2] = sptr[w+1]; 00130 } 00131 00132 sptr += 2; 00133 dptr += 2; 00134 } 00135 00136 sptr += w; 00137 dptr += w; 00138 } 00139 00140 return result; 00141 } 00142 00143 void showStats(const Image<uint16>& img, float sclip_lo, float sclip_hi) 00144 { 00145 const int w = img.getWidth(); 00146 const int h = img.getHeight(); 00147 00148 const int w1 = w/4; 00149 const int w2 = (w*3)/4; 00150 const int h1 = h/4; 00151 const int h2 = (h*3)/4; 00152 00153 const uint16* sptr = img.getArrayPtr(); 00154 Range<uint16> srng; 00155 Range<uint16> srng_center; 00156 00157 int total_lo_clips = 0; 00158 int total_hi_clips = 0; 00159 int center_lo_clips = 0; 00160 int center_hi_clips = 0; 00161 00162 for (int y = 0; y < h; ++y) 00163 for (int x = 0; x < w; ++x) 00164 { 00165 if (*sptr < sclip_lo) 00166 ++total_lo_clips; 00167 else if (*sptr > sclip_hi) 00168 ++total_hi_clips; 00169 00170 srng.merge(*sptr); 00171 if (x >= w1 && x < w2 && y >= h1 && y < h2) 00172 { 00173 srng_center.merge(*sptr); 00174 if (*sptr < sclip_lo) 00175 ++center_lo_clips; 00176 else if (*sptr > sclip_hi) 00177 ++center_hi_clips; 00178 } 00179 ++sptr; 00180 } 00181 00182 LINFO("srng = %u .. %u, srng[center] = %u .. %u, sclip_lo = %g [%g%%, %g%%], sclip_hi = %g [%g%%, %g%%]", 00183 srng.min(), srng.max(), 00184 srng_center.min(), srng_center.max(), 00185 sclip_lo, (100.0 * total_lo_clips) / (w*h), (100.0 * center_lo_clips) / (w*h/4), 00186 sclip_hi, (100.0 * total_hi_clips) / (w*h), (100.0 * center_hi_clips) / (w*h/4)); 00187 } 00188 00189 class ColorTable 00190 { 00191 public: 00192 ColorTable() {} 00193 00194 void init(const size_t size, 00195 const float gamma, 00196 const bool do_log, 00197 const float sigm_contrast, 00198 const float sigm_thresh, 00199 const float sclip_lo, 00200 const float sclip_hi) 00201 { 00202 this->tab.resize(size); 00203 00204 const float cmin = do_log ? logf(sclip_lo > 0.0f ? sclip_lo : 1.0f) : sclip_lo; 00205 const float crng = (do_log ? logf(sclip_hi) : sclip_hi) - cmin; 00206 00207 const float sigmin = 1.0f / (1.0f + expf(sigm_contrast * sigm_thresh)); 00208 const float sigrng = 1.0f / (1.0f + expf(sigm_contrast * (sigm_thresh-1.0f))) 00209 - sigmin; 00210 00211 for (size_t i = 0; i < size; ++i) 00212 { 00213 float val = i; 00214 if (val < sclip_lo) val = sclip_lo; 00215 else if (val > sclip_hi) val = sclip_hi; 00216 00217 if (do_log) 00218 val = logf(val > 0.0f ? val : 1.0f); 00219 00220 val = (val - cmin) / crng; 00221 00222 if (sigm_contrast != 0.0f) 00223 { 00224 val = 1.0f / (1.0f + expf(sigm_contrast * (sigm_thresh - val))); 00225 val = (val - sigmin) / sigrng; 00226 } 00227 00228 val = 255.0f * powf(val, gamma); 00229 00230 this->tab[i] = val; 00231 } 00232 } 00233 00234 std::vector<float> tab; 00235 }; 00236 00237 float defaultGamma = 0.6f; 00238 float defaultSigmoidContrast = 10.0f; 00239 float defaultSigmoidThreshold = 0.1f; 00240 float defaultSrcClipLo = 0.0f; 00241 float defaultSrcClipHi = 5351.0f; 00242 } 00243 00244 // ###################################################################### 00245 void DpxParser::setDefaultGamma(float val) { defaultGamma = val; } 00246 void DpxParser::setDefaultSigmoidContrast(float val) { defaultSigmoidContrast = val; } 00247 void DpxParser::setDefaultSigmoidThreshold(float val) { defaultSigmoidThreshold = val; } 00248 void DpxParser::setDefaultSrcClipLo(float val) { defaultSrcClipLo = val; } 00249 void DpxParser::setDefaultSrcClipHi(float val) { defaultSrcClipHi = val; } 00250 00251 // ###################################################################### 00252 DpxParser::DpxParser(const char* filename) 00253 : 00254 dpx(new DpxFile(filename)), 00255 itsGamma(defaultGamma), 00256 itsDoLog(false), 00257 itsSigmoidContrast(defaultSigmoidContrast), 00258 itsSigmoidThresh(defaultSigmoidThreshold), 00259 itsSclipLo(defaultSrcClipLo), 00260 itsSclipHi(defaultSrcClipHi) 00261 {} 00262 00263 // ###################################################################### 00264 DpxParser::DpxParser(const char* filename, 00265 float gamma, 00266 bool do_log, 00267 float sigm_contrast, 00268 float sigm_thresh, 00269 float sclip_lo, 00270 float sclip_hi) 00271 : 00272 dpx(new DpxFile(filename)), 00273 itsGamma(gamma), 00274 itsDoLog(do_log), 00275 itsSigmoidContrast(sigm_contrast), 00276 itsSigmoidThresh(sigm_thresh), 00277 itsSclipLo(sclip_lo), 00278 itsSclipHi(sclip_hi) 00279 {} 00280 00281 // ###################################################################### 00282 DpxParser::~DpxParser() 00283 { 00284 delete dpx; 00285 } 00286 00287 // ###################################################################### 00288 GenericFrameSpec DpxParser::getFrameSpec() const 00289 { 00290 GenericFrameSpec result; 00291 00292 result.nativeType = GenericFrame::RGB_F32; 00293 result.videoFormat = VIDFMT_AUTO; 00294 result.videoByteSwap = false; 00295 result.dims = dpx->dims; 00296 result.floatFlags = 0; 00297 00298 return result; 00299 } 00300 00301 // ###################################################################### 00302 std::string DpxParser::getComments() const 00303 { 00304 return std::string(); 00305 } 00306 00307 // ###################################################################### 00308 uint DpxParser::getTagCount() const 00309 { 00310 return 0; 00311 } 00312 00313 // ###################################################################### 00314 bool DpxParser::getTag(uint tag, std::string& name, std::string& value) const 00315 { 00316 return false; 00317 } 00318 00319 // ###################################################################### 00320 GenericFrame DpxParser::getFrame() 00321 { 00322 ASSERT(dpx->ih.ImageElement[0].BitSize == 16); 00323 ASSERT(dpx->ih.ImageElement[0].EndOfLinePadding == 0xFFFF); 00324 00325 showStats(dpx->rawimage, itsSclipLo, itsSclipHi); 00326 00327 ColorTable ctab; 00328 ctab.init(1<<16, itsGamma, itsDoLog, 00329 itsSigmoidContrast, itsSigmoidThresh, 00330 itsSclipLo, itsSclipHi); 00331 00332 Image<float> fresult(dpx->dims, NO_INIT); 00333 00334 const uint16* sptr = dpx->rawimage.getArrayPtr(); 00335 for (Image<float>::iterator fptr = fresult.beginw(), 00336 stop = fresult.endw(); fptr != stop; ++fptr, ++sptr) 00337 { 00338 *fptr = ctab.tab[*sptr]; 00339 } 00340 00341 const Image<PixRGB<float> > cimg = deBayer(fresult); 00342 00343 return GenericFrame(cimg, /* flags = */ 0); 00344 } 00345 00346 // ###################################################################### 00347 /* So things look consistent in everyone's emacs... */ 00348 /* Local Variables: */ 00349 /* mode: c++ */ 00350 /* indent-tabs-mode: nil */ 00351 /* End: */ 00352 00353 #endif // RASTER_DPXPARSER_C_DEFINED