00001 /*!@file BeoSub/BeoSubTaskDecoder.C */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2003 // 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 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/BeoSub/BeoSubTaskDecoder.C $ 00035 // $Id: BeoSubTaskDecoder.C 10794 2009-02-08 06:21:09Z itti $ 00036 // 00037 00038 #include "BeoSub/BeoSubTaskDecoder.H" 00039 00040 #include "VFAT/segmentImageTrackMC.H" 00041 #include <iostream> 00042 00043 // ###################################################################### 00044 BeoSubTaskDecoder::BeoSubTaskDecoder(OptionManager& mgr, 00045 const std::string& descrName, 00046 const std::string& tagName) : 00047 ModelComponent(mgr, descrName, tagName) 00048 { 00049 00050 debugmode = false; 00051 setup = false; 00052 color.resize(4,0.0F); 00053 std.resize(4,0.0F); 00054 norm.resize(4,0.0F); 00055 adapt.resize(4,0.0F); 00056 lowerBound.resize(4,0.0F); 00057 upperBound.resize(4,0.0F); 00058 candidate_color = "none"; 00059 Hz = 0.0F; 00060 fps = 0.0F; 00061 res = 0.0F; 00062 00063 //NOTE that hardcoding these dimensions may be harmful and thus have to be FIXed 00064 00065 width = 320; 00066 height = 240; 00067 00068 segmenter = new segmentImageTrackMC<float,unsigned int, 4> (width*height); 00069 00070 int wi = 320/4; 00071 int hi = 240/4; 00072 00073 segmenter->SITsetFrame(&wi,&hi); 00074 00075 segmenter->SITsetCircleColor(0,255,0); 00076 segmenter->SITsetBoxColor(255,255,0,0,255,255); 00077 segmenter->SITsetUseSmoothing(false,10); 00078 00079 00080 segmenter->SITtoggleCandidateBandPass(false); 00081 segmenter->SITtoggleColorAdaptation(false); 00082 00083 } 00084 00085 BeoSubTaskDecoder::~BeoSubTaskDecoder() {} 00086 00087 void BeoSubTaskDecoder::setupRed() 00088 { 00089 //----------------------------------------------- 00090 //! Mean color to track red blinking bike LED 00091 // H1 - H2 - S - V 00092 00093 colorConf.openFile("colortrack.conf", true); 00094 00095 PixRGB<float> P1(colorConf.getItemValueF("RED_R"), 00096 colorConf.getItemValueF("RED_G"), 00097 colorConf.getItemValueF("RED_B")); 00098 00099 PixH2SV1<float> RED(P1); 00100 00101 color[0] = RED.H1(); color[1] = RED.H2(); color[2] = RED.S(); color[3] = RED.V(); 00102 00103 printf("h1: %f, h2: %f, sat: %f, value: %f", color[0], color[1], color[2], color[3]); 00104 00105 //! +/- tollerance value on mean for track 00106 std[0] = colorConf.getItemValueF("RED_std0"); 00107 std[1] = colorConf.getItemValueF("RED_std1"); 00108 std[2] = colorConf.getItemValueF("RED_std2"); 00109 std[3] = colorConf.getItemValueF("RED_std3"); 00110 00111 //! normalizer over color values (highest value possible) 00112 norm[0] = colorConf.getItemValueF("RED_norm0"); 00113 norm[1] = colorConf.getItemValueF("RED_norm1"); 00114 norm[2] = colorConf.getItemValueF("RED_norm2"); 00115 norm[3] = colorConf.getItemValueF("RED_norm3"); 00116 00117 //! how many standard deviations out to adapt, higher means less bias 00118 adapt[0] = colorConf.getItemValueF("RED_adapt0"); 00119 adapt[1] = colorConf.getItemValueF("RED_adapt1"); 00120 adapt[2] = colorConf.getItemValueF("RED_adapt2"); 00121 adapt[3] = colorConf.getItemValueF("RED_adapt3"); 00122 00123 //! highest value for color adaptation possible (hard boundry) 00124 upperBound[0] = color[0] + colorConf.getItemValueF("RED_up0"); 00125 upperBound[1] = color[1] + colorConf.getItemValueF("RED_up1"); 00126 upperBound[2] = color[2] + colorConf.getItemValueF("RED_up2"); 00127 upperBound[3] = color[3] + colorConf.getItemValueF("RED_up3"); 00128 00129 //! lowest value for color adaptation possible (hard boundry) 00130 lowerBound[0] = color[0] - colorConf.getItemValueF("RED_lb0"); 00131 lowerBound[1] = color[1] - colorConf.getItemValueF("RED_lb1"); 00132 lowerBound[2] = color[2] - colorConf.getItemValueF("RED_lb2"); 00133 lowerBound[3] = color[3] - colorConf.getItemValueF("RED_lb3"); 00134 } 00135 00136 void BeoSubTaskDecoder::setupGreen() { 00137 /* 00138 colorConf.openFile("colortrack.conf", true); 00139 00140 PixRGB<float> P1(colorConf.getItemValueF("GREEN_R"), 00141 colorConf.getItemValueF("GREEN_G"), 00142 colorConf.getItemValueF("GREEN_B")); 00143 00144 PixH2SV1<float> GREEN(P1); 00145 00146 color[0] = GREEN.H1(); color[1] = GREEN.H2(); color[2] = GREEN.S(); color[3] = GREEN.V(); 00147 00148 //! +/- tollerance value on mean for track 00149 std[0] = colorConf.getItemValueF("GREEN_std0"); 00150 std[1] = colorConf.getItemValueF("GREEN_std1"); 00151 std[2] = colorConf.getItemValueF("GREEN_std2"); 00152 std[3] = colorConf.getItemValueF("GREEN_std3"); 00153 00154 //! normalizer over color values (highest value possible) 00155 norm[0] = colorConf.getItemValueF("GREEN_norm0"); 00156 norm[1] = colorConf.getItemValueF("GREEN_norm1"); 00157 norm[2] = colorConf.getItemValueF("GREEN_norm2"); 00158 norm[3] = colorConf.getItemValueF("GREEN_norm3"); 00159 00160 //! how many standard deviations out to adapt, higher means less bias 00161 adapt[0] = colorConf.getItemValueF("GREEN_adapt0"); 00162 adapt[1] = colorConf.getItemValueF("GREEN_adapt1"); 00163 adapt[2] = colorConf.getItemValueF("GREEN_adapt2"); 00164 adapt[3] = colorConf.getItemValueF("GREEN_adapt3"); 00165 00166 //! highest value for color adaptation possible (hard boundry) 00167 upperBound[0] = color[0] + colorConf.getItemValueF("GREEN_up0"); 00168 upperBound[1] = color[1] + colorConf.getItemValueF("GREEN_up1"); 00169 upperBound[2] = color[2] + colorConf.getItemValueF("GREEN_up2"); 00170 upperBound[3] = color[3] + colorConf.getItemValueF("GREEN_up3"); 00171 00172 //! lowest value for color adaptation possible (hard boundry) 00173 lowerBound[0] = color[0] - colorConf.getItemValueF("GREEN_lb0"); 00174 lowerBound[1] = color[1] - colorConf.getItemValueF("GREEN_lb1"); 00175 lowerBound[2] = color[2] - colorConf.getItemValueF("GREEN_lb2"); 00176 lowerBound[3] = color[3] - colorConf.getItemValueF("GREEN_lb3");*/ 00177 } 00178 00179 00180 void BeoSubTaskDecoder::setupDecoder(const char* inputColor, bool debug) { 00181 debugmode = debug; 00182 candidate_color = inputColor; 00183 00184 if(!strcmp(candidate_color, "Green")){ 00185 setupGreen(); 00186 } 00187 else if(!strcmp(candidate_color, "Red")){ 00188 setupRed(); 00189 } 00190 else{ 00191 printf("Cannot setup decoder without a color to decode! exiting...\n"); 00192 return; 00193 } 00194 00195 segmenter->SITsetTrackColor(&color,&std,&norm,&adapt,&upperBound,&lowerBound); 00196 00197 if(debugmode){ 00198 wini.reset(new XWindow(Dims(width, height), 0, 0, "test-input window")); 00199 wini->setPosition(0, 0); 00200 wino.reset(new XWindow(Dims(width, height), 0, 0, "test-output window")); 00201 wino->setPosition(width+10, 0); 00202 } 00203 00204 setup = true; 00205 } 00206 00207 // ###################################################################### 00208 bool BeoSubTaskDecoder::runDecoder(ImageSet< PixRGB<byte> > images, float framerate) { 00209 00210 if(!setup){ 00211 printf("Must setup decoder with a color and debug mode before running!\n"); 00212 } 00213 imgList = images; 00214 fps = framerate; 00215 00216 00217 frameCounter.clear(); //added this line to prevent it from doing an average over time --Kevin 00218 // DECODE 00219 res = 0; 00220 float on_res = 0; 00221 float off_res = 0; 00222 int lastBlink = 0; 00223 00224 for(uint j = 0; j < imgList.size(); j++) { 00225 00226 Image<PixRGB<byte> > Aux; 00227 Aux.resize(100,450,true); 00228 00229 /******************************************************************/ 00230 // SEGMENT IMAGE ON EACH INPUT FRAME 00231 H2SVimage = imgList[j]; 00232 display = imgList[j]; 00233 00234 segmenter->SITtrackImageAny(H2SVimage,&display,&Aux,true); 00235 00236 /* Retrieve and Draw all our output images */ 00237 Image<byte> temp = quickInterpolate(segmenter->SITreturnCandidateImage(),4); 00238 00239 if(debugmode){ 00240 wini->drawImage(display); 00241 wino->drawImage(temp); 00242 } 00243 00244 /****************************************************************/ 00245 // ADD EACH FRAME TO A VECTOR INDICATING IF LIGHT WAS ON/OFF 00246 if(!segmenter->SITreturnLOT()) { 00247 frameCounter.push_back(true); 00248 lastBlink = frameCounter.size(); 00249 if(frameCounter[frameCounter.size() - 2] == false) 00250 on_res++; 00251 } 00252 else { 00253 frameCounter.push_back(false); 00254 off_res++; 00255 } 00256 00257 00258 // // if the camera caught a remant of the light ON from the previous frame, ignore it 00259 // if(frameCounter.size() > 2 && frameCounter[frameCounter.size() - 1] == true 00260 // && frameCounter[frameCounter.size() - 2] == false) 00261 // frameCounter.push_back(false); 00262 // else 00263 // frameCounter.push_back(true); 00264 00265 // } 00266 // else 00267 // frameCounter.push_back(false); 00268 00269 } 00270 00271 /// if(lastBlink < (int)frameCounter.size()) 00272 /// off_res - frameCounter.size() + lastBlink; 00273 00274 frameCounter.resize(lastBlink); 00275 res = off_res / on_res; 00276 printf("off_res: %f\n", off_res); 00277 printf("on_res: %f\n", on_res); 00278 printf("res: %f\n", res); 00279 //for(uint j = 1; j < frameCounter.size(); j++) { 00280 00281 // look at the blinker as a clock, we just like for the rising edge. 00282 //if(frameCounter[j] == true && frameCounter[j-1] == false) 00283 00284 //calculateHz(); 00285 //order(); 00286 return(true); //junk return, cuz it balks otherwise 00287 00288 } 00289 00290 float BeoSubTaskDecoder::calculateHz() { 00291 00292 int numBlinks = 0; 00293 int last_on = -1; 00294 00295 if(frameCounter[0]) 00296 numBlinks++; 00297 00298 std::cout << "frameCounter[0]: " << frameCounter[0] << '\n'; 00299 00300 for(uint j = 1; j < frameCounter.size(); j++) { 00301 00302 std::cout << "frameCounter[" << j << "]: " << frameCounter[j] << '\n'; 00303 00304 00305 if(frameCounter[j]) { 00306 last_on = j; 00307 // fills in small holes, if color tracker did not pick up entire length of blink. 00308 // depends on resolution 00309 if(res > 1 && last_on >= 0 && last_on == (int)j - 2) 00310 frameCounter[j - 1] = true; 00311 00312 //rising edge 00313 if(!frameCounter[j-1]) 00314 numBlinks++; 00315 } 00316 } 00317 00318 00319 float secs = frameCounter.size() / fps; 00320 00321 Hz = (float)numBlinks / secs; 00322 00323 printf("res: %f\n", res); 00324 printf("numBlinks: %d\n", numBlinks); 00325 printf("fps: %f\n", fps); 00326 printf("secs: %f\n", secs); 00327 00328 // unsigned int traverse = 0; 00329 00330 // while(traverse < frameCounter.size() && frameCounter[traverse] == false) 00331 // traverse++; 00332 00333 00334 // float denominator = 0; 00335 // float numerator = traverse; 00336 00337 // for(unsigned int i = traverse; i < frameCounter.size(); i++) { 00338 // std::cout << i << ": "; 00339 00340 // if(frameCounter[i] == true) { 00341 // if(debugmode) 00342 // std::cout << "true\n"; 00343 00344 // denominator++; 00345 00346 // if(frameCounter.size() > 2 && fps > 15 && frameCounter[i - 2] == true) 00347 // denominator--; 00348 // } 00349 // else { 00350 // if(debugmode) 00351 // std::cout << "false\n"; 00352 00353 // numerator++; 00354 // } 00355 00356 // } 00357 00358 // Hz = denominator / ((denominator + numerator) / fps); 00359 00360 if(debugmode){ 00361 // std::cout << "there are " << denominator << " trues\n"; 00362 // std::cout << "there are " << numerator << " falses\n"; 00363 std::cout << "frequency is about " << Hz << "Hz\n"; 00364 } 00365 00366 float ones = (int)Hz; 00367 float tenths = (int)((Hz - ones) * 10 + 0.5); 00368 00369 float final_Hz = ones + tenths/10; 00370 return(final_Hz); 00371 00372 } 00373 00374 void BeoSubTaskDecoder::order() { 00375 if(strcmp(candidate_color, "Red") == 0 && Hz == 5.0F) {} 00376 //this is the order 00377 else {} 00378 }