2

我正在从事一个涉及视频运动放大算法的项目。目前我正在尝试使用 riesz 金字塔来理解基于相位的运动放大。我的主要信息来源是这份文件:

用于快速基于相位的视频放大的 Riesz Pyramids \

我已经执行了以下步骤来尝试重现论文中的一些结果:

  1. 使用为 riesz 金字塔提供的 matlab 代码将图像分解为多个尺度

  2. 通过使用论文中介绍的近似 riesz 变换将金字塔的一个子带与 [-0.5, 0, 0.5] 和 [-0.5, 0, 0.5]' 进行卷积,生成图像 Riesz1 和 Riesz2。

  3. 通过计算 atan(R2/R1) 确定子带每个像素中的主要局部方向。该计算源自论文中的公式 3。

  4. 将变换引导到主要的局部方向并计算得到的正交对

  5. 使用正交对生成一个复数 (I + iQ),其相位 I 然后用于确定特定像素中的局部相位。

这是我创建的 Matlab 代码:

%Generate a circle image
img = zeros(512, 512);
img(:) = 128;
rad = 180;
for i = size(img, 1)/2 - rad : size(img,1)/2 + rad
    for j = size(img, 2)/2 - rad : size(img,2)/2 + rad
        deltaX = abs(size(img, 1)/2 - i);
        deltaY = abs(size(img, 2)/2 - j);
        if (sqrt(deltaX^2+deltaY^2) <= rad)
           img(i, j) = 255;
        end
    end
end

%build riesz pyramid
[pyr, pind] = buildNewPyr(img);

%extract band2 from pyramid (no orientation information yet)
I = pyrBand(pyr,pind,3);

%convolve band2 with approximate riesz filter for first quadrature pair
%element
R1 = conv2(I, [0.5, 0, -0.5], 'same');

