《学习OpenCV》第四章课后题9

题目说明:图像稳定。(运动跟踪或光流法代码)在一个更大的窗口中创建并显示视频图像。轻轻移动摄像机,并用光流法的向量将图像显示在大窗口中,并保持画面稳定。这是一个最基本的图像稳定技术。
程序操作方法:运行程序后,点击鼠标左键标定跟踪点,点击右键完成标定,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

发布了19 篇原创文章 · 获赞 13 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/windxf/article/details/49046757