代码之家  ›  专栏  ›  技术社区  ›  user2745692

视频稳定

  •  0
  • user2745692  · 技术社区  · 12 年前

    我正在研究视频稳定领域。我使用OpenCV实现了一个应用程序。

    我的进度,例如:

    曲面点提取

    匹配

    估计刚性变压器

    翘曲仿射

    但结果视频并不稳定。有谁能帮我解决这个问题,或者给我提供一些源代码链接来改进吗?

    视频示例: Hippo video

    这是我的代码[EDIT]

    #include "stdafx.h"
    #include "opencv2/highgui/highgui.hpp"
    #include "opencv2/imgproc/imgproc.hpp"
    #include <iostream>
    #include <stdio.h>
    #include <opencv2/nonfree/features2d.hpp>
    #include <opencv2/opencv.hpp>
    
    const double smooth_level = 0.7;
    using namespace cv;
    using namespace std;
    struct TransformParam
    {
        TransformParam() {}
        TransformParam(double _dx, double _dy, double _da) {
        dx = _dx;
        dy = _dy;
        da = _da;
    }
       double dx; // translation x
       double dy; // translation y
       double da; // angle
    };
    int main( int argc, char** argv )
    {
         VideoCapture cap ("test12.avi");  
         Mat cur, cur_grey;
         Mat prev, prev_grey;
    
    
         cap >> prev;
         cvtColor(prev, prev_grey, COLOR_BGR2GRAY);
    
         // Step 1 - Get previous to current frame transformation (dx, dy, da) for all frames
         vector <TransformParam> prev_to_cur_transform; // previous to current
    
         int k=1;
         int max_frames =  cap.get(CV_CAP_PROP_FRAME_COUNT);
         VideoWriter writeVideo ("stable.avi",0,30,cvSize(prev.cols,prev.rows),true);
         Mat last_T;
         double avg_dx = 0, avg_dy = 0, avg_da = 0;
         Mat smooth_T(2,3,CV_64F);
         while(true) {
            cap >> cur;
    
            if(cur.data == NULL) {
               break;
            }
    
            cvtColor(cur, cur_grey, COLOR_BGR2GRAY);
    
            // vector from prev to cur
            vector <Point2f> prev_corner, cur_corner;
            vector <Point2f> prev_corner2, cur_corner2;
            vector <uchar> status;
            vector <float> err;
    
            goodFeaturesToTrack(prev_grey, prev_corner, 200, 0.01, 30);
            calcOpticalFlowPyrLK(prev_grey, cur_grey, prev_corner, cur_corner, status, err);
    
           // weed out bad matches
           for(size_t i=0; i < status.size(); i++) {
               if(status[i]) {
                   prev_corner2.push_back(prev_corner[i]);
                  cur_corner2.push_back(cur_corner[i]);
               }
           }
    
           // translation + rotation only
           Mat T = estimateRigidTransform(prev_corner2, cur_corner2, false); 
    
           // in rare cases no transform is found. We'll just use the last known good transform.
           if(T.data == NULL) {
              last_T.copyTo(T);
           }
    
           T.copyTo(last_T);
    
          // decompose T
          double dx = T.at<double>(0,2);
          double dy = T.at<double>(1,2);
          double da = atan2(T.at<double>(1,0), T.at<double>(0,0));
          prev_to_cur_transform.push_back(TransformParam(dx, dy, da));
    
          avg_dx = (avg_dx * smooth_level) + (dx * (1- smooth_level));
          avg_dy = (avg_dy * smooth_level) + (dy * (1- smooth_level));
          avg_da = (avg_da * smooth_level) + (da * (1- smooth_level));
    
          smooth_T.at<double>(0,0) = cos(avg_da);
          smooth_T.at<double>(0,1) = -sin(avg_da);
          smooth_T.at<double>(1,0) = sin(avg_da);
          smooth_T.at<double>(1,1) = cos(avg_da);
    
          smooth_T.at<double>(0,2) = avg_dx;
          smooth_T.at<double>(1,2) = avg_dy;
    
          Mat stable;
          warpAffine(prev,stable,smooth_T,prev.size());
    
          Mat canvas = Mat::zeros(cur.rows, cur.cols*2+10, cur.type());
          prev.copyTo(canvas(Range::all(), Range(0, prev.cols)));
          stable.copyTo(canvas(Range::all(), Range(prev.cols+10, prev.cols*2+10)));
    
          imshow("before and after", canvas);
          waitKey(20);
          writeVideo.write(stable);
          cur.copyTo(prev);
          cur_grey.copyTo(prev_grey);
          k++;
       }
     }
    
    1 回复  |  直到 11 年前
        1
  •  1
  •   Vit    12 年前

    首先,你可以模糊你的图像。这会有点帮助。其次,通过指数平滑A(t+1)=A*A(t)+(1-A)*A(t+1)的最简单实现,可以轻松地平滑矩阵,并使用[0;1]范围内的A值。第三,可以关闭某些类型的变换,如旋转、移位等。 下面是代码示例:

    t = estimateRigidTransform(new, old, 0); // 0 means not all transformations (5 of 6)
    if(!t.empty()){
    //  t(Range(0,2), Range(0,2)) = Mat::eye(2, 2, CV_64FC1); // turning off rotation
    //  t.at<double>(0,2) = 0; t.at<double>(1,2) = 0; // turning off shift dx and dy
        tAvrg = tAvrg*a + t*(1-a); // a - smooth level in [0;1] range, play with it
        warpAffine(new, stable, tAvrg, Size(new.cols, new.rows));
    }