当前位置:首页 > 代码 > 正文

opencv光流法代码(opencv 光流)

admin 发布:2022-12-19 22:27 131


本篇文章给大家谈谈opencv光流法代码,以及opencv 光流对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。

本文目录一览:

如何用opencv实现动态手势识别?就是通过摄像头,对手的运动进行判别,既手向左判断向左,手向右判断向右

可以先对手势进行分割,把手拿出来,然后利用harr特征来做手势识别。在opencv里有先关的东西。

请求帮助 实现 背景差减法 、帧间差分法、光流法 的算法,C++或者matlab都行,现成的源码都行

建议用opencv库

环境搭建:

矩阵操作:

代码:

absdiff(frame, prveframe, differframe);//获取差分帧 differframe= frame-prveframe

如何使用opencv实现金字塔光流lk跟踪算法

#include stdio.h

#include windows.h

#include "cv.h"

#include "cxcore.h"

#include "highgui.h"

#include opencv2\opencv.hpp

using namespace cv;

static const double pi = 3.14159265358979323846;

inline static double square(int a)

{

return a * a;

}

/*该函数目的:给img分配内存空间,并设定format,如位深以及channel数*/

inline static void allocateOnDemand(IplImage **img, CvSize size, int depth, int channels)

{

if (*img != NULL) return;

*img = cvCreateImage(size, depth, channels);

if (*img == NULL)

{

fprintf(stderr, "Error: Couldn't allocate image. Out of memory?\n");

exit(-1);

}

}

/*主函数,原程序是读取avi视频文件,然后处理,我简单改成从摄像头直接读取数据*/

int main(int argc, char *argv[])

