00001 /*!@file BayesFilters/test-PF.C test the filter*/ 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/ParticleFilter.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 "Image/Point3D.H" 00047 00048 00049 00050 00051 //Create a tracker to track a particle with a position and velocity 00052 class ParticleTracker : public ParticleFilter 00053 { 00054 public: 00055 ParticleTracker(int numStates, int numObservations, int numParticles) : 00056 ParticleFilter(numStates, numObservations, numParticles) 00057 { 00058 00059 } 00060 00061 ~ParticleTracker() {}; 00062 00063 Image<double> getNextState(const Image<double>& X) 00064 { 00065 00066 double processMean = -0.1; 00067 double processSigma = 0.075; 00068 double processScale = 0.4; 00069 00070 double posX = X.getVal(0,0); 00071 00072 processMean = processMean + ((posX - processMean)*processScale) + 00073 processSigma * gaussianRand(); 00074 00075 Image<double> Xnew(1,itsNumStates, ZEROS); 00076 Xnew[0] = processMean; 00077 00078 return Xnew; 00079 } 00080 00081 Image<double> getObservation(const Image<double>& X) 00082 { 00083 double posX = X.getVal(0,0); 00084 00085 Image<double> zNew(1,itsNumObservations, ZEROS); 00086 zNew[0] = posX; 00087 return zNew; 00088 } 00089 00090 }; 00091 00092 std::vector<int> getIntervals(int n, int polyDegree) 00093 { 00094 std::vector<int> intervals(n+polyDegree+1); 00095 00096 for (int j=0; j<=n+polyDegree; j++) 00097 { 00098 if (j<polyDegree) 00099 intervals[j]=0; 00100 else 00101 if ((polyDegree<=j) && (j<=n)) 00102 intervals[j]=j-polyDegree+1; 00103 else 00104 if (j>n) 00105 intervals[j]=n-polyDegree+2; // if n-t=-2 then we're screwed, everything goes to 0 00106 } 00107 00108 return intervals; 00109 00110 } 00111 00112 00113 double blend(int k, int t, std::vector<int>& intervals, double v) 00114 { 00115 double value; 00116 00117 if (t==1) // base case for the recursion 00118 { 00119 if ((intervals[k]<=v) && (v<intervals[k+1])) 00120 value=1; 00121 else 00122 value=0; 00123 } else { 00124 if ((intervals[k+t-1]==intervals[k]) && (intervals[k+t]==intervals[k+1])) // check for divide by zero 00125 value = 0; 00126 else 00127 if (intervals[k+t-1]==intervals[k]) // if a term's denominator is zero,use just the other 00128 value = (intervals[k+t] - v) / (intervals[k+t] - intervals[k+1]) * blend(k+1, t-1, intervals, v); 00129 else 00130 if (intervals[k+t]==intervals[k+1]) 00131 value = (v - intervals[k]) / (intervals[k+t-1] - intervals[k]) * blend(k, t-1, intervals, v); 00132 else 00133 value = (v - intervals[k]) / (intervals[k+t-1] - intervals[k]) * blend(k, t-1, intervals, v) + 00134 (intervals[k+t] - v) / (intervals[k+t] - intervals[k+1]) * blend(k+1, t-1, intervals, v); 00135 } 00136 00137 return value; 00138 00139 00140 00141 } 00142 00143 00144 double getWeight(int k, double s) 00145 { 00146 00147 double weight = 0; 00148 00149 if (0 <= s && s < 1) 00150 weight = (s*s)/2; 00151 else if (1 <= s && s < 2) 00152 weight = (3/4)-((s-(3/2))*(s-(3/2))); 00153 else if (2 <= s && s < 3) 00154 weight = ((s-3)*(s-3))/2; 00155 00156 return weight; 00157 } 00158 00159 void drawBSpline(std::vector<Point3D<float> >& controlPoints) 00160 { 00161 00162 int numOutput = 100; //The number of points to output 00163 int polyDegree = 3; 00164 00165 std::vector<int> intervals = getIntervals(controlPoints.size()-1, polyDegree); 00166 double incr = 1.0/double(controlPoints.size()-1); //(double) (controlPoints.size()-1-polyDegree+2)/(numOutput-1); 00167 LINFO("Inc %f", incr); 00168 00169 std::vector<Point3D<float> > points; 00170 double interval = 0; 00171 for(int outputIndex=0; outputIndex<numOutput; outputIndex++) 00172 { 00173 //Compute point 00174 Point3D<float> point(0,0,0); 00175 for(uint k=0; k<controlPoints.size(); k++) 00176 { 00177 double blendVal = blend(k,polyDegree, intervals, interval); 00178 //double blendVal = getWeight(k, interval-k); 00179 point.x += blendVal*controlPoints[k].x; 00180 point.y += blendVal*controlPoints[k].y; 00181 point.z += blendVal*controlPoints[k].z; 00182 } 00183 00184 LINFO("Point %f %f", point.x, point.y); 00185 points.push_back(point); 00186 interval += incr; 00187 } 00188 //the last point is the control 00189 //points.push_back(controlPoints[0]); 00190 00191 LINFO("Draw"); 00192 Image<PixRGB<byte> > tmp(640,480,ZEROS); 00193 for(uint i=0; i<controlPoints.size(); i++) 00194 { 00195 Point2D<int> cLoc = Point2D<int>(controlPoints[i].x,controlPoints[i].y); 00196 drawCircle(tmp, cLoc, 3, PixRGB<byte>(0,255,0)); 00197 } 00198 00199 for(uint i=0; i<points.size()-10; i++) 00200 { 00201 Point2D<int> loc = Point2D<int>(points[i].x,points[i].y); 00202 Point2D<int> loc2 = Point2D<int>(points[(i+1)%points.size()].x,points[(i+1)%points.size()].y); 00203 drawLine(tmp, loc, loc2, PixRGB<byte>(255,0,0)); 00204 //if (tmp.coordsOk(loc)) 00205 // tmp.setVal(loc, PixRGB<byte>(255,0,0)); 00206 } 00207 SHOWIMG(tmp); 00208 00209 00210 } 00211 00212 00213 int main(int argc, char *argv[]){ 00214 00215 ModelManager manager("Test UKF"); 00216 00217 nub::ref<OutputFrameSeries> ofs(new OutputFrameSeries(manager)); 00218 manager.addSubComponent(ofs); 00219 00220 // Parse command-line: 00221 if (manager.parseCommandLine(argc, argv, "", 0, 0) == false) return(1); 00222 // let's get all our ModelComponent instances started: 00223 manager.start(); 00224 ///B Spline 00225 std::vector<Point3D<float> > controlPoints; 00226 //controlPoints.push_back(Point3D<float>(10 , 100,0)); 00227 //controlPoints.push_back(Point3D<float>(200, 100,0)); 00228 //controlPoints.push_back(Point3D<float>(345, 300,0)); 00229 //controlPoints.push_back(Point3D<float>(400, 250,0)); 00230 //controlPoints.push_back(Point3D<float>(500, 550,0)); 00231 //controlPoints.push_back(Point3D<float>(550, 150,0)); 00232 //controlPoints.push_back(Point3D<float>(570, 50,0)); 00233 //controlPoints.push_back(Point3D<float>(600, 100,0)); 00234 00235 controlPoints.push_back(Point3D<float>(50*2.75,50*5.25,0)); 00236 controlPoints.push_back(Point3D<float>(50*3.28,50*7.07,0)); 00237 controlPoints.push_back(Point3D<float>(50*6.61,50*7.08,0)); 00238 controlPoints.push_back(Point3D<float>(50*6.85,50*5.19,0)); 00239 controlPoints.push_back(Point3D<float>(50*5.29,50*4.00,0)); 00240 controlPoints.push_back(Point3D<float>(50*5.67,50*1.28,0)); 00241 controlPoints.push_back(Point3D<float>(50*4.12,50*1.28,0)); 00242 controlPoints.push_back(Point3D<float>(50*4.33,50*4.04,0)); 00243 00244 00245 drawBSpline(controlPoints); 00246 00247 //Initialize tracker with 4 states and 2 observations and 1000 particles 00248 ParticleTracker pt(4,2, 1000); 00249 00250 //Simulate a moving particle with a particuler velocity 00251 Image<PixRGB<byte> > worldImg(640,480,ZEROS); 00252 00253 double processMean = -0.1; 00254 double processSigma = 0.4; 00255 double scaling = 0.075; 00256 00257 00258 00259 for(uint t=0; t<100; t++) 00260 { 00261 double truePosition = processMean; 00262 //Move the particle 00263 processMean = processMean + ((truePosition - processMean)*scaling) + 00264 processSigma * pt.gaussianRand(); 00265 00266 pt.predictState(); 00267 00268 //Observe the state and update 00269 Image<double> z(1,1,ZEROS); 00270 z[0] = processMean + processSigma*pt.gaussianRand(); 00271 pt.update(z); 00272 00273 //Show the results 00274 //worldImg.setVal(Point2D<int>(particlePosition), PixRGB<byte>(0,255,0)); 00275 //if (worldImg.coordsOk(Point2D<int>(pt.getPosition()))) 00276 // worldImg.setVal(Point2D<int>(pt.getPosition()), PixRGB<byte>(255,0,0)); 00277 //Image<PixRGB<byte> > tmp = worldImg; 00278 //drawCircle(tmp, Point2D<int>(particlePosition), 3, PixRGB<byte>(0,255,0),3); 00279 //drawCircle(tmp, Point2D<int>(pt.getPosition()), 3, PixRGB<byte>(255,0,0), 3); 00280 //ofs->writeRGB(tmp, "Particle Tracker", FrameInfo("Particle Tracker", SRC_POS)); 00281 //usleep(100000); 00282 //SHOWIMG(tmp); 00283 getchar(); 00284 } 00285 00286 exit(0); 00287 00288 } 00289 00290