OpenCv_背景差分结合LK金字塔进行运动物体跟踪
2015-03-09 21:31
489 查看
【原创】Liu_LongPo 转载请注明出处
【CSDN】http://blog.csdn.net/llp1992
前面我们看到通过光流法进行运动物体跟踪的实际例子,其实现的基本原理就是:
一、获取前一帧,然后转换为灰度图,利用cvGoodFeaturesToTrack 函数寻找这一帧视频流的强角点
二、获取当前帧,然后转换为灰度图,利用LK金字塔算法 cvCalcOpticalFlowPyrLK 函数结合第一帧寻找到的角点A,寻找当前帧的角点B
三、画出角点和运动轨迹
背景差分法进行运动物体检测的基本原理就是:
一、取前一帧的视频流作为运动背景
二、将当前帧的视频流中的每个像素与前一帧的每个像素做差,得出每个像素点前后两帧的值的差
三、判断每个像素点的前后两帧的差值是否大于某个阈值,是则判断为运动
关于 cvGoodFeaturesToTrack 的原理,不清楚的可以参考博客:
OpenCv目标跟踪_cvGoodFeaturesToTrack()寻找角点
其基本原理也就是,强角点所在的位置在图像中一般在两个正交方向上都有明显的倒数,该点在图像中我们认为是独一无二的。
而差分背景法的基本原理,我们从另一个角度上来看,其实也是寻找角点的过程,它在前后两帧图像的每个像素作对比的过程中,过滤掉了像素值变化小的点,变化大的点被认为是运动的,其实这些运动的点从某个意义上也就是我们想要找的角点。
接下来我们来实现这样的思路:
先运用差分背景法,找出前一帧中我们认为是运动的角点,将这些角点保存起来,再结合这些找到的角点运用LK金字塔算法计算出光流,从而实现基于背景差分法的运动物体检测跟踪。
看代码:
效果如下:
【CSDN】http://blog.csdn.net/llp1992
前面我们看到通过光流法进行运动物体跟踪的实际例子,其实现的基本原理就是:
一、获取前一帧,然后转换为灰度图,利用cvGoodFeaturesToTrack 函数寻找这一帧视频流的强角点
二、获取当前帧,然后转换为灰度图,利用LK金字塔算法 cvCalcOpticalFlowPyrLK 函数结合第一帧寻找到的角点A,寻找当前帧的角点B
三、画出角点和运动轨迹
背景差分法进行运动物体检测的基本原理就是:
一、取前一帧的视频流作为运动背景
二、将当前帧的视频流中的每个像素与前一帧的每个像素做差,得出每个像素点前后两帧的值的差
三、判断每个像素点的前后两帧的差值是否大于某个阈值,是则判断为运动
关于 cvGoodFeaturesToTrack 的原理,不清楚的可以参考博客:
OpenCv目标跟踪_cvGoodFeaturesToTrack()寻找角点
其基本原理也就是,强角点所在的位置在图像中一般在两个正交方向上都有明显的倒数,该点在图像中我们认为是独一无二的。
而差分背景法的基本原理,我们从另一个角度上来看,其实也是寻找角点的过程,它在前后两帧图像的每个像素作对比的过程中,过滤掉了像素值变化小的点,变化大的点被认为是运动的,其实这些运动的点从某个意义上也就是我们想要找的角点。
接下来我们来实现这样的思路:
先运用差分背景法,找出前一帧中我们认为是运动的角点,将这些角点保存起来,再结合这些找到的角点运用LK金字塔算法计算出光流,从而实现基于背景差分法的运动物体检测跟踪。
看代码:
/* * Description : Tracking Moving object based on background subtraction * Author : Liulongpo * Date : 2015年3月9日21:24:56 * */ #include <cv.h> #include <highgui.h> #include <iostream> using namespace std; bool acceptTrackedPoint(int i); int const MAX_CORNERS = 200; CvPoint2D32f * cornerA; CvPoint2D32f * cornerB; int main (int argc, char **argv) { CvCapture* capture = 0; //capture = cvCaptureFromCAM( CV_CAP_ANY ); //get frame capture = cvCaptureFromFile( "F://BaiduYunDownload//bike.avi" ); IplImage *pre_frame; //the previous frame IplImage *cur_frame; //the current frame IplImage *dst_img; //the result IplImage *cur_img; IplImage *pre_img; cornerA = new CvPoint2D32f[ MAX_CORNERS]; cornerB = new CvPoint2D32f[ MAX_CORNERS]; char *features_found = new char[MAX_CORNERS]; float *features_error = new float[MAX_CORNERS]; CvTermCriteria criteria; criteria = cvTermCriteria (CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 64, 0.01); // 获取前一帧 pre_frame = cvQueryFrame(capture); while(1) { // 获取当前帧 cur_frame = cvQueryFrame(capture); if (!cur_frame) { cout<<"No frame is captured ! \n"; break; } int i,j; int point_number = 0; int rows, cols; int countn = MAX_CORNERS; CvSize img_sz = cvGetSize(cur_frame); pre_img = cvCreateImage(img_sz, IPL_DEPTH_8U, 1); cvCvtColor(pre_frame,pre_img, CV_RGB2GRAY); cur_img = cvCreateImage(img_sz, IPL_DEPTH_8U, 1); cvCvtColor(cur_frame,cur_img , CV_RGB2GRAY); dst_img = (IplImage *)cvClone(cur_frame); IplImage *move_img = cvCreateImage(img_sz, IPL_DEPTH_8U, 1); cvZero(move_img); //cvAbsDiff(src_img1, src_img2,move_img); cols = cur_frame->width; rows = cur_frame->height; for (i = 0; i <cols; i++) { for (j = 0; j<rows; j++) { // 如果前后两帧的同一个像素点的值之差大于阈值,则认为该像素运动了 double a = abs(cvGet2D(pre_img, j, i).val[0]-cvGet2D(cur_img, j, i).val[0]); CvScalar b = cvScalar(a, 0, 0,0); // 设置灰度图像 cvSet2D(move_img, j, i,b); if (a>40) { if (point_number<MAX_CORNERS-1) { cornerA[++point_number].x = i; cornerA[point_number].y = j; } } } } cvNamedWindow("moving object", 0); cvShowImage("moving object", move_img); CvSize Pyrsize = cvSize(pre_img->width +8, pre_img->height/3); IplImage * pyrA = cvCreateImage(Pyrsize, IPL_DEPTH_32F, 1); IplImage * pyrB = cvCreateImage(Pyrsize, IPL_DEPTH_32F, 1); cvCalcOpticalFlowPyrLK(pre_img,cur_img,pyrA,pyrB,cornerA,cornerB,countn, cvSize(10, 10),3,features_found,features_error,criteria,0); for (i = 0; i < countn; i++) { if (features_found[i] && acceptTrackedPoint(i)) { cvLine (dst_img, cvPointFrom32f (cornerA[i]), cvPointFrom32f (cornerB[i]), CV_RGB (0, 255, 0), 1, CV_AA, 0); //cvCircle(dst_img,cvPointFrom32f (cornerB[i]), 3, CV_RGB (255, 0, 0), -1); } // 交换角点数据 cornerA[i] = cornerB[i]; } // 当前帧交换到前一帧 pre_frame = (IplImage *)cvClone(cur_frame); cvNamedWindow ("ImagePyrLK", 0); cvShowImage ("ImagePyrLK", dst_img); cvWaitKey (1); cvReleaseImage (&dst_img); cvReleaseImage(&pyrA); cvReleaseImage(&pyrB); cvReleaseImage(&move_img); } cvDestroyWindow("moving object"); cvDestroyWindow ("ImagePyrLK"); cvReleaseImage (&pre_frame); cvReleaseImage (&cur_frame); cvReleaseImage (&pre_img); cvReleaseImage (&cur_img); return 0; } // 通过设定之前点与当前点的距离来判断特征点是否可以获取 bool acceptTrackedPoint(int i) { //cout<<abs(cornerA[i].x - cornerB[i].x)<< " "; return ((abs(cornerA[i].x - cornerB[i].x) + abs(cornerA[i].y - cornerB[i].y)) > 3); }
效果如下:
相关文章推荐
- opencv for python(8) 利用颜色空间转换进行物体跟踪
- iOS开发之opencv学习笔记二:使用CascadeClassifier进行对特定物体的跟踪
- OpenCV学习笔记(十六)——CamShift研究 OpenCV学习笔记(十七)——运动分析和物体跟踪Video OpenCV学习笔记(十八)——图像的各种变换(cvtColor*+)imgproc
- OpenCV:运动物体跟踪处理流程
- 初学图像处理+opencv----跟踪视频中运动物体
- python3-opencv库(3)--图片颜色空间转换,利用HSV进行物体跟踪,图像通道分离与合并
- OpenCV学习笔记(十七)——运动分析和物体跟踪Video
- OpenCV学习笔记之--运动物体跟踪的camshift算法
- opencv之运动模板跟踪
- 第十章 跟踪与运动 opencv cvFindCornerSubPi
- 运动分析和物体跟踪Video
- OpenCV结合socket进行实时视频传输(TCP协议)
- OpenCV学习——物体跟踪的粒子滤波算法实现之粒子集重新采样
- OpenCV学习笔记(二十八)——光流法对运动目标跟踪Video
- OpenCV:利用Camshift算法进行彩色目标的跟踪
- IOS使用OPENCV实现物体跟踪
- OpenCV —— 跟踪与运动
- OpenCV学习——LK光流算法动作跟踪程序
- 运动物体跟踪的camshift算法
- 视频跟踪分割运动中的物体