Прошивание Видео с быстрым воспроизведением кадров - PullRequest
0 голосов
/ 10 сентября 2018

Я пытаюсь сшить два видео вместе, сопоставляя ключевые моменты, но находя гомографию между перекрывающимися видео. Я успешно получил это для работы с двумя разными изображениями.

С видео я загрузил два отдельных видеофайла, зациклил кадры и скопировал их в пустую матрицу cap1frame и cap2frame для каждого видео.

Затем я отправляю каждый кадр из каждого видео в функцию сшивания, которая сопоставляет ключевые точки на основе гомографии между двумя кадрами, сшивает их и отображает результирующее изображение. ( соответствие основано на примере openCV )

Однако сшивание выполнено успешно, оно приводит к очень медленному воспроизведению видео и некоторым графическим аномалиям на боковой стороне кадра. Видно на фото.

Мне интересно, как я могу сделать это более эффективным с быстрым воспроизведением видео.

int main(int argc, char** argv){
      // Create a VideoCapture object and open the input file
      VideoCapture cap1("left.mov");
      VideoCapture cap2("right.mov");
      // Check if camera opened successfully
      if(!cap1.isOpened() || !cap2.isOpened()){
        cout << "Error opening video stream or file" << endl;
        return -1;
      }
        //Trying to loop frames
        for (;;){
        Mat cap1frame;
        Mat cap2frame;

        cap1 >> cap1frame;
        cap2 >> cap2frame;

        // If the frame is empty, break immediately
        if (cap1frame.empty() || cap2frame.empty())
          break;

        //sending each frame from each video to the stitch function then displaying
        imshow( "Result", Stitching(cap1frame,cap2frame));

        if(waitKey(30) >= 0) break;
         //destroyWindow("Stitching");
        // waitKey(0);
      }
      return 0;
    }

enter image description here

1 Ответ

0 голосов
/ 05 октября 2018

Мне удалось решить мою проблему, предварительно рассчитав гомографию только с первым кадром видео. Это так, что функция была вызвана только один раз.

Затем я перебрал оставшуюся часть видео, чтобы применить деформацию видеокадров, чтобы их можно было соединить вместе на основе предварительно рассчитанной гомографии. Этот бит был изначально в моей функции сшивания.

У меня все еще была проблема с воспроизведением, все еще очень медленным при вызове imshow. Но я решил экспортировать полученное видео, и это сработало, когда в объекте VideoWriter был установлен правильный fps. Интересно, нужно ли мне просто настроить воспроизведение fms в imshow, но я не уверен в этом.

У меня есть полный код ниже:

#include <stdio.h>
#include <iostream>
#include "opencv2/core.hpp"
#include "opencv2/features2d.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/calib3d.hpp"
#include "opencv2/xfeatures2d.hpp"
#include <opencv2/xfeatures2d/nonfree.hpp>
#include <opencv2/xfeatures2d/cuda.hpp>
#include <opencv2/opencv.hpp>
#include <vector>
//To get homography from images passed in. Matching points in the images.

Mat Stitching(Mat image1,Mat image2){

    Mat I_1 = image1;
    Mat I_2 = image2;
//based on https://docs.opencv.org/3.3.0/d7/dff/tutorial_feature_homography.html
    cv::Ptr<Feature2D> f2d = xfeatures2d::SIFT::create();
        // Step 1: Detect the keypoints:
        std::vector<KeyPoint> keypoints_1, keypoints_2;
        f2d->detect( I_1, keypoints_1 );
        f2d->detect( I_2, keypoints_2 );
        // Step 2: Calculate descriptors (feature vectors)
        Mat descriptors_1, descriptors_2;
        f2d->compute( I_1, keypoints_1, descriptors_1 );
        f2d->compute( I_2, keypoints_2, descriptors_2 );
        // Step 3: Matching descriptor vectors using BFMatcher :
        BFMatcher matcher;
        std::vector< DMatch > matches;
        matcher.match( descriptors_1, descriptors_2, matches );
        // Keep best matches only to have a nice drawing.
        // We sort distance between descriptor matches
        Mat index;
        int nbMatch = int(matches.size());
        Mat tab(nbMatch, 1, CV_32F);
        for (int i = 0; i < nbMatch; i++)
            tab.at<float>(i, 0) = matches[i].distance;
        sortIdx(tab, index, SORT_EVERY_COLUMN + SORT_ASCENDING);
        vector<DMatch> bestMatches;
        for (int i = 0; i < 200; i++)
            bestMatches.push_back(matches[index.at < int > (i, 0)]);
        // 1st image is the destination image and the 2nd image is the src image
        std::vector<Point2f> dst_pts;                   //1st
        std::vector<Point2f> source_pts;                //2nd

        for (vector<DMatch>::iterator it = bestMatches.begin(); it != bestMatches.end(); ++it) {
            //cout << it->queryIdx << "\t" <<  it->trainIdx << "\t"  <<  it->distance << "\n";
            //-- Get the keypoints from the good matches
            dst_pts.push_back( keypoints_1[ it->queryIdx ].pt );
            source_pts.push_back( keypoints_2[ it->trainIdx ].pt );
        }
        Mat H_12 = findHomography( source_pts, dst_pts, CV_RANSAC );
      return H_12;
}
int main(int argc, char** argv){
  //Mats to get the first frame of video and pass to Stitching function.
  Mat I1, h_I1;
  Mat I2, h_I2;
  // Create a VideoCapture object and open the input file
  VideoCapture cap1("left.mov");
  VideoCapture cap2("right.mov");
  cap1.set(CV_CAP_PROP_BUFFERSIZE, 10);
  cap2.set(CV_CAP_PROP_BUFFERSIZE, 10);
  //Check if camera opened successfully
  if(!cap1.isOpened() || !cap2.isOpened()){
    cout << "Error opening video stream or file" << endl;
    return -1;
  }
//passing first frame to Stitching function
  if (cap1.read(I1)){
     h_I1 = I1;
   }

   if (cap2.read(I2)){
     h_I2 = I2;
   }
   Mat homography;
//passing here.
   homography = Stitching(h_I1,h_I2);
  std::cout << homography << '\n';

//creating VideoWriter object with defined values.
VideoWriter video("video/output.avi",CV_FOURCC('M','J','P','G'),30, Size(1280,720));

//Looping through frames of both videos.
    for (;;){
    Mat cap1frame;
    Mat cap2frame;

    cap1 >> cap1frame;
    cap2 >> cap2frame;

    // If the frame is empty, break immediately
    if (cap1frame.empty() || cap2frame.empty())
      break;
      Mat warpImage2;
      //warping the second video cap2frame so it matches with the first one.
      //size is defined as the final video size
      warpPerspective(cap2frame, warpImage2, homography, Size(1280,720), INTER_CUBIC);
      //final is the final canvas where both videos will be warped onto.
      Mat final (Size(1280,720), CV_8UC3);
      //Mat final(Size(cap1frame.cols*2 + cap1frame.cols, cap1frame.rows*2),CV_8UC3);
      //Using roi getting the relivent areas of each video.
      Mat roi1(final, Rect(0, 0,  cap1frame.cols, cap1frame.rows));
      Mat roi2(final, Rect(0, 0, warpImage2.cols, warpImage2.rows));
      //warping images on to the canvases which are linked with the final canvas.
      warpImage2.copyTo(roi2);
      cap1frame.copyTo(roi1);
      //writing to video.
      video.write(final);
      //imshow ("Result", final);
    if(waitKey(30) >= 0) break;
  }
  video.release();
  return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...