Help coding a "circular" 2D tapered cosine function

10 views (last 30 days)
I would like to produce a 2D function that looks like a circular flat-top with tapered cosine edges. Something like this:
Imagine the tapered cosine function:
tukeywin()
I would like the profile through the centre of the 2D function to look like this, but if visualizing the function from plan view, I would like it to be circular rather than rectangular like the 2D tapered cosine function which is given by the below code:
diam = 25; % Diameter of tukey window
alpha = 0.5; % Falloff of function. 1 is equal to hanning window
wc=window(@tukeywin,diam,alpha);
wr=window(@tukeywin,diam,alpha);
[maskr,maskc] = meshgrid(wr,wc);
tukey2D = maskr.*maskc;
Could someone help me? I imagine the solution will use the function cart2pol()
I have come up with this as a start, but I don't think it's exactly what I am after. The below code does produce a round tapered function, but its edges don't follow the cosine shape I am after. I think instead of rotating one of the masks and multiplying, it would be better to generate the function in polar co-ordinates. By multiplying the masks, I am going to higher order functions for the falloff. I would like the function to always fill up the entire window. There's also a slight issue with cropping the rotated function to the same size as the original array where i have used "ceil" and "floor" meaning the center of rotation is not in the middle when the array size is small and of even side length.
% rounded tukey function
L = 100; % Length of tukey window
alpha = 0.5; % Falloff of function. 1 is equal to hanning window
beta = 45; % rotation increment of mask
wc=window(@tukeywin,L,alpha);
wr=window(@tukeywin,L,alpha);
[maskr,maskc] = meshgrid(wr,wc);
for i = 1:beta:180
temprot=imrotate(maskc,i);
if size(temprot)>size(maskr)
maskr = maskr.*temprot(ceil(end/2)-floor(L/2):floor(end/2)+ceil(L/2),ceil(end/2)-floor(L/2):floor(end/2)+ceil(L/2));
else
maskr = maskr.*temprot;
end
end
% Graphics
maskr(maskr<1e-9)=0;
figure;
surf(maskr,'Linestyle','none')

Answers (2)

Frederick Purcell
Frederick Purcell on 28 Feb 2018
Came across the same problem while trying to create the same type of filter. The window you created and were aiming for are both shown and described in the link below
This block of python demonstrates how to create the desired window using a 1D window function expended to 2D with a circular support (any 1D window function could be used). I wrote this to demonstrate the concept rather than to be used as is.
%if true
import numpy as np
from scipy import signal
def tukey_twoD(width, alpha):
"""2D tukey lowpass window with a circular support
"""
base = np.zeros((width, width))
tukey = signal.tukey(width, alpha)
tukey = tukey[int(len(tukey)/2)-1:] # Second half of tukey window
x = np.linspace(-width/2, width/2, width)
y = np.linspace(-width/2, width/2, width)
for x_index in range(0, width):
for y_index in range(0, width):
# Only plot tukey value with in circle of radius width
if int(np.sqrt(x[x_index]**2 + y[y_index]**2)) <= width/2:
base[x_index, y_index] = tukey[int(np.sqrt(x[x_index]**2
+ y[y_index]**2))]
# Based on k**2 find tukey window value and place in matrix
return base
%end
This creates a low pass window of width 'width' in the centre of an array. E.g. with alpha = 0 and shape = 100 it will return a circle with a diameter of 100
Sorry to to give the solution in Python and not Matlab but should be pretty simple to translate over.
Hope this helps anyone coming across this problem in the future

Pavel Inchin
Pavel Inchin on 24 Oct 2018
just in case of need (based on code above):
domain = 600;
base = zeros(domain,domain);
tukey1 = tukeywin(domain,0.65);
tukey1 = tukey1(domain/2+1:domain);
x = linspace(-domain/2, domain/2, domain);
y = linspace(-domain/2, domain/2, domain);
for i=1:1:domain
for j=1:1:domain
if (round(sqrt(x(i)^2 + y(j)^2)) <= domain/2)
x(i);
y(i);
round(sqrt(x(i)^2+y(j)^2));
base(i,j) = tukey1(round(sqrt(x(i)^2+y(j)^2)));
end
end
end

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!