{

//读取摄像头

VideoCapture cap(0);

//读取视频文件

//VideoCapture cap; cap.open("optical_flow_input.avi");

if (!cap.isOpened())

{

return -1;

}

Mat frame;

/*

bool stop = false;

while (!stop)

{

cap frame;

// cvtColor(frame, edges, CV_RGB2GRAY);

// GaussianBlur(edges, edges, Size(7, 7), 1.5, 1.5);

// Canny(edges, edges, 0, 30, 3);

// imshow("当前视频", edges);

imshow("当前视频", frame);

if (waitKey(30) = 0)

stop = true;

}

*/

//CvCapture *input_video = cvCaptureFromFile( "optical_flow_input.avi" );

//cv::VideoCapture cap = *(cv::VideoCapture *) userdata;

//if (input_video == NULL)

// {

// fprintf(stderr, "Error: Can't open video device.\n");

// return -1;

// }

/*先读取一帧,以便得到帧的属性,如长、宽等*/

//cvQueryFrame(input_video);

/*读取帧的属性*/

CvSize frame_size;

frame_size.height = cap.get(CV_CAP_PROP_FRAME_HEIGHT);

frame_size.width = cap.get(CV_CAP_PROP_FRAME_WIDTH);

/*********************************************************/

/*用于把结果写到文件中去,非必要

int frameW = frame_size.height; // 744 for firewire cameras

int frameH = frame_size.width; // 480 for firewire cameras

VideoWriter writer("VideoTest.avi", -1, 25.0, cvSize(frameW, frameH), true);

/*开始光流法*/

//VideoWriter writer("VideoTest.avi", CV_FOURCC('D', 'I', 'V', 'X'), 25.0, Size(640, 480), true);

while (true)

{

static IplImage *frame = NULL, *frame1 = NULL, *frame1_1C = NULL,

*frame2_1C = NULL, *eig_image = NULL, *temp_image = NULL,

*pyramid1 = NULL, *pyramid2 = NULL;

Mat framet;

/*获取第一帧*/

// cap framet;

cap.read(framet);

Mat edges;

//黑白抽象滤镜模式

// cvtColor(framet, edges, CV_RGB2GRAY);

// GaussianBlur(edges, edges, Size(7, 7), 1.5, 1.5);

// Canny(edges, edges, 0, 30, 3);

//转换mat格式到lpiimage格式

frame = IplImage(framet);

if (frame == NULL)

{

fprintf(stderr, "Error: Hmm. The end came sooner than we thought.\n");

return -1;

}

/*由于opencv的光流函数处理的是8位的灰度图,所以需要创建一个同样格式的

IplImage的对象*/

allocateOnDemand(frame1_1C, frame_size, IPL_DEPTH_8U, 1);

/* 把摄像头图像格式转换成OpenCV惯常处理的图像格式*/

cvConvertImage(frame, frame1_1C, 0);

/* 我们需要把具有全部颜色信息的原帧保存,以备最后在屏幕上显示用*/

allocateOnDemand(frame1, frame_size, IPL_DEPTH_8U, 3);

cvConvertImage(frame, frame1, 0);

/* 获取第二帧 */

//cap framet;

cap.read(framet);

// cvtColor(framet, edges, CV_RGB2GRAY);

// GaussianBlur(edges, edges, Size(7, 7), 1.5, 1.5);

// Canny(edges, edges, 0, 30, 3);

frame = IplImage(framet);

if (frame == NULL)

{

fprintf(stderr, "Error: Hmm. The end came sooner than we thought.\n");

return -1;

}

/*原理同上*/

allocateOnDemand(frame2_1C, frame_size, IPL_DEPTH_8U, 1);

cvConvertImage(frame, frame2_1C, 0);

/*********************************************************

开始shi-Tomasi算法,该算法主要用于feature selection,即一张图中哪些是我

们感兴趣需要跟踪的点(interest point)

input:

* "frame1_1C" 输入图像.

* "eig_image" and "temp_image" 只是给该算法提供可操作的内存区域.

* 第一个".01" 规定了特征值的最小质量,因为该算法要得到好的特征点,哪就

需要一个选择的阈值

* 第二个".01" 规定了像素之间最小的距离,用于减少运算复杂度,当然也一定

程度降低了跟踪精度

* "NULL" 意味着处理整张图片,当然你也可以指定一块区域

output:

* "frame1_features" 将会包含fram1的特征值

* "number_of_features" 将在该函数中自动填充上所找到特征值的真实数目,

该值= 400

**********************************************************/

/*开始准备该算法需要的输入*/

/* 给eig_image,temp_image分配空间*/

allocateOnDemand(eig_image, frame_size, IPL_DEPTH_32F, 1);

allocateOnDemand(temp_image, frame_size, IPL_DEPTH_32F, 1);

/* 定义存放frame1特征值的数组,400只是定义一个上限 */

CvPoint2D32f frame1_features[400];

int number_of_features = 400;

/*开始跑shi-tomasi函数*/

cvGoodFeaturesToTrack(frame1_1C, eig_image, temp_image,

frame1_features, number_of_features, .01, .01, NULL);

/**********************************************************

开始金字塔Lucas Kanade光流法,该算法主要用于feature tracking,即是算出

光流,并跟踪目标。

input:

* "frame1_1C" 输入图像,即8位灰色的第一帧

* "frame2_1C" 第二帧,我们要在其上找出第一帧我们发现的特征点在第二帧

的什么位置

* "pyramid1" and "pyramid2" 是提供给该算法可操作的内存区域,计算中间

数据

* "frame1_features" 由shi-tomasi算法得到的第一帧的特征点.

* "number_of_features" 第一帧特征点的数目

* "optical_flow_termination_criteria" 该算法中迭代终止的判别,这里是

epsilon0.3,epsilon是两帧中对应特征窗口的光度之差的平方,这个以后的文

章会讲

* "0" 这个我不知道啥意思,反正改成1就出不来光流了,就用作者原话解释把

means disable enhancements. (For example, the second array isn't

pre-initialized with guesses.)

output:

* "frame2_features" 根据第一帧的特征点,在第二帧上所找到的对应点

* "optical_flow_window" lucas-kanade光流算法的运算窗口,具体lucas-kanade

会在下一篇详述

* "5" 指示最大的金字塔层数,0表示只有一层,那就是没用金字塔算法

* "optical_flow_found_feature" 用于指示在第二帧中是否找到对应特征值,

若找到,其值为非零

* "optical_flow_feature_error" 用于存放光流误差

**********************************************************/

/*开始为pyramid lucas kanade光流算法输入做准备*/

CvPoint2D32f frame2_features[400];

/* 该数组相应位置的值为非零,如果frame1中的特征值在frame2中找到 */

char optical_flow_found_feature[400];

/* 数组第i个元素表对应点光流误差*/

float optical_flow_feature_error[400];

/*lucas-kanade光流法运算窗口,这里取3*3的窗口,可以尝试下5*5,区别就是5*5

出现aperture problem的几率较小,3*3运算量小,对于feature selection即shi-tomasi算法来说足够了*/

CvSize optical_flow_window = cvSize(5, 5);

// CvSize optical_flow_window = cvSize(5, 5);

/* 终止规则,当完成20次迭代或者当epsilon=0.3,迭代终止,可以尝试下别的值*/

CvTermCriteria optical_flow_termination_criteria= cvTermCriteria(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 20, .3);

/*分配工作区域*/

allocateOnDemand(pyramid1, frame_size, IPL_DEPTH_8U, 1);

allocateOnDemand(pyramid2, frame_size, IPL_DEPTH_8U, 1);

/*开始跑该算法*/

cvCalcOpticalFlowPyrLK(frame1_1C, frame2_1C, pyramid1, pyramid2,frame1_features, frame2_features, number_of_features,

optical_flow_window, 5, optical_flow_found_feature,optical_flow_feature_error, optical_flow_termination_criteria, 0);

/*画光流场,画图是依据两帧对应的特征值,

这个特征值就是图像上我们感兴趣的点,如边缘上的点P(x,y)*/

for (int i = 0; i number_of_features; i++)

{

/* 如果没找到对应特征点 */

if (optical_flow_found_feature[i] == 0)

continue;

int line_thickness;

line_thickness = 1;

/* CV_RGB(red, green, blue) is the red, green, and blue components

* of the color you want, each out of 255.

*/

CvScalar line_color;

line_color = CV_RGB(255, 0, 0);

/*画箭头,因为帧间的运动很小,所以需要缩放,不然看不见箭头,缩放因子为3*/

CvPoint p, q;

p.x = (int)frame1_features[i].x;

p.y = (int)frame1_features[i].y;

q.x = (int)frame2_features[i].x;

q.y = (int)frame2_features[i].y;

double angle;

angle = atan2((double)p.y - q.y, (double)p.x - q.x);

double hypotenuse;

hypotenuse = sqrt(square(p.y - q.y) + square(p.x - q.x));

/*执行缩放*/

q.x = (int)(p.x - 5 * hypotenuse * cos(angle));

q.y = (int)(p.y - 5 * hypotenuse * sin(angle));

/*画箭头主线*/

/* "frame1"要在frame1上作画.

* "p" 线的开始点.

* "q" 线的终止点.

* "CV_AA" 反锯齿.

* "0" 没有小数位.

*/

cvLine(frame1, p, q, line_color, line_thickness, CV_AA, 0);

/* 画箭的头部*/

p.x = (int)(q.x + 9 * cos(angle + pi / 4));

p.y = (int)(q.y + 9 * sin(angle + pi / 4));

cvLine(frame1, p, q, line_color, line_thickness, CV_AA, 0);

p.x = (int)(q.x + 9 * cos(angle - pi / 4));

p.y = (int)(q.y + 9 * sin(angle - pi / 4));

cvLine(frame1, p, q, line_color, line_thickness, CV_AA, 0);

}

/*显示图像*/

/*创建一个名为optical flow的窗口,大小自动改变*/

cvNamedWindow("Optical Flow", CV_WINDOW_NORMAL);

cvFlip(frame1, NULL, 2);

cvShowImage("Optical Flow", frame1);

/*延时,要不放不了*/

cvWaitKey(33);

/*写入到文件中去*/

// cv::Mat m = cv::cvarrToMat(frame1);//转换lpimgae到mat格式

// writer m;//opencv3.0 version writer

}

cap.release();

cvWaitKey(33);

system("pause");

}

