00001 /*!@file AppPsycho/psycho-showEyePos.C Filter and Show the eye positions*/ 00002 00003 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2003 // 00004 // by the University of Southern California (USC) and the iLab at USC. // 00005 // See http://iLab.usc.edu for information about this project. // 00006 // //////////////////////////////////////////////////////////////////// // 00007 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00008 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00009 // in Visual Environments, and Applications'' by Christof Koch and // 00010 // Laurent Itti, California Institute of Technology, 2001 (patent // 00011 // pending; application number 09/912,225 filed July 23, 2001; see // 00012 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00013 // //////////////////////////////////////////////////////////////////// // 00014 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00015 // // 00016 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00017 // redistribute it and/or modify it under the terms of the GNU General // 00018 // Public License as published by the Free Software Foundation; either // 00019 // version 2 of the License, or (at your option) any later version. // 00020 // // 00021 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00022 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00023 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00024 // PURPOSE. See the GNU General Public License for more details. // 00025 // // 00026 // You should have received a copy of the GNU General Public License // 00027 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00028 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00029 // Boston, MA 02111-1307 USA. // 00030 // //////////////////////////////////////////////////////////////////// // 00031 // Primary maintainer for this file: Lior Elazary <elazary@usc.edu> 00032 // $HeadURL: $ 00033 // $Id: $ 00034 00035 00036 #include "BayesFilters/UKF.H" 00037 #include "Component/ModelManager.H" 00038 #include "Raster/GenericFrame.H" 00039 #include "Image/Layout.H" 00040 #include "Image/MatrixOps.H" 00041 #include "Image/DrawOps.H" 00042 #include "GUI/DebugWin.H" 00043 #include "Util/MathFunctions.H" 00044 #include "Media/FrameSeries.H" 00045 #include "Transport/FrameInfo.H" 00046 #include "Psycho/EyeSFile.H" 00047 00048 //Create a tracker to track a particle with a position and velocity 00049 class EyeFilter : public UKF 00050 { 00051 public: 00052 EyeFilter() : 00053 UKF(6, 2) //Initialize with pos,vel,acc as state and pos as observation 00054 { 00055 00056 //Initial state 00057 itsState.setVal(0,0, 640/2); 00058 itsState.setVal(0,1, 480/2); 00059 itsState.setVal(0,2, 0); 00060 itsState.setVal(0,3, 0); 00061 itsState.setVal(0,4, 0); 00062 itsState.setVal(0,5, 0); 00063 00064 //Initial covariance 00065 itsSigma.setVal(0,0,100.0*100.0); //X Position 00066 itsSigma.setVal(1,1,100.0*100.0); //Y Position 00067 itsSigma.setVal(2,2,0.01*0.01); //X Velocity 00068 itsSigma.setVal(3,3,0.01*0.01); //Y Velocity 00069 itsSigma.setVal(4,4,0.01*0.01); //X Acc 00070 itsSigma.setVal(5,5,0.01*0.01); //Y Acc 00071 00072 double posVar=4; 00073 double velVar=0.1; 00074 double accVar=0.1; 00075 //Initial noise matrix 00076 itsR.setVal(0,0,posVar); //X Pos 00077 itsR.setVal(1,1,posVar); //Y Pos 00078 itsR.setVal(2,2,velVar); //X Vel 00079 itsR.setVal(3,3,velVar); //Y Vel 00080 itsR.setVal(4,4,accVar); //X Acc 00081 itsR.setVal(5,5,accVar); //Y Acc 00082 } 00083 00084 ~EyeFilter() {}; 00085 00086 Image<double> getNextState(const Image<double>& X, int k) 00087 { 00088 double posX = X.getVal(k,0); 00089 double posY = X.getVal(k,1); 00090 double velX = X.getVal(k,2); 00091 double velY = X.getVal(k,3); 00092 double accX = X.getVal(k,4); 00093 double accY = X.getVal(k,5); 00094 00095 Image<double> Xnew(1,itsNumStates, ZEROS); 00096 Xnew[0] = posX + velX; 00097 Xnew[1] = posY + velY; 00098 Xnew[2] = velX + accX; 00099 Xnew[3] = velY + accY; 00100 Xnew[4] = accX; 00101 Xnew[5] = accY; 00102 00103 return Xnew; 00104 } 00105 00106 Image<double> getObservation(const Image<double>& X, int k) 00107 { 00108 double posX = X.getVal(k,0); 00109 double posY = X.getVal(k,1); 00110 00111 00112 Image<double> zNew(1,itsNumObservations, ZEROS); 00113 zNew[0] = posX; 00114 zNew[1] = posY; 00115 return zNew; 00116 } 00117 00118 Point2D<double> getPos() { return Point2D<double>(itsState[0], itsState[1]); } 00119 Point2D<double> getVel() { return Point2D<double>(itsState[2], itsState[3]); } 00120 Point2D<double> getAcc() { return Point2D<double>(itsState[4], itsState[5]); } 00121 00122 void getPosEllipse(Point2D<float>& mu, Point2D<float>& sigma) 00123 { 00124 //Set the Mean 00125 mu.i = itsState[0]; 00126 mu.j = itsState[1]; 00127 00128 //Get the 95% uncertainty region 00129 //Set the major/minor axis 00130 sigma = Point2D<float>(2*sqrt(itsSigma.getVal(0,0)), 00131 2*sqrt(itsSigma.getVal(1,1))); 00132 } 00133 00134 00135 }; 00136 00137 00138 int main(int argc, char *argv[]){ 00139 00140 ModelManager manager("ShowEyePos"); 00141 00142 nub::ref<OutputFrameSeries> ofs(new OutputFrameSeries(manager)); 00143 manager.addSubComponent(ofs); 00144 00145 nub::ref<EyeSFile> eyeS(new EyeSFile(manager)); 00146 manager.addSubComponent(eyeS); 00147 00148 // Parse command-line: 00149 if (manager.parseCommandLine(argc, argv, "<velocity threshold> <delay>", 2, 2) == false) return(1); 00150 // let's get all our ModelComponent instances started: 00151 manager.start(); 00152 00153 double velThresh = atof(manager.getExtraArg(0).c_str()); 00154 int delay = atoi(manager.getExtraArg(1).c_str()); 00155 00156 00157 00158 EyeFilter eyeFilter; 00159 00160 00161 double pVar=3.0; 00162 Image<double> zNoise(2,2,ZEROS); 00163 zNoise.setVal(0,0,pVar*pVar); 00164 zNoise.setVal(1,1,pVar*pVar); 00165 00166 00167 Point2D<float> lastSaccLoc; 00168 00169 Point2D<float> eyeLoc = eyeS->getPos(); 00170 while(eyeLoc.isValid()) 00171 { 00172 ////Predict the eye position 00173 eyeFilter.predictState(); 00174 eyeFilter.predictObservation(zNoise); 00175 00176 00177 ////Update 00178 Image<double> z(1,2,ZEROS); 00179 z[0] = eyeLoc.i; z[1] = eyeLoc.j; 00180 eyeFilter.update(z, zNoise); 00181 00182 00183 //Get the predicted pos,vel and acc 00184 Point2D<double> pos = eyeFilter.getPos(); 00185 Point2D<double> vel = eyeFilter.getVel(); 00186 Point2D<double> acc = eyeFilter.getAcc(); 00187 00188 00189 //Display the eye movement 00190 Image<PixRGB<byte> > display(eyeS->getRawInputDims(),ZEROS); 00191 00192 //Draw the Real eye movement 00193 drawCircle(display, (Point2D<int>)eyeLoc, 2, PixRGB<byte>(0,255,0), 2); 00194 00195 //Draw Our Predicted mean and covariance 00196 Point2D<float> mu, sigma; 00197 eyeFilter.getPosEllipse(mu,sigma); 00198 00199 if (vel.magnitude() > velThresh) 00200 { 00201 drawCircle(display, (Point2D<int>)mu, 3, PixRGB<byte>(0,0,255), 3); 00202 drawLine(display, (Point2D<int>)lastSaccLoc, (Point2D<int>)mu, PixRGB<byte>(255,255,255), 3); 00203 } else { 00204 drawCircle(display, (Point2D<int>)mu, 1, PixRGB<byte>(255,0,0), 1); 00205 lastSaccLoc = mu; 00206 } 00207 00208 00209 if (sigma.i < 500 && sigma.j < 500) 00210 drawEllipse(display, (Point2D<int>)mu, sigma.i,sigma.j, PixRGB<byte>(255,0,0)); 00211 00212 //Show the Predicted Pos Vel and Acc 00213 00214 char msg[255]; 00215 sprintf(msg, "Pos: %0.1fx%0.1f", pos.i, pos.j); 00216 writeText(display, Point2D<int>(0,0), msg, 00217 PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0)); 00218 sprintf(msg, "Vel: %0.2f", vel.magnitude()); 00219 writeText(display, Point2D<int>(0,20), msg, 00220 PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0)); 00221 sprintf(msg, "Acc: %0.2f", acc.magnitude()); 00222 writeText(display, Point2D<int>(0,40), msg, 00223 PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0)); 00224 00225 00226 ofs->writeRGB(display, "EyeMovement", FrameInfo("EyeMovement", SRC_POS)); 00227 00228 eyeLoc = eyeS->getPos(); //Get the next position 00229 00230 usleep(delay); 00231 } 00232 00233 00234 00235 manager.stop(); 00236 exit(0); 00237 00238 } 00239 00240