%convolve band2 with approximate riesz filter (rotated by 90°) for second
%quadrature pair element
R2 = conv2(I, [0.5, 0, -0.5]', 'same');

% show the resulting image containing orientation information!
% imshow(band2_r2, []);

%To extract the phase, we have to steer the pyramid to its dominant local
%orientation. Orientation is calculated as atan(R2/R1)
theta = atan(R2./R1);
theta(isnan(theta) | isinf(theta)) = 0;
%imshow(theta, []);

% create quadrature pair
Q = zeros(size(theta, 1), size(theta, 2));

for i = 1:size(theta, 1)
    for j = 1:size(theta, 1)
        if theta(i, j) ~= 0
            %create rotation matrix
            rot_mat = ...
                [cos(theta(i, j)), sin(theta(i, j));...
                -sin(theta(i, j)) cos(theta(i, j))];

            %steer to dominant local orientation(theta) and set Q
            resultPair = rot_mat*[R1(i, j), R2(i,j)]';
            Q(i,j) = resultPair(1);
        end 
    end
end

% create amplitude and phase image
A = abs(complex(I, Q));
Phi = angle(complex(I, Q));

生成的图像如下所示:

生成的图像

现在我的问题:

  1. 使用 atan(R2/R1) 计算 theta 时,我会在结果中得到很多伪像(参见图像“主导方向”)。有什么明显的我想念这里/做错了吗?

  2. 假设到目前为止我的结果是正确的。为了放大运动,我不仅需要能够确定局部相位,还需要改变它。我似乎错过了一些明显的东西,但我该怎么做呢?我是否需要以某种方式改变金字塔子带像素的相位然后折叠金字塔?如果是,如何?

我(显然)对这个主题很陌生,对图像处理只有初步的了解。我会非常感谢任何答案,无论是解决我的问题还是只是推荐其他有用的信息来源。

真挚地

4

3 回答 3

1

我有这个算法的功能实现。以下是我使用这种方法成功地对视频进行运动放大所采取的步骤。

这些步骤应该应用于您的视频序列的每个通道(我已经尝试将它用于 RGB 视频,您可能会在 YUV 视频中只为亮度而这样做)。

  1. 创建每一帧的图像金字塔。原始论文有一个推荐的金字塔结构,以允许更大的放大倍数,尽管它与拉普拉斯金字塔配合得很好。

  2. 对于每个视频通道的每个金字塔级别,计算 Riesz 变换(有关变换的概述,请参阅空间视觉中的 Riesz 变换和相位、能量和方向的同时表示,并参阅原始问题中的论文以获得有效的近似实现)。

  3. 使用 Riesz 变换,计算每个视频帧的每个金字塔级别的每个像素的局部幅度、方向和相位。以下 Matlab 代码将使用近似 Riesz 变换计算(双格式)图像的局部方向、相位和幅度:

    function [orientation, phase, amplitude] = riesz(image)
    
    [imHeight, imWidth] = size(image);
    
    %approx riesz, from Riesz Pyramids for Fast Phase-Based Video Magnification
    
    dxkernel = zeros(size(image));
    dxkernel(1, 2)=-0.5;
    dxkernel(1,imWidth) = 0.5;
    
    
    dykernel = zeros(size(image));
    dykernel(2, 1) = -0.5;
    dykernel(imHeight, 1) = 0.5;
    
    R1 = ifft2(fft2(image) .* fft2(dxkernel));
    R2 = ifft2(fft2(image) .* fft2(dykernel));
    
    
    orientation = zeros(imHeight, imWidth);
    phase = zeros(imHeight, imWidth);
    
    orientation = (atan2(-R2, R1));
    
    phase = ((unwrap(atan2(sqrt(R1.^2 + R2.^2) , image))));
    
    amplitude = sqrt(image.^2 + R1.^2 + R2.^2);
    
    end   
    
  4. 对于每个金字塔级别,使用设置为适合您希望放大的运动的频率的带通滤波器临时过滤每个像素的相位值。请注意,这会从相位值中去除直流分量。

  5. 计算放大的相位值

    amplifiedPhase = phase + (requiredGain * filteredPhase);
    
  6. 使用放大阶段计算每个金字塔级别的新像素值

    amplifiedSequence = amplitude .* cos(amplifiedPhase);
    
  7. 折叠金字塔以生成新的放大视频通道。

  8. 将您放大的频道重新组合成一个新的视频帧。

原始论文中还有一些其他步骤可以提高噪声性能,但上面的序列可以很好地产生运动放大视频。

于 2015-04-09T11:14:42.407 回答
1

我已经完全实现了基于快速相位的视频运动放大的 Riesz Pyramids 方法。我觉得论文没有清楚地描述正确过滤相位所需的适当步骤。重要的是要认识到相位和方向的多个数学上正确的表达式实际上可能不适合使用 MATLAB 的 acos()、asin() 和 atan() 函数。这是我的实现:

% R1, R2 are Riesz transforms of the image I and Q is the Quadrature pair

Q = sqrt((R1.^2) + (R2.^2));

phase = atan2(Q,I);

相位应该被包裹在-pi和+pi之间,即如果相位大于+pi,相位=相位-2*pi,如果相位小于-pi,

phase = phase + 2*pi.

amplitude = sqrt((I.^2) + (R1.^2) + (R2.^2));

此外,必须过滤连续帧之间的相位变化,而不是直接过滤相位。

phase_diff = phase(t+1) - phase(t);

这个量“phase_diff”在时间上被过滤,并通过乘以放大因子来放大。然后使用经滤波、放大的相位变化对输入进行相移。

magnified output = amplitude.*cos(phase_diff_filtered_amplified + original phase).
于 2016-03-05T18:28:43.413 回答
0

虽然 DrMcCleod 的回答没有直接提供解决方案,但他似乎走在了正确的轨道上。

可以从输入和正交对构造图像的复杂表示

complexImg = complex(I, Q);

然后可以通过将复数表示与 e^(-i*shift) 相乘来生成图像的相移重建,e^(-i*shift) 去除表示的复数部分并导致原始图像加上引入的相移。

reconstructed = complexImg*exp(-sqrt(-1) * shift);

我将不得不进行一些实验,但这似乎会产生预期的结果。

谢谢您的帮助!

于 2015-04-09T15:58:31.860 回答