opencv svm怎么把特征转成svm中train函数需要的Mat类型

OpenCV开发SVM算法是基于LibSVM软件包开发的,LibSVM是台湾大学林智仁(Lin Chih-Jen)等开发设计的一个简单、易于使用和快速有效的SVM模式识别与回归的软件包。用OpenCV使用SVM算法的大概流程是1)设置训练样本集需要两组数据,一组是数据的类别,一组是数据的向量信息。2)设置SVM参数利用CvSVMParams类实现类内的成员变量svm_type表示SVM类型:CvSVM::C_SVC C-SVCCvSVM::NU_SVC v-SVCCvSVM::ONE_CLASS 一类SVMCvSVM::EPS_SVR e-SVRCvSVM::NU_SVR v-SVR成员变量kernel_type表示核函数的类型:CvSVM::LINEAR 线性:u‘vCvSVM::POLY 多项式:(r*u'v + coef0)^degreeCvSVM::RBF RBF函数:exp(-r|u-v|^2)CvSVM::SIGMOID sigmoid函数:tanh(r*u'v + coef0)成员变量degree针对多项式核函数degree的设置,gamma针对多项式/rbf/sigmoid核函数的设置,coef0针对多项式/sigmoid核函数的设置,Cvalue为损失函数,在C-SVC、e-SVR、v-SVR中有效,nu设置v-SVC、一类SVM和v-SVR参数,p为设置e-SVR中损失函数的值,class_weightsC_SVC的权重,term_crit为SVM训练过程的终止条件。其中默认值degree = 0,gamma = 1,coef0 = 0,Cvalue = 1,nu = 0,p = 0,class_weights = 03)训练SVM调用CvSVM::train函数建立SVM模型,第一个参数为训练数据,第二个参数为分类结果,最后一个参数即CvSVMParams4)用这个SVM进行分类调用函数CvSVM::predict实现分类5)获得支持向量除了分类,也可以得到SVM的支持向量,调用函数CvSVM::get_support_vector_count获得支持向量的个数,CvSVM::get_support_vector获得对应的索引编号的支持向量。实现代码如下:view plain// step 1: float labels[4] = {1.0, -1.0, -1.0, -1.0}; Mat labelsMat(3, 1, CV_32FC1, labels); float trainingData[4][2] = { {501, 10}, {255, 10}, {501, 255}, {10, 501} }; Mat trainingDataMat(3, 2, CV_32FC1, trainingData); // step 2: CvSVMParams params; params.svm_type = CvSVM::C_SVC; params.kernel_type = CvSVM::LINEAR; params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6); // step 3: CvSVM SVM; SVM.train(trainingDataMat, labelsMat, Mat(), Mat(), params); // step 4: Vec3b green(0, 255, 0), blue(255, 0, 0); for (int i=0; iimage.rows; i++) { for (int j=0; jimage.cols; j++) { Mat sampleMat = (Mat_float(1,2) i,j); float response = SVM.predict(sampleMat); if (fabs(response-1.0) 0.0001) { image.atVec3b(j, i) = green; } else if (fabs(response+1.0) 0.001) { image.atVec3b(j, i) = blue; } } } // step 5: int c = SVM.get_support_vector_count(); for (int i=0; i i++) { const float* v = SVM.get_support_vector(i); } OpenCV支持的目标检测的方法是利用样本的Haar特征进行的分类器训练,得到的级联boosted分类器(Cascade Classification)。注意,新版本的C++接口除了Haar特征以外也可以使用LBP特征。先介绍一下相关的结构,级联分类器的计算特征值的基础类FeatureEvaluator,功能包括读操作read、复制clone、获得特征类型getFeatureType,分配图片分配窗口的操作setImage、setWindow,计算有序特征calcOrd,计算绝对特征calcCat,创建分类器特征的结构create函数。级联分类器类CascadeClassifier。目标级联矩形的分组函数groupRectangles。接下来,我尝试使用CascadeClassifier这个级联分类器类检测视频流中的目标(haar支持的目标有人脸、人眼、嘴、鼻、身体。这里尝试比较成熟的人脸和眼镜)。用load函数加载XML分类器文件(目前提供的分类器包括Haar分类器和LBP分类器(LBP分类器数据较少))具体步骤如下:1)加载级联分类器调用CascadeClassifier类成员函数load实现,代码为:view plainCascadeClassifier face_cascade; face_cascade.load("haarcascade_frontalface_alt.xml"); 2)读取视频流这部分比较基础啦~~从文件中读取图像序列,读取视频文件,读取摄像头视频流看过我之前的文章,这3种方法应该了然于心。3)对每一帧使用该分类器这里先将图像变成灰度图,对它应用直方图均衡化,做一些预处理的工作。接下来检测人脸,调用detectMultiScale函数,该函数在输入图像的不同尺度中检测物体,参数image为输入的灰度图像,objects为得到被检测物体的矩形框向量组,scaleFactor为每一个图像尺度中的尺度参数,默认值为1.1,minNeighbors参数为每一个级联矩形应该保留的邻近个数(没能理解这个参数,-_-|||),默认为3,flags对于新的分类器没有用(但目前的haar分类器都是旧版的,CV_HAAR_DO_CANNY_PRUNING利用Canny边缘检测器来排除一些边缘很少或者很多的图像区域,CV_HAAR_SCALE_IMAGE就是按比例正常检测,CV_HAAR_FIND_BIGGEST_OBJECT只检测最大的物体,CV_HAAR_DO_ROUGH_SEARCH只做初略检测),默认为0.minSize和maxSize用来限制得到的目标区域的范围。这里调用的代码如下:view plainface_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30) ); 4)显示目标这个也比较简单,调用ellips函数将刚才得到的faces矩形框都显示出来更进一步,也可以在得到的每一幅人脸中得到人眼的位置,调用的分类器文件为haarcascade_eye_tree_eyeglasses.xml,先将脸部区域选为兴趣区域ROI,重复上诉步骤即可,这里就不详细介绍了。当然,感兴趣的朋友也可以试试其他的xml文件作为分类器玩一下啊,感觉LBP特征虽然xml文件的大小很小,但效果还可以,不过我没有做过多的测试。光说不练假把式,最后贴上效果图和源代码的下载地址代码下载地址:配套的教程Tutorials对于Video的部分,没有实例进行说明,我只能摸石头过河啦,之前试过一个camShift做目标检测,这次试一试光流法做运动估计。这里使用的光流法是比较常用的 Lucas-Kanade方法。对于光流法的原理,我就不过多介绍了,主要讲使用OpenCV如何实现。首先利用goodFeaturesToTrack函数得到图像中的强边界作为跟踪的特征点,接下来要调用calcOpticalFlowPyrLK函数,输入两幅连续的图像,并在第一幅图像里选择一组特征点,输出为这组点在下一幅图像中的位置。再把得到的跟踪结果过滤一下,去掉不好的特征点。再把特征点的跟踪路径标示出来。说着好简单哦~~程序的效果和代码下载视频捕捉的对象中,背景通常保持不变。一般分析中关注移动的前景物体,威力提取出前景物体,需要建立背景的模型,将模型和当前帧进行比对检测前景物体。前景提取应用非常广泛,特别是在智能监控领域中。如果有不含前景物体的背景图片,提取前景的工作相对容易,只需要比对当前帧和背景图片的不同,调用函数absdiff实现。但是大多数情况,获得背景图片是不可能的,比如在复杂的场景下,或者有光线条件的变化。因此,就需要动态的变换背景。一种简单的办法是对所观察到的图片取平均,但这样做也有很多弊端,首先,这种办法在计算背景图片的前需要输入大量的图片,其次我们进行取平均的过程中不能有前景物体进入。所以一种相对好的办法是动态建立背景图片并实时更新。具体的实现过程主要分为两部分:一部分是调用absdiff函数找出当前图片和背景图片的区别,这之中使用了threshold函数去除为前景,当前图片像素与背景图片像素变化超过一定阈值的时候才认定其为前景;另一个工作是更新背景图片,调用函数accumulateWeighted,根据权重参数可以调整背景更新的速度,将当前图片更新到背景中,这里巧妙利用得到的前景提取结果作为mask,在更新背景图片的过程中避免了前景的干扰。程序效果如图,代码下载地址为虽然可以调整阈值参数和权重更新速度调节前景提取的结果,但从测试视频可以发现,树叶的运动对结果的干扰还是不小的,特别对于第一帧出现前景的情况,由于后续更新背景都是对前景mask后对背景进行更新的,所以第一帧的前景部分对背景的影响因子很难被更新掉。这里提出一种改进的办法——混合高斯模型。可以使一个像素具有更多的信息,这样可以有效的减少类似树叶的不停飘动,水波的不停荡漾这种对前景的干扰。这个精密的算法比之前我所介绍的简单方法要复杂很多,不易实现。还好,OpenCV已经为我们做好了相关工作,将其封装在类BackgroundSubtractorMOG,使用起来非常方便。实现代码如下:view plainMat frame; Mat foreground; // 前景图片 namedWindow("Extracted Foreground"); // 混合高斯物体 BackgroundSubtractorMOG mog; bool stop(false); while (!stop) { if (!capture.read(frame)) { break; } // 更新背景图片并且输出前景 mog(frame, foreground, 0.01); // 输出的前景图片并不是2值图片,要处理一下显示 threshold(foreground, foreground, 128, 255, THRESH_BINARY_INV);

