24,854
社区成员
发帖
与我相关
我的任务
分享
#include <cv.h>
#include <highgui.h>
#include <iostream>
using namespace std;
int const MAX_CORNERS = 1000; //设置最大角点个数
int main(int argc, char **argv)
{
CvCapture* capture = 0;//capture 获取摄像头或视频中的某一帧 此为初始化
//capture = cvCaptureFromCAM(CV_CAP_ANY); //get frame
capture = cvCaptureFromAVI("video1.avi");
IplImage *src_img1; //the previous frame (gray)前一帧
IplImage *src_img2; //the current frame(gray)当前帧
IplImage *dst_img; //the result 结果
IplImage *cur_img; //
IplImage *pre_img;
CvPoint2D32f * move_old_point = new CvPoint2D32f[MAX_CORNERS]; // cvpoint基本数据类型之一,表示一个坐标为整数的二维点 CvPoint2D32f表示cvPoint2D32f(float型别row,float型别colunm)
CvPoint2D32f * move_new_point = 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);
while (1)
{
int i, j;
int dx, dy;
int p = 0;
int rows, cols;
int countn = MAX_CORNERS;
pre_img = cvQueryFrame(capture);//从摄像头或者文件中抓取并返回一帧
CvSize img_sz = cvGetSize(pre_img);
src_img1 = cvCreateImage(img_sz, IPL_DEPTH_8U, 1);//是指图像数据是8位无符号整型,也就是用2的8次方来表示一个像素,就是传说中的256色
cvCvtColor(pre_img, src_img1, CV_RGB2GRAY);//cvCvtColor颜色空间转换函数
cur_img = cvQueryFrame(capture);
src_img2 = cvCreateImage(img_sz, IPL_DEPTH_8U, 1);
cvCvtColor(cur_img, src_img2, CV_RGB2GRAY);
dst_img = (IplImage *)cvClone(cur_img);//克隆一个对象
IplImage *move_img = cvCreateImage(img_sz, IPL_DEPTH_8U, 1);
cvZero(move_img);//这个函数会将数组中的所有通道的元素的值都设置为0.
//cvAbsDiff(src_img1, src_img2,move_img); OpenCV 中计算两个数组差的绝对值的函数
cols = src_img1->width;
rows = src_img1->height;
for (i = 0; i <cols; i++)
{
for (j = 0; j<rows; j++)
{
double a = abs(cvGet2D(src_img1, j, i).val[0] - cvGet2D(src_img2, j, i).val[0]);//abs()仅对整型求绝对值 cvGet2D获取src_img中像素值
CvScalar b = cvScalar(a, 0, 0, 0);//是一个可以用来存放4个double数值的数组(O'Reilly的书上写的是4个整型成员);一般用来存放像素值(不一定是灰度值哦)的,最多可以存放4个通道的。
cvSet2D(move_img, j, i, b);//用于对2维图像进行像素值设置
if (a>40)
{
if (p<MAX_CORNERS - 1)
{
int d = ++p;
move_old_point[d].x = i;
move_old_point[d].y = j;
}
}
}
}
cvNamedWindow("moving object", 1);
cvShowImage("moving object", move_img);
CvSize Pyrsize = cvSize(src_img1->width + 8, src_img1->height / 3); //表示矩阵框大小,以像素为精度。与CvPoint结构类似,但数据成员是integer类型的width和height。
IplImage * pyrA = cvCreateImage(Pyrsize, IPL_DEPTH_32F, 1); //pyrA是需要寻找的点,不是没有初始化的
IplImage * pyrB = cvCreateImage(Pyrsize, IPL_DEPTH_32F, 1);
cvCalcOpticalFlowPyrLK(src_img1,src_img2,pyrA, pyrB, move_old_point, move_new_point, countn, cvSize(10, 10), 3, features_found,features_error,criteria,0);
//计算一个稀疏特征集的光流,使用金字塔中的迭代 Lucas-Kanade 方法
for (i = 0; i < countn; i++)
{
int x1 = (int)move_new_point[i].x;
int x2 = (int)move_old_point[i].x;
int y1 = (int)move_new_point[i].y;
int y2 = (int)move_old_point[i].y;
dx = (int)abs(x1 - x2);
dy = (int)abs(y1 - y2);
if (dx >= 5 && dy >= 5)
{
cvLine(dst_img, cvPoint(x2, y2), cvPoint(x2 + 5, y2 + 5), CV_RGB(255, 0, 0), 1, CV_AA, 0);//绘制连接两个点的线段
}
}
cvNamedWindow("ImagePyrLK", 1);
cvShowImage("ImagePyrLK", dst_img);
cvWaitKey(1);
cvReleaseImage(&dst_img);
cvReleaseImage(&pyrA);
cvReleaseImage(&pyrB);
cvReleaseImage(&move_img);
}
cvDestroyWindow("moving object");
cvDestroyWindow("ImagePyrLK");
cvReleaseImage(&src_img1);
cvReleaseImage(&src_img2);
cvReleaseImage(&pre_img);
cvReleaseImage(&cur_img);
return 0;
}