题目说明:图像稳定。(运动跟踪或光流法代码)在一个更大的窗口中创建并显示视频图像。轻轻移动摄像机,并用光流法的向量将图像显示在大窗口中,并保持画面稳定。这是一个最基本的图像稳定技术。
程序操作方法:运行程序后,点击鼠标左键标定跟踪点,点击右键完成标定,4个标定点可启动图像稳定窗口(这里图像稳定是:使用透视投影变换将新的图像投影到原来的图像平面,实现图像稳定)
#include <opencv2/video/video.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>
#include <iostream>
#include <cstdio>
using namespace std;
using namespace cv;
Mat frame;
Mat prevImg;
Mat nextImg;
Mat copy_frame;
Mat warp_matrix;
Mat perspecttive_frame;
vector<Point2f> features;
vector<Point2f> prevPts;
vector<Point2f> nextPts;
vector<Point2f> initial;
int maxCount = 30;
double qLevel = 0.01;
double minDist = 10.0;
vector<uchar> status;
vector<float> err;
int detect_station;
void my_mouse_callback(int event,int x,int y,int flags,void* param)
{
switch (event){
case CV_EVENT_LBUTTONDOWN://点击鼠标左键标定跟踪点
{
prevPts.push_back(cvPoint(x,y));
initial.push_back(cvPoint(x,y));
}
break;
case CV_EVENT_RBUTTONDOWN:
{
detect_station = 1;//点击鼠标右键确认完成跟踪点标定
}
break;
}
}
int main()
{
cvNamedWindow("OpticalFlow",0);
cvNamedWindow("Perspective_Image",1);
cvSetMouseCallback("OpticalFlow",my_mouse_callback);
CvCapture* capture = cvCreateCameraCapture(0);
cvWaitKey(100);
while (capture)
{
frame = cvQueryFrame(capture);
imshow("OpticalFlow",frame);
cvWaitKey(1);
if (detect_station == 1)
{
cvtColor(frame ,nextImg,CV_BGR2GRAY);
if (prevImg.empty())
{
nextImg.copyTo(prevImg);
}
}
while(detect_station == 1)
{
if (prevPts.size() == 0)
{
break;
}
calcOpticalFlowPyrLK(prevImg,nextImg,prevPts,nextPts,status,err);
int k = 0;
for(int i=0;i<nextPts.size();i++)
{
if (status[i])
{
//prevPts[k++] = prevPts[i];
initial[k] = initial[i];
nextPts[k++] = nextPts[i];
}
}
nextPts.resize(k);
//nextPts.resize(k);
initial.resize(k);
for (int i=0 ;i<nextPts.size();i++)
{
line(frame,initial[i],nextPts[i],Scalar(0,0,255));
circle(frame, nextPts[i], 3, Scalar(255, 0, 0), -1);
}
swap(prevPts,nextPts);
swap(prevImg,nextImg);
imshow("OpticalFlow",frame);//显示跟踪点移动位置
//图像稳定(透视变换,基于标定点(4个)将新图像投影到原始图像的平面)
if (prevPts.size() == 4)
{
warp_matrix = getPerspectiveTransform(nextPts,prevPts);
warpPerspective(nextImg,perspecttive_frame,warp_matrix,cvSize(frame.cols,frame.rows));
imshow("Perspective_Image",perspecttive_frame);
}
//继续下一帧的处理
frame = cvQueryFrame(capture);
cvtColor(frame ,nextImg,CV_BGR2GRAY);
char c = cvWaitKey(10);
if(c == 27)
{
detect_station = 0;
initial.resize(0);
prevPts.resize(0);
break;
}
}
char d = cvWaitKey(10);
if (d == 27) break;
}
cvDestroyWindow("OpticalFlow");
cvReleaseCapture(&capture);
return 0;
}
程序基本函数:
1、确定图像强角点(Shi-Tomasi算子):goodFeaturesTotrack()—在程序中采用人为选取替代之,参数释义如下:
http://www.docs.opencv.org/modules/imgproc/doc/feature_detection.html?highlight=goodfeaturestotrack%20c#void
2、图像金字塔中计算Lucas-Kanade光流的算法:calcOpticalFlowPyrLK(),参数释义如下:
http://www.docs.opencv.org/modules/video/doc/motion_analysis_and_object_tracking.html?highlight=calcopticalflowpyrlk#void
3、透视投影变换函数:getPerspectiveTransform()和warpPerspective(),前者是用来求取矩阵,后者是进行透视变换。参数释义如下:
http://www.docs.opencv.org/modules/imgproc/doc/geometric_transformations.html?highlight=getperspectivetransform#Mat
http://www.docs.opencv.org/modules/imgproc/doc/geometric_transformations.html?highlight=warpperspective#void
程序由于事先人为采集跟踪点,降低了视频处理光流算法的计算开销,故可实时进行跟踪与处理。
程序部分参考:yang_xian521,wenrenwang
http://blog.csdn.net/yang_xian521/article/details/6987447
http://download.csdn.net/detail/wenrenwang/4997013