00001 /*!@file AppMedia/app-mouseChaser.C get estimate of mouse position in temperature preference assay */ 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: Farhan Baluch <fbaluch at usc dot edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/AppMedia/app-mouseChaser.C $ 00035 // $Id: $ 00036 // 00037 00038 #ifndef APPMEDIA_APP_MOUSE_CHASER_C_DEFINED 00039 #define APPMEDIA_APP_MOUSE_CHASER_C_DEFINED 00040 00041 #include "Component/ModelManager.H" 00042 #include "Devices/FrameGrabberConfigurator.H" 00043 #include "Devices/DeviceOpts.H" 00044 #include "GUI/XWindow.H" 00045 #include "Image/Image.H" 00046 #include "Image/MathOps.H" 00047 #include "Image/ShapeOps.H" 00048 #include "Image/ColorOps.H" 00049 #include "Image/DrawOps.H" 00050 #include "Image/Range.H" 00051 #include "Raster/Raster.H" 00052 #include "Transport/FrameIstream.H" 00053 #include "Util/Timer.H" 00054 #include "Util/Types.H" 00055 #include "Util/log.H" 00056 00057 #include "Media/FrameSeries.H" 00058 #include "Media/MediaOpts.H" 00059 #include "Raster/GenericFrame.H" 00060 #include <cstdio> 00061 #include <numeric> 00062 #include <iostream> 00063 00064 Point2D<int> getMeanMotion(const Image<float>& itsImg,float thresh); 00065 00066 00067 int main(int argc,const char**argv) 00068 { 00069 00070 //Instantiate a ModelManager: 00071 ModelManager *mgr = new ModelManager("locust model frame series style"); 00072 00073 nub::ref<InputFrameSeries> ifs(new InputFrameSeries(*mgr)); 00074 mgr->addSubComponent(ifs); 00075 mgr->setOptionValString(&OPT_FrameGrabberFPS, "30"); 00076 mgr->exportOptions(MC_RECURSE); 00077 00078 // Parse command-line: 00079 if (mgr->parseCommandLine(argc, argv, "<threshold>", 1, 1) == false) return(1); 00080 00081 int itsMoThresh = mgr->getExtraArgAs<int>(0); 00082 00083 // do post-command-line configs: 00084 Dims imageDims = ifs->peekDims(); 00085 LINFO("w=%d,h=%d",imageDims.w(),imageDims.h()); 00086 00087 Dims layer_screen(800,800); 00088 XWindow layers(layer_screen, 0, 0, "layers"); //preview window 00089 00090 // let's get all our ModelComponent instances started: 00091 mgr->start(); 00092 00093 const FrameState is = ifs->updateNext(); 00094 if(is == FRAME_COMPLETE) 00095 LFATAL("frames completed!"); 00096 00097 Image <PixRGB<byte> > prev,crnt; 00098 00099 std::vector<Image<PixRGB<byte> > > frames; 00100 std::vector<Image<float> > motion; 00101 00102 prev = ifs->readRGB(); 00103 frames.push_back(prev); 00104 00105 if(!prev.initialized()) 00106 LFATAL("frame killed"); 00107 00108 //figure out plate region threshold 00109 bool happy=false,happyBlob=false; 00110 int crit = imageDims.w()/2; 00111 while(!happy && !happyBlob) 00112 { 00113 Image<PixRGB<byte> > testImg = prev; 00114 int choice,x,y; 00115 00116 LINFO("Input a threshold image center is at %d: ",imageDims.w()/2); 00117 std::cin >> choice; 00118 if(choice == 0) 00119 happy =true; 00120 else 00121 { 00122 00123 drawLine(testImg,Point2D<int>(crit,0), 00124 Point2D<int>(crit,imageDims.h()),PixRGB<byte>(255,0,0),2); 00125 layers.drawImage(rescale(testImg,320,240),0,0); 00126 crit = choice; 00127 00128 } 00129 00130 LINFO("Input an x pos: "); 00131 std::cin >> x; 00132 LINFO("Input an y pos: "); 00133 std::cin >> y; 00134 00135 if(x == -1) 00136 happyBlob =true; 00137 else 00138 { 00139 Rectangle r1(Point2D<int>(x,y),Dims(30,30)); 00140 drawRect(testImg,r1,PixRGB<byte>(255,0,0),1); 00141 layers.drawImage(rescale(testImg,320,240),0,0); 00142 crit = choice; 00143 } 00144 00145 } 00146 00147 00148 LINFO("processing..."); 00149 00150 Timer T,frameTim; 00151 T.reset(); 00152 int fTotal=0; 00153 00154 frameTim.reset(); 00155 while(is != FRAME_COMPLETE) 00156 { 00157 const FrameState is = ifs->updateNext(); 00158 if(is == FRAME_COMPLETE) 00159 break; 00160 00161 //grab the images 00162 crnt = ifs->readRGB(); 00163 if(!crnt.initialized()) 00164 break; 00165 frames.push_back(crnt); 00166 motion.push_back(absDiff(luminance(crnt),luminance(prev))); 00167 prev= crnt; 00168 fTotal++; 00169 } 00170 00171 LINFO("Total movie time %f: \ntime to compute motion: %f",frameTim.getSecs(), 00172 T.getSecs()); 00173 T.reset(); 00174 00175 00176 std::vector<Point2D<int> > posVec; 00177 std::vector<int> posX; 00178 std::vector<Image<float> >::iterator itM = motion.begin(); 00179 Point2D<int> prevMean = getMeanMotion(*itM,itsMoThresh); 00180 int fLeft=0; 00181 posVec.push_back(prevMean); 00182 00183 for(std::vector<Image<PixRGB<byte> > >::iterator it = frames.begin(); 00184 it!=frames.end()-1;++it) 00185 { 00186 Image<PixRGB<byte> > vid= *it; 00187 Point2D<int> meanMotion = getMeanMotion(*itM,80); 00188 if(meanMotion.i == 0 && meanMotion.j == 0) 00189 meanMotion = prevMean; 00190 else 00191 prevMean = meanMotion; 00192 00193 posVec.push_back(meanMotion); 00194 posX.push_back(meanMotion.i); 00195 if (meanMotion.i < crit) 00196 fLeft++; 00197 00198 00199 Image<PixRGB<byte> > mot= *itM; 00200 ++itM; 00201 } 00202 00203 LINFO("time to compute motion position: %f",T.getSecs()); 00204 LINFO("num frames on left %d, num frames on right %d",fLeft,fTotal-fLeft); 00205 LINFO("time on left %f, time on right %f",fLeft/25.0,(fTotal-fLeft)/25.0); 00206 00207 00208 Image<PixRGB<byte> > itsPlot = linePlot(posX, 400,500,0,0, 00209 "xPosition","position","time/s", 00210 PixRGB<byte>(0,0,0), 00211 PixRGB<byte>(255,255,255),5,0); 00212 00213 itM = motion.begin(); 00214 std::vector<Point2D<int> >::iterator posItr = posVec.begin(); 00215 Point2D<int> meanMotion; 00216 layers.drawImage(itsPlot,0,240+10); 00217 for(std::vector<Image<PixRGB<byte> > >::iterator it = frames.begin(); 00218 it!=frames.end()-1;++it) 00219 { 00220 00221 Image<PixRGB<byte> > vid= *it; 00222 Image<PixRGB<byte> > mot= *itM++; 00223 mot= mot*5; 00224 meanMotion = *posItr++; 00225 drawCross(mot,meanMotion,PixRGB<byte>(255,255,0),3,2); 00226 drawLine(mot,Point2D<int>(crit,0),Point2D<int>(crit,imageDims.h()), 00227 PixRGB<byte>(255,0,0),2); 00228 layers.drawImage(rescale(mot,320,240),0,0); 00229 //layers.drawImage(rescale(vid,320,240),0,240 +10); 00230 00231 00232 // usleep(1000); 00233 } 00234 00235 mgr->stop(); 00236 return 0; 00237 } 00238 00239 00240 00241 //###########################getMotionVector############################// 00242 00243 std::vector<Point2D<int> > getMotionVector(const Image<float>& itsImg, 00244 float thresh) 00245 { 00246 00247 std::vector<Point2D<int> > motionVec; 00248 int cnt=0; 00249 00250 for(Image<float>::const_iterator itr=itsImg.begin();itr!=itsImg.end();++itr) 00251 { 00252 if(*itr >= thresh) 00253 motionVec.push_back(Point2D<int>(cnt % itsImg.getWidth(), 00254 (cnt-(cnt % itsImg.getWidth()))/itsImg.getWidth())); 00255 cnt++; 00256 00257 } 00258 return motionVec; 00259 00260 00261 } 00262 00263 //###########################getMotionVector############################// 00264 Point2D<int> getMeanMotion(const Image<float>& itsImg,float thresh) 00265 00266 { 00267 00268 std::vector<Point2D<int> > motionVec = getMotionVector(itsImg,thresh); 00269 00270 if(motionVec.size() == 0) 00271 return Point2D<int>(0,0); 00272 else 00273 { 00274 00275 std::vector<int> x,y; 00276 std::vector<Point2D<int> >::const_iterator itr=motionVec.begin(); 00277 00278 while(itr!=motionVec.end()) 00279 { 00280 Point2D<int> temp = *itr; 00281 x.push_back(temp.i); 00282 y.push_back(temp.j); 00283 ++itr; 00284 } 00285 00286 int meanX= std::accumulate(x.begin(),x.end(),0.0)/x.size(); 00287 int meanY = std::accumulate(y.begin(),y.end(),0.0)/y.size(); 00288 00289 return Point2D<int>(meanX,meanY); 00290 } 00291 00292 } 00293 00294 00295 00296 // ###################################################################### 00297 /* So things look consistent in everyone's emacs... */ 00298 /* Local Variables: */ 00299 /* mode: c++ */ 00300 /* indent-tabs-mode: nil */ 00301 /* End: */ 00302 00303 #endif // APPMEDIA_APP_MOUSE_CHASER_C_DEFINED