运动目标检测——光流法与opencv代码实现

运动目标的检测的其主要目的是 获取目标对象的运动参数(位置、速度、加速度等)及运动轨迹 ,通过进一步分析处理,实现对目标行为更高层级上的理解。

运动目标检测技术目的是 从序列图像中将变化区域从背景图像中提取出来 ,常用于视频监视、图像压缩、三维重构、异常检测等。

运动目标检测主流方法有帧差法、背景差法、光流法等。光流法源于 仿生学 思想,更贴近于直觉,大量昆虫的视觉机理便是基于光流法。

二十世纪五十年代心理学家Gibson在他的著作“The Perception of Visual World”中首次提出了以心理学实验为基础的光流法基本概念,而直到八十年代才由Horn、Kanade、Lucash和Schunck创造性地将灰度与二维速度场相联系,引入光流约束方程的算法,对光流计算做了奠基性的工作。

光流(optical flow):由于目标对象或者摄像机的移动造成的图像对象在连续两帧图像中的移动。

小球在连续五帧运动构成的光流 小球在连续五帧运动构成的光流

通俗说,对于一个图片序列,把每张图像每个像素在连续帧之间的运动速度和方向( 某像素点在连续两帧上的位移矢量 )找出来就是光流场。

第t帧的时A点的位置是(x1, y1),第t+1帧时A点位置是(x2,y2),则像素点A的位移矢量:(ux, vy) = (x2, y2) - (x1,y1)

