目标跟踪学习笔记_2(particle filter初探1)
首先提供几篇关于粒子滤波算法的博客:
http://www.cnblogs.com/yangyangcv/archive/2010/05/23/1742263.html 这篇博客比较通俗易懂,简单的介绍了粒子滤波的基本工作思想和步骤。
http://www.cnblogs.com/lwbaptx/archive/2011/10/20/2218419.html这篇博客用的是opencv1.0,实现的功能是用粒子滤波跟踪鼠标轨迹,有视频演示,效果还不错。
http://blog.csdn.net/yang_xian521/article/details/6928131 这篇博客是用粒子滤波来做视频目标跟踪的,里面也有opencv2.0的代码,有注释,结构比较清晰。我这里就把他的代码和分析贴出来,里面加了我添加了一些注释,这样看起来更加清晰。
代码和解释如下:
1 // particle_demo.cpp : 定义控制台应用程序的入口点。 2 // 3 4 #include "stdafx.h" 5 /************************************************************************/ 6 /* 7 Description: 基本的粒子滤波目标跟踪 8 Author: Yang Xian 9 Email: yang_xian521@163.com 10 Version: 2011-11-2 11 History: 12 */ 13 /************************************************************************/ 14 #include <iostream> // for standard I/O 15 #include <string> // for strings 16 #include <iomanip> // for controlling float print precision 17 #include <sstream> // string to number conversion 18 19 #include <opencv2/imgproc/imgproc.hpp> 20 #include <opencv2/core/core.hpp> // Basic OpenCV structures (cv::Mat, Scalar) 21 #include <opencv2/highgui/highgui.hpp> // OpenCV window I/O 22 23 using namespace cv; 24 using namespace std; 25 26 // 以下这些参数对结果影响很大,而且也会根据视频内容,会对结果有很大的影响 27 const int PARTICLE_NUM = 25; // 粒子个数 28 // 粒子放入的相关区域 29 const double A1 = 2.0; 30 const double A2 = -1.0; 31 const double B0 = 1.0; 32 // 高斯随机数sigma参数 33 const double SIGMA_X = 1.0; 34 const double SIGMA_Y = 0.5; 35 const double SIGMA_SCALE = 0.001; 36 37 // 粒子结构体 38 typedef struct particle { 39 double x; // 当前x坐标 40 double y; // 当前y坐标 41 double scale; // 窗口比例系数 42 double xPre; // x坐标预测位置 43 double yPre; // y坐标预测位置 44 double scalePre; // 窗口预测比例系数 45 double xOri; // 原始x坐标 46 double yOri; // 原始y坐标 47 Rect rect; // 原始区域大小 48 MatND hist; // 粒子区域的特征直方图 49 double weight; // 该粒子的权重 50 } PARTICLE; 51 52 Mat hsv; // hsv色彩空间的输入图像 53 Mat roiImage; // 目标区域 54 MatND roiHist; // 目标区域直方图 55 Mat img; // 输出的目标图像 56 PARTICLE particles[PARTICLE_NUM]; // 粒子 57 58 int nFrameNum = 0; 59 60 bool bSelectObject = false; // 区域选择标志 61 bool bTracking = false; // 开始跟踪标志 62 Point origin; // 鼠标按下时的点位置 63 Rect selection;// 感兴趣的区域大小 64 65 // 直方图相关参数,特征的选取也会对结果影响巨大 66 // Quantize the hue to 30 levels 67 // and the saturation to 32 levels 68 // value to 10 levels 69 int hbins = 180, sbins = 256, vbin = 10; 70 int histSize[] = {hbins, sbins, vbin}; 71 // hue varies from 0 to 179, see cvtColor 72 float hranges[] = { 0, 180 }; 73 // saturation varies from 0 (black-gray-white) to 255 (pure spectrum color) 74 float sranges[] = { 0, 256 }; 75 // value varies from 0 (black-gray-white) to 255 (pure spectrum color) 76 float vranges[] = { 0, 256 }; 77 const float* ranges[] = {hranges, sranges, vranges}; 78 // we compute the histogram from the 0-th and 1-st channels 79 int channels[] = {0, 1, 2}; 80 81 // 鼠标响应函数,得到选择的区域,保存在selection 82 void onMouse(int event, int x, int y, int, void*) 83 { 84 if( bSelectObject ) 85 { 86 selection.x = MIN(x, origin.x); 87 selection.y = MIN(y, origin.y); 88 selection.width = std::abs(x - origin.x); 89 selection.height = std::abs(y - origin.y); 90 91 selection &= Rect(0, 0, img.cols, img.rows); 92 } 93 94 switch (event) 95 { 96 case CV_EVENT_LBUTTONDOWN: 97 origin = Point(x,y); 98 selection = Rect(x,y,0,0); 99 bSelectObject = true;100 bTracking = false;101 break;102 case CV_EVENT_LBUTTONUP:103 bSelectObject = false;104 // if( selection.width > 0 && selection.height > 0 )105 bTracking = true;106 nFrameNum = 0;107 break;108 }109 }110 111 // 快速排序算法排序函数112 int particle_cmp(const void* p1,const void* p2)113 {114 PARTICLE* _p1 = (PARTICLE*)p1;115 PARTICLE* _p2 = (PARTICLE*)p2;116 117 if(_p1->weight < _p2->weight)118 return 1; //按照权重降序排序119 if(_p1->weight > _p2->weight)120 return -1;121 return 0;122 }123 124 const char* keys = 125 {126 "{1| | 0 | camera number}"127 };128 129 int main(int argc, const char **argv)//这里char **argv前必须用const,why?130 {131 int delay = 30; // 控制播放速度132 char c; // 键值133 134 /*读取avi文件*/135 VideoCapture captRefrnc("IndoorGTTest1.avi"); // 视频文件136 137 /*打开摄像头*/138 //VideoCapture captRefrnc;139 //CommandLineParser parser(argc, argv, keys);//命令解析器函数140 //int camNum = parser.get<int>("1"); 141 //captRefrnc.open(camNum);142 143 if ( !captRefrnc.isOpened())144 {145 return -1;146 }147 148 // Windows149 const char* WIN_RESULT = "Result";150 namedWindow(WIN_RESULT, CV_WINDOW_AUTOSIZE);151 //namedWindow(WIN_RESULT, 0);152 // namedWindow("Result",0);153 // 鼠标响应函数154 //setMouseCallback(WIN_RESULT, onMouse, 0);155 setMouseCallback("Result", onMouse, 0);156 157 Mat frame; //视频的每一帧图像158 159 bool paused = false;160 PARTICLE * pParticles = particles;//particles为可装PARTICLE_NUM个PARTICLE结构体的数组,所以pParticles为指向其数组的指针161 162 while(true) //Show the image captured in the window and repeat163 {164 if(!paused)165 {166 captRefrnc >> frame;167 if(frame.empty())168 break;169 }170 171 frame.copyTo(img); // 接下来的操作都是对src的172 173 174 // 选择目标后进行跟踪175 if (bTracking == true)//鼠标操作选完后176 {177 if(!paused)178 { 179 nFrameNum++;//帧数计数器180 cvtColor(img, hsv, CV_BGR2HSV);181 Mat roiImage(hsv, selection); // 目标区域,这个构造函数第二个参数表示截取selection部分182 183 if (nFrameNum == 1) //选择目标后的第一帧需要初始化184 {185 // step 1: 提取目标区域特征,难道其目标特征就是其色调的直方图分布?186 calcHist(&roiImage, 1, channels, Mat(), roiHist, 3, histSize, ranges);187 normalize(roiHist, roiHist); // 归一化L2188 189 // step 2: 初始化particle190 pParticles = particles;191 for (int i=0; i<PARTICLE_NUM; i++)192 {193 pParticles->x = selection.x + 0.5 * selection.width;194 pParticles->y = selection.y + 0.5 * selection.height;195 pParticles->xPre = pParticles->x;196 pParticles->yPre = pParticles->y;197 pParticles->xOri = pParticles->x;198 pParticles->yOri = pParticles->y;199 pParticles->rect = selection;200 pParticles->scale = 1.0;201 pParticles->scalePre = 1.0;202 pParticles->hist = roiHist;203 pParticles->weight = 0;204 pParticles++;205 }206 }207 else //不是第一帧208 { 209 pParticles = particles; 210 RNG rng;//随机数序列产生器211 for (int i=0; i<PARTICLE_NUM; i++)212 {213 // step 3: 求particle的transition,粒子结构中的参数全部更新过214 double x, y, s;215 216 pParticles->xPre = pParticles->x;217 pParticles->yPre = pParticles->y;218 pParticles->scalePre = pParticles->scale;219 220 x = A1 * (pParticles->x - pParticles->xOri) + A2 * (pParticles->xPre - pParticles->xOri) +221 B0 * rng.gaussian(SIGMA_X) + pParticles->xOri;//以当前点为中心产生高斯分布的粒子222 pParticles->x = std::max(0.0, std::min(x, img.cols-1.0));//其实就是x,只是考虑了边界在内而已223 224 225 y = A1 * (pParticles->y - pParticles->yOri) + A2 * (pParticles->yPre - pParticles->yOri) +226 B0 * rng.gaussian(SIGMA_Y) + pParticles->yOri;227 pParticles->y = std::max(0.0, std::min(y, img.rows-1.0));228 229 s = A1 * (pParticles->scale - 1.0) + A2 * (pParticles->scalePre - 1.0) +230 B0 * rng.gaussian(SIGMA_SCALE) + 1.0;231 pParticles->scale = std::max(0.1, std::min(s, 3.0));232 // rect参数有待考证233 pParticles->rect.x = std::max(0, std::min(cvRound(pParticles->x - 0.5 * pParticles->rect.width * pParticles->scale), img.cols-1)); // 0 <= x <= img.rows-1234 pParticles->rect.y = std::max(0, std::min(cvRound(pParticles->y - 0.5 * pParticles->rect.height * pParticles->scale), img.rows-1)); // 0 <= y <= img.cols-1235 pParticles->rect.width = std::min(cvRound(pParticles->rect.width * pParticles->scale), img.cols - pParticles->rect.x);236 pParticles->rect.height = std::min(cvRound(pParticles->rect.height * pParticles->scale), img.rows - pParticles->rect.y);237 // Ori参数不改变238 239 // step 4: 求particle区域的特征直方图240 Mat imgParticle(img, pParticles->rect);241 calcHist(&imgParticle, 1, channels, Mat(), pParticles->hist, 3, histSize, ranges);242 normalize(pParticles->hist, pParticles->hist); // 归一化L2243 244 // step 5: 特征的比对,更新particle权重245 //compareHist()函数返回2个直方图之间的相似度,因为参数为CV_COMP_INTERSECT,所以返回的是最小直方图值之和246 pParticles->weight = compareHist(roiHist, pParticles->hist, CV_COMP_INTERSECT);//其差值直接作为其权值247 248 pParticles++; 249 }250 251 // step 6: 归一化粒子权重252 double sum = 0.0;253 int i;254 255 pParticles = particles;256 for(i=0; i<PARTICLE_NUM; i++)257 {258 sum += pParticles->weight;259 pParticles++;260 }261 pParticles = particles;262 for(i=0; i<PARTICLE_NUM; i++)263 {264 pParticles->weight /= sum;265 pParticles++;266 }267 268 // step 7: resample根据粒子的权重的后验概率分布重新采样269 pParticles = particles;270 // PARTICLE* newParticles = new PARTICLE[sizeof(PARTICLE) * PARTICLE_NUM];271 PARTICLE newParticles[PARTICLE_NUM];272 int np, k = 0;273 274 //qsort()函数为对数组进行快速排序,其中第4个参数表示的是排序是升序还是降序275 qsort(pParticles, PARTICLE_NUM, sizeof(PARTICLE), &particle_cmp);//这里采用的是降序排列276 for(int i=0; i<PARTICLE_NUM; i++)277 {278 np = cvRound(particles[i].weight * PARTICLE_NUM);//权值高的优先重采样279 for(int j=0; j<np; j++)280 {281 newParticles[k++] = particles[i];282 if(k == PARTICLE_NUM)//重采样后达到了个数要求则直接跳出283 goto EXITOUT;284 }285 }286 while(k < PARTICLE_NUM)287 {288 newParticles[k++] = particles[0];//个数不够时,将权值最高的粒子重复给289 }290 291 EXITOUT:292 for (int i=0; i<PARTICLE_NUM; i++)293 {294 particles[i] = newParticles[i];295 }296 297 }// end else298 299 qsort(pParticles, PARTICLE_NUM, sizeof(PARTICLE), &particle_cmp);300 301 // step 8: 计算粒子的期望,作为跟踪结果302 Rect_<double> rectTrackingTemp(0.0, 0.0, 0.0, 0.0);303 pParticles = particles;304 for (int i=0; i<PARTICLE_NUM; i++)305 {306 rectTrackingTemp.x += pParticles->rect.x * pParticles->weight;//坐标加上权重的偏移值307 rectTrackingTemp.y += pParticles->rect.y * pParticles->weight;308 rectTrackingTemp.width += pParticles->rect.width * pParticles->weight;//宽度也要加上权值的偏移值309 rectTrackingTemp.height += pParticles->rect.height * pParticles->weight;310 pParticles++;311 }312 Rect rectTracking(rectTrackingTemp); // 跟踪结果313 314 // 显示各粒子的运动315 for (int i=0; i<PARTICLE_NUM; i++)316 {317 rectangle(img, particles[i].rect, Scalar(255,0,0));318 }319 // 显示跟踪结果320 rectangle(img, rectTracking, Scalar(0,0,255), 3);321 322 }323 }// end Tracking324 325 // imshow(WIN_SRC, frame);326 imshow(WIN_RESULT, img);327 328 c = (char)waitKey(delay);329 if( c == 27 )330 break;331 switch(c)332 {333 case 'p'://暂停键334 paused = !paused;335 break;336 default:337 ;338 }339 }// end while340 }
但是用他的代码在进行鼠标选定后就出现如下错误。
我的工程环境:opencv2.2+vs2010
经过单步调试跟踪后发现,错误的那一行为:
pParticles->weight = compareHist(roiHist, pParticles->hist, CV_COMP_INTERSECT);
去掉该行程序可以正常运行,但是完成不了跟踪功能,其目标跟踪框不会移动,只会慢慢收敛到一个点,因为粒子的权重此时没有更新。
查找资料了很久,函数compareHist()的用法并没有错,也不知道是哪里错了。先工作暂时弄到这里,只要对粒子滤波有个感性认识即可。等过段时间再来真正学粒子滤波算法时完成该演示。
修改时间:2012.05.08:
过了这么久,重新学习粒子滤波时,想解决上面那个遗留下来的问题。事实证明C/C++内存搞死人,上面那个问题debug了2天也不懂哪里出错了。自己又用了不少时间理解程序后敲了一遍代码。那个问题暂时解决了,但是跟踪起来根本无效过。修改后的代码如下:
1 // particle_tracking.cpp : 定义控制台应用程序的入口点。 2 // 3 4 #include "stdafx.h" 5 #include <opencv2/core/core.hpp> 6 #include "opencv2/imgproc/imgproc.hpp" 7 #include <opencv2/highgui/highgui.hpp> 8 #include <stdio.h> 9 #include <iostream> 10 11 using namespace cv; 12 using namespace std; 13 14 Rect select; 15 bool select_flag=false; 16 bool tracking=false;//跟踪标志位 17 bool select_show=false; 18 Point origin; 19 Mat frame,hsv; 20 int after_select_frames=0;//选择矩形区域完后的帧计数 21 22 /****rgb空间用到的变量****/ 23 //int hist_size[]={16,16,16};//rgb空间各维度的bin个数 24 //float rrange[]={0,255.0}; 25 //float grange[]={0,255.0}; 26 //float brange[]={0,255.0}; 27 //const float *ranges[] ={rrange,grange,brange};//range相当于一个二维数组指针 28 29 /****hsv空间用到的变量****/ 30 int hist_size[]={16,16,16}; 31 float hrange[]={0,180.0}; 32 float srange[]={0,256.0}; 33 float vrange[]={0,256.0}; 34 const float *ranges[]={hrange,srange,vrange}; 35 36 int channels[]={0,1,2}; 37 38 /****有关粒子窗口变化用到的相关变量****/ 39 int A1=2; 40 int A2=-1; 41 int B0=1; 42 double sigmax=1.0; 43 double sigmay=0.5; 44 double sigmas=0.001; 45 46 /****定义使用粒子数目宏****/ 47 #define PARTICLE_NUMBER 50 //如果这个数设定太大,比如100,则在运行时将会出现错误 48 49 /****定义粒子结构体****/ 50 typedef struct particle 51 { 52 int orix,oriy;//原始粒子坐标 53 int x,y;//当前粒子的坐标 54 double scale;//当前粒子窗口的尺寸 55 int prex,prey;//上一帧粒子的坐标 56 double prescale;//上一帧粒子窗口的尺寸 57 Rect rect;//当前粒子矩形窗口 58 Mat hist;//当前粒子窗口直方图特征 59 double weight;//当前粒子权值 60 }PARTICLE; 61 62 PARTICLE particles[PARTICLE_NUMBER]; 63 64 /************************************************************************************************************************/ 65 /**** 如果采用这个onMouse()函数的话,则可以画出鼠标拖动矩形框的4种情形 ****/ 66 /************************************************************************************************************************/ 67 void onMouse(int event,int x,int y,int,void*) 68 { 69 //Point origin;//不能在这个地方进行定义,因为这是基于消息响应的函数,执行完后origin就释放了,所以达不到效果。 70 if(select_flag) 71 { 72 select.x=MIN(origin.x,x);//不一定要等鼠标弹起才计算矩形框,而应该在鼠标按下开始到弹起这段时间实时计算所选矩形框 73 select.y=MIN(origin.y,y); 74 select.width=abs(x-origin.x);//算矩形宽度和高度 75 select.height=abs(y-origin.y); 76 select&=Rect(0,0,frame.cols,frame.rows);//保证所选矩形框在视频显示区域之内 77 78 // rectangle(frame,select,Scalar(0,0,255),3,8,0);//显示手动选择的矩形框 79 } 80 if(event==CV_EVENT_LBUTTONDOWN) 81 { 82 select_flag=true;//鼠标按下的标志赋真值 83 tracking=false; 84 select_show=true; 85 after_select_frames=0;//还没开始选择,或者重新开始选择,计数为0 86 origin=Point(x,y);//保存下来单击是捕捉到的点 87 select=Rect(x,y,0,0);//这里一定要初始化,因为在opencv中Rect矩形框类内的点是包含左上角那个点的,但是不含右下角那个点。 88 } 89 else if(event==CV_EVENT_LBUTTONUP) 90 { 91 select_flag=false; 92 tracking=true; 93 select_show=false; 94 after_select_frames=1;//选择完后的那一帧当做第1帧 95 } 96 } 97 98 /****粒子权值降序排列函数****/ 99 int particle_decrease(const void *p1,const void *p2) 100 { 101 PARTICLE* _p1=(PARTICLE*)p1; 102 PARTICLE* _p2=(PARTICLE*)p2; 103 if(_p1->weight<_p2->weight) 104 return 1; 105 else if(_p1->weight>_p2->weight) 106 return -1; 107 return 0;//相等的情况下返回0 108 } 109 110 int main(int argc, unsigned char* argv[]) 111 { 112 char c; 113 Mat target_img,track_img; 114 Mat target_hist,track_hist; 115 PARTICLE *pParticle; 116 117 /***打开摄像头****/ 118 VideoCapture cam(0); 119 if (!cam.isOpened()) 120 return -1; 121 122 /****建立窗口****/ 123 namedWindow("camera",1);//显示视频原图像的窗口 124 125 /****捕捉鼠标****/ 126 setMouseCallback("camera",onMouse,0); 127 128 while(1) 129 { 130 /****读取一帧图像****/ 131 cam>>frame; 132 if(frame.empty()) 133 return -1; 134 135 /****将rgb空间转换为hsv空间****/ 136 cvtColor(frame,hsv,CV_BGR2HSV); 137 138 if(tracking) 139 { 140 141 if(1==after_select_frames)//选择完目标区域后 142 { 143 /****计算目标模板的直方图特征****/ 144 target_img=Mat(hsv,select);//在此之前先定义好target_img,然后这样赋值也行,要学会Mat的这个操作 145 calcHist(&target_img,1,channels,Mat(),target_hist,3,hist_size,ranges); 146 normalize(target_hist,target_hist); 147 148 /****初始化目标粒子****/ 149 pParticle=particles;//指针初始化指向particles数组 150 for(int x=0;x<PARTICLE_NUMBER;x++) 151 { 152 pParticle->x=cvRound(select.x+0.5*select.width);//选定目标矩形框中心为初始粒子窗口中心 153 pParticle->y=cvRound(select.y+0.5*select.height); 154 pParticle->orix=pParticle->x;//粒子的原始坐标为选定矩形框(即目标)的中心 155 pParticle->oriy=pParticle->y; 156 pParticle->prex=pParticle->x;//更新上一次的粒子位置 157 pParticle->prey=pParticle->y; 158 pParticle->rect=select; 159 pParticle->prescale=1; 160 pParticle->scale=1; 161 pParticle->hist=target_hist; 162 pParticle->weight=0; 163 pParticle++; 164 } 165 } 166 else if(2==after_select_frames)//从第二帧开始就可以开始跟踪了 167 { 168 double sum=0.0; 169 pParticle=particles; 170 RNG rng;//随机数产生器 171 172 /****更新粒子结构体的大部分参数****/ 173 for(int i=0;i<PARTICLE_NUMBER;i++) 174 { 175 int x,y; 176 double s; 177 178 /****更新粒子的矩形区域即粒子中心****/ 179 pParticle->prex=pParticle->x; 180 pParticle->prey=pParticle->y; 181 pParticle->prescale=pParticle->scale; 182 183 x=cvRound(A1*(pParticle->x-pParticle->orix)+A2*(pParticle->prex-pParticle->orix)+ 184 B0*rng.gaussian(sigmax)+pParticle->orix); 185 pParticle->x=max(0,min(x,frame.cols-1)); 186 187 y=cvRound(A1*(pParticle->y-pParticle->oriy)+A2*(pParticle->prey-pParticle->oriy)+ 188 B0*rng.gaussian(sigmay)+pParticle->oriy); 189 pParticle->y=max(0,min(y,frame.rows-1)); 190 191 s=A1*(pParticle->scale-1)+A2*(pParticle->prescale-1)+B0*(rng.gaussian(sigmas))+1.0; 192 pParticle->scale=max(1.0,min(s,3.0)); 193 194 //注意在c语言中,x-1.0,如果x是int型,则这句语法有错误,但如果前面加了cvRound(x-0.5)则是正确的 195 pParticle->rect.x=max(0,min(cvRound(pParticle->x-0.5*pParticle->scale*pParticle->rect.width),frame.cols)); 196 pParticle->rect.y=max(0,min(cvRound(pParticle->y-0.5*pParticle->scale*pParticle->rect.height),frame.rows)); 197 pParticle->rect.width=min(cvRound(pParticle->scale*pParticle->rect.width),frame.cols-pParticle->rect.x); 198 pParticle->rect.height=min(cvRound(pParticle->scale*pParticle->rect.height),frame.rows-pParticle->rect.y); 199 200 /****计算粒子区域的新的直方图特征****/ 201 track_img=Mat(hsv,pParticle->rect); 202 calcHist(&track_img,1,channels,Mat(),track_hist,3,hist_size,ranges); 203 normalize(track_hist,track_hist); 204 205 /****更新粒子的权值****/ 206 // pParticle->weight=compareHist(target_hist,track_hist,CV_COMP_INTERSECT); 207 pParticle->weight=compareHist(target_hist,track_hist,CV_COMP_BHATTACHARYYA);//采用巴氏系数计算相似度 208 209 /****累加粒子权值****/ 210 sum+=pParticle->weight; 211 pParticle++; 212 } 213 214 /****归一化粒子权重****/ 215 pParticle=particles; 216 for(int i=0;i<PARTICLE_NUMBER;i++) 217 { 218 pParticle->weight/=sum; 219 pParticle++; 220 } 221 222 /****根据粒子的权值降序排列****/ 223 pParticle=particles; 224 qsort(pParticle,PARTICLE_NUMBER,sizeof(PARTICLE),&particle_decrease); 225 226 /****根据粒子权重重采样粒子****/ 227 PARTICLE newParticle[PARTICLE_NUMBER]; 228 int np=0,k=0; 229 for(int i=0;i<PARTICLE_NUMBER;i++) 230 { 231 np=cvRound(pParticle->weight*PARTICLE_NUMBER); 232 for(int j=0;j<np;j++) 233 { 234 newParticle[k++]=particles[i]; 235 if(k==PARTICLE_NUMBER) 236 goto EXITOUT; 237 } 238 } 239 while(k<PARTICLE_NUMBER) 240 newParticle[k++]=particles[0]; 241 EXITOUT: 242 for(int i=0;i<PARTICLE_NUMBER;i++) 243 particles[i]=newParticle[i]; 244 }//end else 245 246 qsort(pParticle,PARTICLE_NUMBER,sizeof(PARTICLE),&particle_decrease); 247 248 /****计算粒子期望,做为跟踪结果****/ 249 Rect_<double> rectTrackingTemp(0.0,0.0,0.0,0.0); 250 pParticle=particles; 251 for(int i=0;i<PARTICLE_NUMBER;i++) 252 { 253 rectTrackingTemp.x+=pParticle->rect.x*pParticle->weight; 254 rectTrackingTemp.y+=pParticle->rect.y*pParticle->weight; 255 rectTrackingTemp.width+=pParticle->rect.width*pParticle->weight; 256 rectTrackingTemp.height+=pParticle->rect.height*pParticle->weight; 257 pParticle++; 258 } 259 260 Rect tracking_rect(rectTrackingTemp); 261 262 pParticle=particles; 263 264 /****显示各粒子运动结果****/ 265 for(int m=0;m<PARTICLE_NUMBER;m++) 266 { 267 rectangle(frame,pParticle->rect,Scalar(255,0,0),1,8,0); 268 pParticle++; 269 } 270 271 /****显示跟踪结果****/ 272 rectangle(frame,tracking_rect,Scalar(0,0,255),3,8,0); 273 274 after_select_frames++;//总循环每循环一次,计数加1 275 if(after_select_frames>2)//防止跟踪太长,after_select_frames计数溢出 276 after_select_frames=2; 277 } 278 279 if(select_show) 280 rectangle(frame,select,Scalar(0,0,255),3,8,0);//显示手动选择的矩形框 281 //显示视频图片到窗口 282 imshow("camera",frame); 283 284 // select.zeros(); 285 //键盘响应 286 c=(char)waitKey(20); 287 if(27==c)//ESC键 288 return -1; 289 } 290 291 return 0; 292 }
目标跟踪学习笔记_2(particle filter初探1)相关推荐
- Jarry的目标跟踪学习笔记一
Jarry的目标跟踪学习笔记一 目标跟踪是计算机视觉中的一个重要方向,已经由来已久,并且有着广泛的应用,如:视频监控,人机交互, 无人驾驶等.在我的想象中,自己研究的内容就是,将来钢铁侠头盔里追踪敌人 ...
- 相关滤波目标跟踪学习笔记(三)——KCF算法公式理解
KCF算法特点: 1.通过循环移位产生了大量的虚拟样本: 2.利用循环矩阵可以在傅里叶域对角化的性质,大大减少了运算量,提高了运算速度: 3.核函数的运用,提高了分类器的性能: 4.采用HOG特征,相 ...
- OpenCV 3 Tracking API目标跟踪学习笔记——定义、物体跟踪常用算法、demo
今天开始接触目标跟踪 本文翻译自https://www.learnopencv.com/object-tracking-using-opencv-cpp-python/#opencv-tracking ...
- 目标跟踪学习笔记_1(opencv中meanshift和camshift例子的应用)
在这一节中,主要讲目标跟踪的一个重要的算法Camshift,因为它是连续自使用的meanShift,所以这2个函数opencv中都有,且都很重要.为了让大家先达到一个感性认识.这节主要是看懂和运行op ...
- vot 单目标跟踪学习笔记
目录 MixFormer TCTrack 视频测试代码: 图片测试代码: 摄像头测试代码: MixFormer
- opencv动态目标跟踪学习总结
用opencv实现对视频中动态目标的追踪 第一步,是要建立一个编程环境,然后加载opencv的库路径等等.具体步骤在 http://www.opencv.org.cn/ 的"安装" ...
- 单目标跟踪——个人笔记
单目标跟踪--个人笔记 以<Handcrafted and Deep Trackers: A Review of Recent ObjectTracking Approaches>为主线看 ...
- 尚学堂JAVA基础学习笔记_2/2
尚学堂JAVA基础学习笔记_2/2 文章目录 尚学堂JAVA基础学习笔记_2/2 写在前面 第10章 IO技术 1. IO入门 2. IO的API 3. 装饰流 4. IO实战 5. CommonsI ...
- 《南溪的目标检测学习笔记》——模型预处理的学习笔记
1 介绍 在目标检测任务中,模型预处理分为两个步骤: 图像预处理:基于图像处理算法 数值预处理:基于机器学习理论 关于图像预处理,请参考<南溪的目标检测学习笔记>--图像预处理的学习笔记 ...
最新文章
- Ext JS图书风暴来袭!
- [Asp.net]绝对路径和相对路径
- SpringMVC、Spring和Struts的区别
- java和python哪个好就业2020-java和python哪个未来发展比较好?
- 【转】使用Windows Backup备份Exchange 2007 SP2和Exchange 2010
- 算法设计与分析——递归与分治策略——快速排序
- PowerMock介绍
- oracle ogg 12安装,Oracle GoldenGate Studio 12.2.1.3安装
- MVC中如何使用语音识别功能实现输入
- 【BZOJ3144】[Hnoi2013]切糕 最小割
- 摩托罗拉发布RhoElements HTML5框架
- python生成可执行exe控制Microsip自动填写号码并拨打
- android腾讯微博客户端开发,基于android系统的腾讯微博客户端的开发
- 微信小程序开发(4)--发布评论
- 客户案例 | 初窥元宇宙,Oasis让更多人找到第二人生
- Python 数据处理工具 Pandas(上)
- hdu2191 买大米 多重背包 模板题
- 计算机网络实验四:配置网络路由
- MySQL 分库拆表方案
- 中国新经济指数(2017-2022)
热门文章
- linux oracle查看服务,技术|如何查看 Linux 中所有正在运行的服务
- python动态变量名以及调用_Python 动态变量名与调用介绍
- pythonweb项目源码下载_最新Python WEB开发在线教育项目之谷粒教育 软件源码齐全...
- python可以用来写导航吗_在python中使用selenium进行导航
- 怎么把3d风格的图变成2d_单图像三维重建、2D到3D风格迁移和3D DeepDream
- php 二维数组去除一项,PHP二维数组提取函数----把不需要的数据剔除
- k均值的损失函数_机器学习:手撕 cross-entropy 损失函数
- 系统学习NLP(八)--中文分词整理
- mysql8.0数据回滚_大企业数据库服务首选!AliSQL这几大企业级功能你不可不知
- ofdma技术_数字化领航 | Wi-Fi 6 关键技术剖析