使用 Lucas-Kanade 方法的视频稳定

信息处理 matlab 算法 视频处理 光流
2022-02-20 20:18:56

我在视频处理课程中获得了一项作业 - 使用 Lucas-Kanade 方法稳定视频。假设我编写的用于在 2 个图像上执行 LK 的 matlab 代码有效(即,我可以获得光流矩阵uv允许我将一个图像扭曲到另一个图像) - 我如何使用它来执行视频稳定?

据我了解,主要思想是计算每 2 个相邻帧的 OF,并将所有图像向第一个图像扭曲。这意味着我需要保留在整个过程中积累的总扭曲——实际上:保存总扭曲矩阵并将我从 2 个相邻帧中获得u_tot, v_tot的矩阵添加到它们中,以根据等执行后一帧的扭曲on(注意下面的 matlab 代码)。u, vu_tot, v_tot

我是否朝着正确的方向前进?我想得到一个建议...谢谢


matlab代码:

编辑:更改代码 + 添加 WarpImage imp。(23.4.17)

function StabilizedVid =LucasKanadeVideoStabilization(InputVid,WindowSize,MaxIter,NumLevels,NumOfFrames)
    % InputVid is a VideoFileReader object
    % WindowSize - window size for the LK phase
    % MaxIter - maximal number of iterations for the LK phase
    % NumLevels - number of levels in the pyramid for the LK phase
    % NumOfFrames - number of frames to process

    reset(InputVid);
    StabilizedVid = vision.VideoFileWriter('StabilizedVid.avi');
    cnt = 1;
    if (~isDone(InputVid))
        frame1 = im2double(rgb2gray(step(InputVid)));
        first_frame = true;
    else
        error('no frames in the video');
    end

    while ~isDone(InputVid)
        cnt = cnt+1;
        frame2 = im2double(rgb2gray(step(InputVid)));
        [frame1, frame2] = sizeCheck(frame1, frame2, NumLevels);
        if (first_frame)
            u_tot = zeros(size(frame1));
            v_tot = zeros(size(frame1));
            step(StabilizedVid,frame1);
            first_frame = false;
        end  
        disp(['processing frames no. ', num2str(cnt-1), ', ', num2str(cnt)]);
        tic
        [u ,v] = LucasKanadeOpticalFlow(frame1,frame2,WindowSize,MaxIter,NumLevels); 
        disp(['time: ', num2str(toc)]);
        u_tot = u_tot + u;
        v_tot = v_tot + v;
        frame2_warp = WarpImage(frame2, u_tot, v_tot);
        step(StabilizedVid,frame2_warp);
        if cnt >= NumOfFrames
            break
        end
        frame1 = frame2_warp;
    end
    release(StabilizedVid);
end

%%%%%%%%%%%%%%%%%%%%

function I_warp = WarpImage(I,u,v)
    % I - image to warp
    % u,v - the optical flow parameters gotten from the LK algorithm        

    [x, y] = meshgrid(1:size(I,2),1:size(I,1));
    % interpulate
    I_warp = interp2(I, x+u, y+v, 'cubic');
    % in case of NaN values - put the original values of I instead
    I_warp(isnan(I_warp)) = I(isnan(I_warp));

end
1个回答

对于视频稳定,您需要估计相对于参考帧的运动矢量Freference(让我们假设它是第一帧)。然后应该确定您的运动模型,为简单起见,我们假设它是平移运动。因此,我们需要估计运动x方向和运动y每一帧的方向。现在您有两个选项来估计变化。如果您有兴趣通过光流估计它,您可以执行以下任一操作:

  1. 估计从帧到帧的常规常规光流
  2. 估计第一帧到i th框架。

我在整个过程中积累-实际上...

如果您选择了第一种,那么Yes,您需要累积光流,但我认为选择第二种方法会更简单。

作为提示,我建议跟踪一个标记或计算一小块图像的光流。

编辑:

我觉得问题出在你的 Warp 函数上,下面的代码是我课堂上视频稳定任务的一部分,试试这个示例。使用基于标记的跟踪来估计平移参数。

function [ ou_I ] = frame_translation_func( in_I,Tx,Ty,ou_RoWs,ou_CuLoMns,ou_layer)
ou_I = uint8(zeros(ou_RoWs,ou_CuLoMns,ou_layer));
for i2=1:ou_RoWs
    for j2=1:ou_CuLoMns
        if (i2 - Tx<1) || (j2 - Ty<1) || (i2 - Tx>ou_RoWs) || (j2 - Ty>ou_CuLoMns)
            ou_I(i2,j2,:)=0;
        else
            ou_I(i2,j2,:) = in_I(i2 - Tx,j2 - Ty,:);
        end
    end
end
end