How to separate the upwards-propagating from the downwards-propagating waves? I've got a real 2D image of propagating waves in both directions. How can I separate this image into one with the upward-propagating waves and one with the downward-propagating ones?

This example has one wave in each direction. The x-scale shows time, the y-scale shows position, and intensity shows the amplitude of the wave at that position and time. The first image is my input.



However, I'm not very used to 2D signal processing, so the way I'm doing this is by just setting two quadrants of the FFT spectrum to zero and then reverse-transforming back. I got the other two images using the following algorithm:

X = fftshift(fft2( x )); % x is the input (image above)
X( 1:floor(size(X,1)/2),    1:floor(size(X,2)/2)   ) = 0; % null 1st quadrant
X( ceil(size(X,1)/2)+1:end, ceil(size(X,2)/2)+1:end) = 0; % null 3rd quadrant
y = ifft2( ifftshift(X) );
y = real( y ); % y is the output (image above)


It feels like such a barbaric method would introduce all kinds of artefacts, so I'm looking for feedback from someone more experienced.


Is there a better way to achieve this?
How should I "soften" the edges of the 0/1 "mask" I'm multiplying the FFT with?
The output is complex, so I'm discarding the imaginary part. Is that correct?
I'm also a bit worried about the fact that the noise will not be white anymore, but I suppose there isn't much to do about that except for low-pass filtering the whole image.
Instead of nulling the 2 quadrants, multiply them by $i$. Then the real part will be one image and the imaginary part the other image.


X = fftshift(fft2( x )); % x is the input (image above)
X( 1:floor(size(X,1)/2),    1:floor(size(X,2)/2)   ) = ...
    X( 1:floor(size(X,1)/2),    1:floor(size(X,2)/2)   ) * 1i;
X( ceil(size(X,1)/2)+1:end, ceil(size(X,2)/2)+1:end) = ...
    X( ceil(size(X,1)/2)+1:end, ceil(size(X,2)/2)+1:end) * 1i;
y = ifft2( ifftshift(X) );
imagesc(real(y)); pause;
imagesc(imag(y)); pause;


Since this is unitary operation the energy of this complex image will be the same as the original, as will the noise energy. Doesn't look very white to me though, seems there is differences between entire rows.

If you want to get rid of the artefacts, you could use a smoother function such as cosine of the angle of the spectrum:


[rows,cols] = size(x);
IM = fft2(x);
% Create polar co-ordinate of FFT
[ux, uy] = meshgrid(([1:cols]-(fix(cols/2)+1))/(cols-mod(cols,2)), ...
    ([1:rows]-(fix(rows/2)+1))/(rows-mod(rows,2)));
ux = ifftshift(ux);   % Quadrant shift to put 0 frequency at the corners
uy = ifftshift(uy);
th = atan2(uy,ux);
r = sqrt(ux.^2 + uy.^2);
% cos^2
R2 = cos(th +pi/4).^2 + 1i*cos(th +3*pi/4).^2;
R2(1,1) = 0;
I_a = real(ifft2(R2.*IM));
I_b = imag(ifft2(R2.*IM));
imagesc(I_a); pause;
imagesc(I_b); pause;


I don't think the energy remains constant in this case, but assuming white noise energy the noise of the resulting two images should be similar. 

Using the polar form of the spectrum it will be easier to experiment and create smoother cutoffs. For example, you could 'narrow' the angle of the filter to isolate the wave further.