00001 /*!@file AppMedia/app-mouseChaserColorHist.C get estimate of mouse position in temperature preference assay using color histogram */ 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-mouseChaserColorHist.C $ 00035 // $Id: $ 00036 // 00037 00038 #ifndef APPMEDIA_APP_MOUSE_CHASER_COLORHIST_C_DEFINED 00039 #define APPMEDIA_APP_MOUSE_CHASER_COLORHIST_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 "Transport/FrameInfo.H" 00061 #include <cstdio> 00062 #include <numeric> 00063 #include <iostream> 00064 #include <fstream> 00065 00066 Point2D<int> getMeanMotion(const Image<float>& itsImg,float thresh); 00067 Point2D<int> featTrack(Image<PixRGB<byte> >& crnt, Point2D<int> prevTrackPt, 00068 PixRGB<float> itsMeanRGB, Dims rectDims); 00069 float euclidDist(PixRGB<float> a, PixRGB<float> b); 00070 00071 int prevDir = 0; 00072 int main(int argc,const char**argv) 00073 { 00074 00075 //Instantiate a ModelManager: 00076 ModelManager *mgr = new ModelManager("Animal Tracker"); 00077 nub::ref<InputFrameSeries> ifs(new InputFrameSeries(*mgr)); 00078 nub::ref<OutputFrameSeries> ofs(new OutputFrameSeries(*mgr)); 00079 00080 mgr->addSubComponent(ifs); 00081 mgr->addSubComponent(ofs); 00082 00083 mgr->setOptionValString(&OPT_FrameGrabberFPS, "30"); 00084 mgr->exportOptions(MC_RECURSE); 00085 00086 // Parse command-line: 00087 if (mgr->parseCommandLine(argc, argv, "", 0, 0) == false) return(1); 00088 00089 // do post-command-line configs: 00090 Dims imageDims = ifs->peekDims(); 00091 LINFO("w=%d,h=%d",imageDims.w(),imageDims.h()); 00092 00093 Dims layer_screen(800,800); 00094 XWindow layers(layer_screen, 0, 0, "layers"); //preview window 00095 00096 // let's get all our ModelComponent instances started: 00097 mgr->start(); 00098 00099 const FrameState is = ifs->updateNext(); 00100 if(is == FRAME_COMPLETE) 00101 LFATAL("frames completed!"); 00102 00103 Image <PixRGB<byte> > crnt,prev; 00104 Image <PixRGB<byte> > dispImg; 00105 std::vector<Image<PixRGB<byte> > > frames; 00106 00107 prev = ifs->readRGB(); 00108 frames.push_back(prev); 00109 00110 if(!prev.initialized()) 00111 LFATAL("frame killed"); 00112 //figure out plate region threshold 00113 bool happy=false,happyBlob=false; 00114 int crit = imageDims.w()/2; 00115 int x,y; 00116 Dims rectDims(imageDims.w()/8,imageDims.h()/8); 00117 00118 dispImg = prev; 00119 drawLine(dispImg,Point2D<int>(crit,0), 00120 Point2D<int>(crit,imageDims.h()),PixRGB<byte>(255,0,0),2); 00121 drawGrid(dispImg,10,10,1,PixRGB<byte> (255,0,0)); 00122 layers.drawImage(dispImg,0,0); 00123 std::string saveName; 00124 saveName = mgr->getOptionValString(&OPT_InputFrameSource); 00125 saveName = saveName + ".dat"; 00126 std::ofstream outFile(saveName.c_str()); 00127 00128 while(!happy && !happyBlob) 00129 { 00130 Image<PixRGB<byte> > testImg = prev; 00131 00132 int choice, choiceX, choiceY; 00133 LINFO("Input a threshold image center is at %d: ",imageDims.w()/2); 00134 std::cin >> choice; 00135 if(choice == -1) 00136 happy =true; 00137 else 00138 { 00139 drawLine(testImg,Point2D<int>(choice,0), 00140 Point2D<int>(choice,imageDims.h()),PixRGB<byte>(255,0,0),2); 00141 drawGrid(testImg,10,10,0.5,PixRGB<byte> (255,0,0)); 00142 layers.drawImage(testImg,0,0); 00143 crit = choice; 00144 } 00145 00146 LINFO("Input an x pos: "); 00147 std::cin >> choiceX; 00148 LINFO("Input an y pos: "); 00149 std::cin >> choiceY; 00150 00151 if(choiceX == -1) 00152 happyBlob =true; 00153 else 00154 { 00155 Rectangle r1(Point2D<int>(choiceX,choiceY),rectDims); 00156 drawRect(testImg,r1,PixRGB<byte>(0,255,0),1); 00157 layers.drawImage(testImg,0,0); 00158 x = choiceX; 00159 y = choiceY; 00160 } 00161 } 00162 00163 00164 LINFO("processing..."); 00165 00166 Timer T,frameTim; 00167 T.reset(); 00168 int fTotal=1; 00169 00170 frameTim.reset(); 00171 00172 std::vector<int> trackX; 00173 std::vector<int> trackY; 00174 00175 trackX.push_back(x); 00176 trackY.push_back(y); 00177 00178 Point2D<int> prevTrackPt, crntTrackPt; 00179 prevTrackPt = Point2D<int>(x,y); 00180 00181 Image<PixRGB<float> > target= crop(prev,prevTrackPt,rectDims,false); 00182 PixRGB<float> itsMeanRGB = meanRGB(target); 00183 int leftCnt=0,rightCnt=0; 00184 00185 Image<PixRGB<byte> > meanBkg =prev; 00186 00187 while(is != FRAME_COMPLETE) 00188 { 00189 const FrameState is = ifs->updateNext(); 00190 if(is == FRAME_COMPLETE) 00191 break; 00192 00193 //grab the images 00194 crnt = ifs->readRGB(); 00195 00196 if(!crnt.initialized()) 00197 break; 00198 00199 crntTrackPt = featTrack(crnt, prevTrackPt, itsMeanRGB,rectDims); 00200 prevTrackPt = crntTrackPt; 00201 00202 Rectangle r1(crntTrackPt,rectDims); 00203 drawRect(crnt,r1,PixRGB<byte>(255,0,0),1); 00204 Point2D<int> cross = crntTrackPt; 00205 cross.i += rectDims.w()/2; 00206 cross.j += rectDims.h()/2; 00207 00208 outFile << cross.i << "\t" << cross.j << std::endl; 00209 //LINFO("crit is %d cross.i =%d cross.j=%d",crit,cross.i,cross.j); 00210 if (cross.i < crit) 00211 { 00212 leftCnt++; 00213 writeText(crnt, Point2D<int> (2,0),"LEFT", 00214 PixRGB<byte>(0,255,0),PixRGB<byte>(0,0,0), 00215 SimpleFont::FIXED(9)); 00216 } 00217 else 00218 { 00219 rightCnt++; 00220 writeText(crnt, Point2D<int> (2,0),"RIGHT", 00221 PixRGB<byte>(0,255,0),PixRGB<byte>(0,0,0), 00222 SimpleFont::FIXED(9)); 00223 } 00224 00225 drawCross(crnt, cross, PixRGB<byte>(255,255,0), 3, 2); 00226 drawLine(crnt, Point2D<int>(crit,0), Point2D<int>(crit,imageDims.h()), 00227 PixRGB<byte>(255,0,0),2); 00228 //frames.push_back(crnt); 00229 // layers.drawImage(crnt,0,0); 00230 ofs->writeRgbLayout(crnt,"MouseChaser", FrameInfo("output",SRC_POS)); 00231 fTotal++; 00232 } 00233 00234 LINFO("Total movie time %f: \ntime to compute motion: %f",frameTim.getSecs(), T.getSecs()); 00235 T.reset(); 00236 00237 LINFO("Result cnts: LEFT = %d, RIGHT= %d ",leftCnt, rightCnt); 00238 float total = (float) (leftCnt + rightCnt); 00239 00240 float leftP = (float)leftCnt/total; 00241 float rightP = (float)rightCnt/total; 00242 00243 LINFO("Results: LEFT = %.2f %%, RIGHT= %.2f %% total=%f", leftP*100.0F, rightP*100.0F,total); 00244 00245 /*for(std::vector<Image<PixRGB<byte> > >::iterator it = frames.begin(); 00246 it!=frames.end()-1;++it) 00247 { 00248 layers.drawImage(*it,0,0); 00249 usleep(250); 00250 }*/ 00251 00252 mgr->stop(); 00253 return 0; 00254 } 00255 00256 //###########################Feat Track################################/ 00257 /*Tracks color blob across a frame--tests 8 positions to find best match 00258 for previous track point*/ 00259 00260 Point2D<int> featTrack(Image<PixRGB<byte> > &crnt, Point2D<int> prevTrackPt, 00261 PixRGB<float> itsMeanRGB, Dims rectDims) 00262 { 00263 int x = prevTrackPt.i; 00264 int y = prevTrackPt.j; 00265 00266 std::vector<Image<PixRGB<byte> > > regions; 00267 std::vector<float> colorDists; 00268 std::vector<Point2D<int> > thePoints; 00269 00270 //int pd = rectDims.w()/5; 00271 int pd =40; 00272 00273 for (int i = x-pd;i <= x+pd; i+=5) 00274 for (int j = y-pd; j<=y+pd; j+=5) 00275 if (crnt.coordsOk(i, j) & 00276 crnt.coordsOk(i + rectDims.w()-1, j + rectDims.h()-1)) 00277 thePoints.push_back(Point2D<int>(i,j)); 00278 00279 std::vector<Point2D<int> >::iterator pItr = thePoints.begin(); 00280 00281 while(pItr != thePoints.end()) 00282 regions.push_back(crop(crnt,*pItr++,rectDims,false)); 00283 00284 for(std::vector<Image<PixRGB<byte> > >::iterator it = regions.begin(); 00285 it!=regions.end(); ++it) 00286 { 00287 int dist = euclidDist(itsMeanRGB,meanRGB(*it)); 00288 Image<PixRGB<float> > temp = *it; 00289 dist = dist + euclidDist(temp.getVal(Point2D<int>(rectDims.w()/2, 00290 rectDims.h()/2)), 00291 itsMeanRGB); 00292 colorDists.push_back(dist); 00293 } 00294 //LINFO("min of the dists was %f", *(std::min_element(colorDists.begin(), 00295 // colorDists.end()))); 00296 //LINFO("min dist is at %td", std::min_element(colorDists.begin(),colorDists.end())-colorDists.begin()); 00297 00298 int min = *(std::min_element(colorDists.begin(),colorDists.end())); 00299 if (min > 120) 00300 return prevTrackPt; 00301 else 00302 { 00303 prevDir = std::min_element(colorDists.begin(),colorDists.end())- 00304 colorDists.begin(); 00305 return thePoints[std::min_element(colorDists.begin(),colorDists.end())- 00306 colorDists.begin()]; 00307 } 00308 } 00309 00310 00311 //###########################Euclid dist################################/ 00312 /*Get euclid dist between pixels*/ 00313 00314 float euclidDist(PixRGB<float> a, PixRGB<float> b) 00315 { 00316 float rDiff, gDiff, bDiff; 00317 rDiff= abs(a.red()-b.red()); 00318 gDiff= abs(a.green()-b.green()); 00319 bDiff= abs(a.blue()-b.blue()); 00320 00321 return sqrt(rDiff*rDiff + gDiff*gDiff + bDiff*bDiff); 00322 } 00323 00324 00325 00326 00327 00328 00329 00330 // ###################################################################### 00331 /* So things look consistent in everyone's emacs... */ 00332 /* Local Variables: */ 00333 /* mode: c++ */ 00334 /* indent-tabs-mode: nil */ 00335 /* End: */ 00336 00337 #endif // APPMEDIA_APP_MOUSE_CHASER_COLORHIST_C_DEFINED