我正在开展一个涉及视频运动放大算法的项目。目前我正在尝试使用riesz金字塔来理解基于相位的运动放大。我的主要信息来源是这份文件:
Riesz Pyramids for Fast Phase-Based Video Magnification \
我已经执行了以下步骤来尝试重现本文中的一些结果:
使用提供的riesz金字塔的matlab代码将图像分解为多个比例
通过将金字塔的一个子带卷积为[-0.5,0,0.5]和[-0.5,0,0.5]'来生成图像Riesz1和Riesz2。使用本文介绍的近似riesz变换。
通过计算atan(R2 / R1)来确定子带的每个像素中的主要局部方向。该计算源自本文中的等式3。
将变换引导至主导局部方向并计算得到的正交对
使用正交对生成一个复数(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));
生成的图像如下所示:
现在我的问题:
当使用atan(R2 / R1)计算theta时,我在结果中得到了很多伪影(参见图像&#34;显性方向&#34;)。有没有明显的东西我想念/做错了?
假设到目前为止我的结果是正确的。为了放大运动,我不仅需要能够确定局部相位,还需要更改它。我似乎错过了一些明显的东西,但我怎么会这样做呢?我是否需要以某种方式改变金字塔子带像素的相位然后折叠金字塔?如果有,怎么样?
我(显然)对这个主题很新,只对图像处理有基本的了解。我会非常感谢任何答案,无论是解决我的问题还是只是推荐其他有用的信息来源。
此致
答案 0 :(得分:1)
我已经有了这个算法的功能实现。以下是我使用此方法成功运动放大视频的步骤。
这些步骤应该应用于您(我已经尝试过用于RGB视频的视频序列的每个通道,您可能可以通过YUV视频中的亮度来完成它。)
创建每个帧的图像金字塔。原始纸张有一个推荐的金字塔结构,允许更大的放大倍数值,虽然它与拉普拉斯金字塔的效果相当不错。
对于每个视频频道的每个金字塔等级,计算Riesz变换(有关变换的概述,请参阅The Riesz transform and simultaneous representations of phase, energy and orientation in spatial vision,并参阅原始问题中的文章以获得有效的近似实现)。 p>
使用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
对于每个金字塔等级,使用带通滤波器对每个像素的相位值进行时间滤波,该带通滤波器设置为适合您要放大的运动的频率。请注意,这会从相位值中删除DC分量。
通过
计算放大的相位值amplifiedPhase = phase + (requiredGain * filteredPhase);
使用放大的相位计算每个金字塔等级的新像素值
amplifiedSequence = amplitude .* cos(amplifiedPhase);
折叠金字塔以生成新的放大视频频道。
将放大的频道重新组合成新的视频帧。
原始论文中还有一些其他步骤可以改善噪音性能,但上面的序列可以很好地生成运动放大视频。
答案 1 :(得分:0)
图像的复杂表示可以用输入和正交对构造
complexImg = complex(I, Q);
然后可以通过将复数表示与e ^( - i * shift)相乘来生成图像的相移重建,这消除了表示的复杂部分并导致原始图像加上引入的相移。
reconstructed = complexImg*exp(-sqrt(-1) * shift);
我必须尝试一点,但这似乎产生了预期的结果。
感谢您的帮助!
答案 2 :(得分:0)
我已经完全实现了Riesz金字塔的方法,用于基于快速相位的视频运动放大。我觉得这些文件没有清楚地描述正确过滤阶段所需的适当步骤。重要的是要认识到,使用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);
此数量&#34; phase_diff&#34;在时间上过滤,并通过乘以放大因子进行放大。然后使用经滤波,放大的相位变化来相移输入。
magnified output = amplitude.*cos(phase_diff_filtered_amplified + original phase).