主要内容

本页采用了机器翻译。点击此处可查看英文原文。

视频防抖

本示例演示了如何从视频流中消除相机运动带来的影响。

简介

例如,在此示例中,我们首先定义要跟踪的目标。在这种情况下,是汽车的后部和车牌。我们还建立了一个动态搜索区域,其位置由已知的最后目标位置决定。然后,我们仅在此搜索区域内搜索目标,从而减少了查找目标所需的计算量。在随后的每一帧视频中,我们都会确定目标相对于上一帧移动了多少。我们利用这些信息来消除不需要的平移相机运动,并生成一段稳定的视频。

初始化

创建一个 System object™ 来读取多媒体文件中的视频。我们将输出设置为仅包含亮度信息的视频。

% Input video file which needs to be stabilized.
filename = "shaky_car.avi";

hVideoSource = VideoReader(filename);

创建一个模板匹配器 System object,用于计算目标在视频帧中最佳匹配的位置。我们利用该位置来计算相邻视频帧之间的位移。

hTM = vision.TemplateMatcher("ROIInputPort", true, ...
                            "BestMatchNeighborhoodOutputPort", true);

创建一个名为 System object 的文件,用于显示原始视频和防抖后的视频。

hVideoOut = vision.VideoPlayer("Name", "Video Stabilization");
hVideoOut.Position(1) = round(0.4*hVideoOut.Position(1));
hVideoOut.Position(2) = round(1.5*(hVideoOut.Position(2)));
hVideoOut.Position(3:4) = [650 350];

在此,我们初始化了处理循环中用到的几个变量。

pos.template_orig = [109 100]; % [x y] upper left corner
pos.template_size = [22 18];   % [width height]
pos.search_border = [15 10];   % max horizontal and vertical displacement
pos.template_center = floor((pos.template_size-1)/2);
pos.template_center_pos = (pos.template_orig + pos.template_center - 1);
W = hVideoSource.Width; % Width in pixels
H = hVideoSource.Height; % Height in pixels
BorderCols = [1:pos.search_border(1)+4 W-pos.search_border(1)+4:W];
BorderRows = [1:pos.search_border(2)+4 H-pos.search_border(2)+4:H];
sz = [W, H];
TargetRowIndices = ...
  pos.template_orig(2)-1:pos.template_orig(2)+pos.template_size(2)-2;
TargetColIndices = ...
  pos.template_orig(1)-1:pos.template_orig(1)+pos.template_size(1)-2;
SearchRegion = pos.template_orig - pos.search_border - 1;
Offset = [0 0];
Target = zeros(18,22);
firstTime = true;

流处理循环

这是主处理循环,它使用我们上面实例化的对象来稳定输入视频。

while hasFrame(hVideoSource)
    input = im2gray(im2double(readFrame(hVideoSource)));

    % Find location of Target in the input video frame
    if firstTime
      Idx = int32(pos.template_center_pos);
      MotionVector = [0 0];
      firstTime = false;
    else
      IdxPrev = Idx;

      ROI = [SearchRegion, pos.template_size+2*pos.search_border];
      Idx = hTM(input,Target,ROI);

      MotionVector = double(Idx-IdxPrev);
    end

    [Offset, SearchRegion] = updatesearch(sz, MotionVector, ...
        SearchRegion, Offset, pos);

    % Translate video frame to offset the camera motion
    Stabilized = imtranslate(input, Offset, "linear");

    Target = Stabilized(TargetRowIndices, TargetColIndices);

    % Add black border for display
    Stabilized(:, BorderCols) = 0;
    Stabilized(BorderRows, :) = 0;

    TargetRect = [pos.template_orig-Offset, pos.template_size];
    SearchRegionRect = [SearchRegion, pos.template_size + 2*pos.search_border];

    % Draw rectangles on input to show target and search region
    input = insertShape(input, "rectangle", [TargetRect; SearchRegionRect],...
                        "Color", "white");
    % Display the offset (displacement) values on the input image
    txt = sprintf("(%+05.1f,%+05.1f)", Offset);
    input = insertText(input(:,:,1),[191 215],txt,"FontSize",16, ...
                    "TextColor", "white", "BoxOpacity", 0);
    % Display video
    hVideoOut([input(:,:,1) Stabilized]);
end

结论

利用 MATLAB® 命令行中的 Computer Vision Toolbox™ 函数,可以轻松实现视频防抖等复杂系统。

附录

本示例中使用了以下辅助函数。