стабилизация видео с помощью opencv

Я пытаюсь сделать стабилизацию видео с помощью opencv (без класса стабилизации видео opencv).

шаги для моего алгоритма следующие->

  1. Добыча очков серфинга,

  2. соответствие,

  3. Матрица гомографии,

  4. деформацияПерспектива

И выходное видео вообще не стабилизировано :(. оно просто выглядит как исходное видео. Я не смог найти и справочный код для стабилизации видео. Я следовал процедуре, описанной здесь . Может ли кто-нибудь помочь мне, сказав, где я ошибаюсь, или предоставить мне ссылку на исходный код, чтобы улучшить мой алгоритм.

Пожалуйста помоги. Спасибо


person MMH    schedule 07.02.2014    source источник
comment
Этот вопрос и очень расплывчатый, и очень широкий. Вам нужно будет перефразировать его и предоставить нам больше информации, если мы хотим помочь вам.   -  person Hannes Ovrén    schedule 07.02.2014


Ответы (3)


Вы можете использовать мой фрагмент кода в качестве отправной точки (не очень стабильный, но, похоже, работает):

#include "opencv2/opencv.hpp"
#include <iostream>
#include <vector>
#include <stdio.h>

using namespace cv;
using namespace std;

int main(int ac, char** av)
{
    VideoCapture capture(0);
    namedWindow("Cam");
    namedWindow("Camw");
    Mat frame;
    Mat frame_edg;
    Mat prev_frame;
    int k=0;
    Mat Transform;
    Mat Transform_avg=Mat::eye(2,3,CV_64FC1);
    Mat warped;
    while(k!=27)
    {
        capture >> frame;
        cv::cvtColor(frame,frame,cv::COLOR_BGR2GRAY);
        cv::equalizeHist(frame,frame);
        cv::Canny(frame,frame_edg,64,64);
        //frame=frame_edg.clone();
        imshow("Cam_e",frame_edg);
        imshow("Cam",frame);

        if(!prev_frame.empty())
        {
            Transform=estimateRigidTransform(frame,prev_frame,0);
            Transform(Range(0,2),Range(0,2))=Mat::eye(2,2,CV_64FC1);
            Transform_avg+=(Transform-Transform_avg)/2.0;
            warpAffine(frame,warped,Transform_avg,Size( frame.cols, frame.rows));

            imshow("Camw",warped);
        }

        if(prev_frame.empty())
        {
            prev_frame=frame.clone();
        }

        k=waitKey(20);      
    }
    cv::destroyAllWindows();
    return 0;
}

Вы также можете найти документ: Chen_Halawa_Pang_FastVideoStabilization.pdf, насколько я помню, там был предоставлен исходный код MATLAB.

person Andrey Smorodov    schedule 08.02.2014
comment
Привет Андрей Спасибо за ответ. не могли бы вы объяснить, что делает Transform(Range(0,2),Range(0,2))=Mat::eye(2,2,CV_64FC1); Transform_avg+=(Transform-Transform_avg)/2.0; это 2 строки делает? А также я видел код Matlab, я пытаюсь преобразовать его в C++. - person MMH; 10.02.2014
comment
Transform(Range(0,2),Range(0,2))=Mat::eye(2,2,CV_64FC1); линия отбрасывает все преобразования (вращение, масштабирование и сдвиг), кроме перемещений. Это было сделано, так как мне не нужна эта компенсация преобразования и она повышает стабильность алгоритма. Строка Transform_avg+=(Transform-Transform_avg)/2.0; это разница для компенсации смещения преобразования. 1/2 это коэффициент для большей надежности, насколько я помню (я написал этот код пару лет назад), он также работает как фильтр нижних частот. - person Andrey Smorodov; 10.02.2014
comment
Спасибо, Андрей, я очень ценю ваш ответ. Но мое тестовое видео не дает хорошего результата с предоставленным фрагментом кода. в любом случае спасибо. - person MMH; 11.02.2014

В вашем "warpAffine(frame,warped,Transform_avg,Size(frame.cols, frame.rows));" функции, вы должны указать FLAG как WARP_INVERSE_MAP для стабилизации.

Пример кода, который я написал:

Mat src, prev, curr, rigid_mat, dst;

VideoCapture cap("test_a3.avi");

while (1)
{
    bool bSuccess = cap.read(src);
    if (!bSuccess) //if not success, break loop
        {
                cout << "Cannot read the frame from video file" << endl;
                break;
        }

    cvtColor(src, curr, CV_BGR2GRAY);

    if (prev.empty())
    {
        prev = curr.clone();
    }

    rigid_mat = estimateRigidTransform(prev, curr, false);

    warpAffine(src, dst, rigid_mat, src.size(), INTER_NEAREST|WARP_INVERSE_MAP, BORDER_CONSTANT);


    // ---------------------------------------------------------------------------//

    imshow("input", src);
    imshow("output", dst);

    Mat dst_gray;
    cvtColor(dst, dst_gray, CV_BGR2GRAY);
    prev = dst_gray.clone();

    waitKey(30);
}

Надеюсь, это решит вашу проблему :)

person user3566188    schedule 23.04.2014

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

теперь у вас есть характерные точки в вашем начальном кадре, следующее, что вам нужно сделать, это определить оптический поток. Существует несколько функций Optical Flow, но я использую OpticalFlow.PyrLK(), в одном из выходных параметров вы получаете точки признаков в текущем кадре. При этом вы можете рассчитать матрицу гомографии с помощью функции FindHomography(). Затем вам нужно инвертировать эту матрицу, объяснение вы можете легко найти в Google, затем вы вызываете функцию WarpPerspective() для стабилизации вашего кадра.

PS. Функции, которые я поместил здесь, взяты из EmguCV, оболочки .NET для OpenCV, поэтому могут быть некоторые отличия

person hof_mat    schedule 28.03.2014