如何知道第t+1帧的时候A点的位置涉及到不同的光流计算方法,主要有四种:基于梯度的方法、基于匹配的方法、基于能量的方法、基于相位的方法。

光流法依赖于三个假设:

根据所形成的光流场中 二维矢量的疏密程度 ,光流法可分为稠密光流与稀疏光流。

基于区域匹配生成的稠密光流场 基于区域匹配生成的稠密光流场

稀疏光流只对有 明显特征的组点 (如角点)进行跟踪,计算开销小。

基于特征匹配发生成的稀疏光流场 基于特征匹配发生成的稀疏光流场

(1)calcOpticalFlowPyrLK

基于金字塔LK光流算法,计算某些点集的稀疏光流。

参考论文《Pyramidal Implementation of the Lucas Kanade Feature TrackerDescription of the algorithm》

(2)calcOpticalFlowFarneback

基于Gunnar Farneback 的算法计算稠密光流。

参考论文《Two-Frame Motion Estimation Based on PolynomialExpansion》

(3)CalcOpticalFlowBM

通过块匹配的方法来计算光流

(4)CalcOpticalFlowHS

基于Horn-Schunck 的算法计算稠密光流。

参考论文《Determining Optical Flow》

(5)calcOpticalFlowSF

论文《SimpleFlow: A Non-iterative, Sublinear Optical FlowAlgo》的实现

LK光流法效果 LK光流法效果

opencv光流法代码的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于opencv 光流、opencv光流法代码的信息别忘了在本站进行查找喔。

版权说明:如非注明,本站文章均为 AH站长 原创,转载请注明出处和附带本文链接;

本文地址:http://ahzz.com.cn/post/27636.html


取消回复欢迎 发表评论:

分享到

温馨提示

下载成功了么?或者链接失效了?

联系我们反馈

立即下载