Code covered by the BSD License  

Highlights from
Toolbox Wavelets

image thumbnail
from Toolbox Wavelets by Gabriel Peyre
Wavelet transform and coding functions, including other more exotic transforms (laplacian, steerable

perform_quincunx_wavelet_transform(x,Jmin,dir,options)
function [y,quincunx_filters] = perform_quincunx_wavelet_transform(x,Jmin,dir,options)

% perform_quincunx_wavelet_transform - compute quincunx transform
%
% Forward transform
%   [MW,options.quincunx_filters] = perform_quincunx_wavelet_transform(M,Jmin,+1,options);
% Backward transform
%   M = perform_quincunx_wavelet_transform(MW,Jmin,-1,options);
%
% This is a simple wrapper to the code of
%   Dimitri Van De Ville
%   Biomedical Imaging Group, BIO-E/STI
%   Swiss Federal Institute of Technology Lausanne
%   CH-1015 Lausanne EPFL, Switzerland
%
% For more information, see
%   Isotropic Polyharmonic B-Splines: Scaling Functions and Wavelets
%   D. Van De Ville, T. Blu, M. Unser
%   IEEE Transactions on Image Processing, vol. 14, no. 11, pp. 1798-1813, November 2005.
%
% options.type is the type of transform:
%    - McClellan: O/B/D,
%    - Polyharmonic Rabut: Po/Pb/Pd
%    - Polyharmonic isotropic: PO/PB/PD
% options.gamma is the degree of the wavelet transform

options.null = 0;


% Setup parameters of wavelet transform
% -------------------------------------
% 1. Type of wavelet transform
%    - McClellan: O/B/D,
%    - Polyharmonic Rabut: Po/Pb/Pd
%    - Polyharmonic isotropic: PO/PB/PD
if isfield(options, 'type')
    type = options.type;
else
    type='PO';
end

% 2. Degree of the wavelet transform
%    (order gamma polyharmonic=degree alpha+2)
if isfield(options, 'gamma')
    gamma = options.gamma;
else
    gamma = 4;
end
alpha=gamma-2;

% 3. Number of iterations
n = size(x,1);
Jmax = log2(n)-1;
J = 2*(Jmax-Jmin+1);


% Precalculate filters
% --------------------
if isfield(options, 'quincunx_filters')
    quincunx_filters = options.quincunx_filters;
    FA = quincunx_filters{1};
    FS = quincunx_filters{2};
else
    [FA,FS]=FFTquincunxfilter2D([size(x)],alpha,type);
    quincunx_filters{1} = FA;
    quincunx_filters{2} = FS;
end

% Perform wavelet analysis
% ------------------------
if dir==1
    y = FFTquin2D_analysis(x,J,FA); y=real(y);
else
    y = FFTquin2D_synthesis(x,J,FS);
end


function A0=autocorr2d(H)

% AUTOCORR2D
%       Iterative frequency domain calculation of the 2D autocorrelation
%       function. A=autocorr2d(H) computes the frequency response of
%       the autocorrelation filter A(exp(2*i*Pi*nu)) corresponding to the
%       scaling function with refinement filter H.
%       Please note that the 2D grid of the refinement filter (nu),
%       corresponds to a uniformly sampled grid, twice as coarse
%       (in each dimension) as the given filter H.
%
% Please treat this source code as confidential!
% Its content is part of work in preparation to be submitted:
%
% T. Blu, D. Van De Ville, M. Unser, ''Numerical methods for the computation
% of wavelet correlation sequences,'' SIAM Numerical Analysis.
%
% Biomedical Imaging Group, EPFL, Lausanne, Switzerland.


len1=size(H,1)/2;
len2=size(H,2)/2;

% stop criterion
crit=1e-4;
improvement=1.0;

% initial "guess"
A0=ones(len1,len2);

% calculation loop

while improvement>crit,

    % sinc interpolation
    if 1,
        Af=fftshift(ifftn(A0));
        Af(1,:)=Af(1,:)/2;
        Af(:,1)=Af(:,1)/2;
        Af(len1+1,1:len2)=Af(1,len2:-1:1);
        Af(1:len1,len2+1)=Af(len1:-1:1,1);
        Ai=zeros(2*len1,2*len2);
        Ai(len1-len1/2+1:len1+len1/2+1,len2-len2/2+1:len2+len2/2+1)=Af;
        Ai=fftn(ifftshift(Ai));
    else
        Ai=interp2(A0,1,'nearest'); Ai(:,end+1)=Ai(:,end); Ai(end+1,:)=Ai(end,:);
    end;

    % recursion
    A1=Ai(1:len1,1:len2).*H(1:len1,1:len2)+Ai(len1+1:2*len1,1:len2).*H(len1+1:2*len1,1:len2)+Ai(1:len1,len2+1:2*len2).*H(1:len1,len2+1:2*len2)+Ai(len1+1:2*len1,len2+1:2*len2).*H(len1+1:2*len1,len2+1:2*len2);

    improvement=mean(abs(A1(:)-A0(:)));

    A0=A1;

end;


function y2=FFTquin2D_analysis(x,J,FA);

% FFTQUIN2D_ANALYSIS Perform 2D quincunx wavelet analysis
% 	y2 = FFTquin2D_analysis(x,J,FA)
%
% 	Input:
%       x  = input data
%       J  = number of iterations
%       FA = analysis filters
%
%       Output:
%       y2 = result (folded)
%
% Dimitri Van De Ville
%      Biomedical Imaging Group, BIO-E/STI
%      Swiss Federal Institute of Technology Lausanne
%      CH-1015 Lausanne EPFL, Switzerland

% Dimensions of data
[m,n]=size(x);

% Dimensions of remaining folded lowpass subband
cm=m; cn=n;

% Check dimensions of input data
for iter=1:2,
    tmp=size(x,iter)/2^floor((J+2-iter)/2);
    if round(tmp)~=tmp,
        disp(' ')
        disp('The size of the input signal must be a sufficient power of two!')
        disp(' ')
        y2=[];
        return;
    end;
end;

% Analysis filters:
%  H1,   G1   : filters for iterations with mod(j,2)=1
%  H1D,  G1D  : filters for iterations with mod(j,2)=0
% (premultiply analysis filters by the downsampling factor; i.e., det(D)=2)
H1=FA(:,:,1)/2;
G1=FA(:,:,2)/2;
H1D=FA(:,:,3)/2;
G1D=FA(:,:,4)/2;

% Compute the FFT of the input data
X=fftn(x); clear x;

% Initialize cube for folded wavelet coefficients
y2=zeros(cm,cn);

for j=1:J,

    mj=mod(j,2);

    % Select filter
    switch mj,
        case 1,
            H=H1;
            G=G1;
        case 0,
            H=H1D;
            G=G1D;
    end;

    % Filtering
    Y1=H(1:size(X,1),1:size(X,2)).*X;
    Y2=G(1:size(X,1),1:size(X,2)).*X;

    % Downsampling & upsampling
    switch mj,
        case 1,
            if j~=J,
                % This operates like: Y1=Y1+fftshift(Y1); Y1=Y1(1:cm,1:cn/2);
                Y1(1:cm/2,1:cn/2)=Y1(1:cm/2,1:cn/2)+Y1(cm/2+1:cm,cn/2+1:cn);
                Y1(cm/2+1:cm,1:cn/2)=Y1(cm/2+1:cm,1:cn/2)+Y1(1:cm/2,cn/2+1:cn);
                Y1=Y1(1:cm,1:cn/2);
            else
                Y1=Y1+fftshift(Y1);
            end;
            Y2=Y2 + fftshift(Y2);
            %! y2(1:cm,cn/2+1:cn)=fold2D(real(ifftn(Y2)),mj,m,n);
            y2(1:cm,cn/2+1:cn)=fold2D((ifftn(Y2)),mj,m,n);
            cn=cn/2;
        case 0,
            m2=m/2;n2=n/2;
            Y1=Y1(1:m2,1:n2)+Y1(m2+1:2*m2,1:n2);
            Y2=Y2(1:m2,1:n2)+Y2(m2+1:2*m2,1:n2);
            y2(cm/2+1:cm,1:cn)=real(ifftn(Y2));
            cm=cm/2;

            % Preparing filters for next three iterations
            lm=1:2:m; ln=1:2:n;
            H1=H1(lm,ln);
            G1=G1(lm,ln);
            H1D=H1D(lm,ln);
            G1D=G1D(lm,ln);
            m=m2; n=n2;
    end;

    X=Y1;
end;

% Insert folded lowpass subband
y2(1:cm,1:cn)=fold2D(real(ifftn(Y1)),mj,m,n);
return;


% ----------------------------------------------------------------------
% Fold 2D subband
% ----------------------------------------------------------------------
function f=fold2D(u,j,m,n)
switch j,
    case 0,
        f=u;
    case 1,
        f=u(:,1:2:n)+u(:,2:2:n);
end;


function x=FFTquin2D_synthesis(y2,J,FS);

% FFTQUIN2D_SYNTHESIS Perform 2D quincunx wavelet synthesis
% 	x = FFTquin2D_synthesis(y2,J,FS)
%
% 	Input:
%       y2 = data (folded)
%       J = number of interations
%       FS = synthesis filters
%
%       Output:
%       x = result (unfolded)
%
% Dimitri Van De Ville
%      Biomedical Imaging Group, BIO-E/STI
%      Swiss Federal Institute of Technology Lausanne
%      CH-1015 Lausanne EPFL, Switzerland

% Dimensions of input data
[m,n]=size(y2);

% Synthesis filters:
%  H1,   G1   : filters for iterations with mod(j,2)=1
%  H1D,  G1D  : filters for iterations with mod(j,2)=0
H1=FS(:,:,1);
G1=FS(:,:,2);
H1D=FS(:,:,3);
G1D=FS(:,:,4);

% How many "double-iterations"?
l=2^((J-mod(J,2))/2);
M=m/l; N=n/l;

% Dimensions of full data
[M0,N0,P0]=size(H1);

% Dimensions of folded lowpass subband
cm=M0; cn=N0;
cn=cn/2^floor((J+1)/2);
cm=cm/2^floor((J)/2);

% Extract folded lowpass subband and unfold
y1=y2(1:cm,1:cn);
y1=unfold2D(y1,mod(J,2),M,N);
Y1=fftn(y1); clear y1;

j=J;
while j>0;
    mj=mod(j,2);

    % unfold highpass subband and select filters
    switch mj,
        case 1,
            f=unfold2D(y2(1:M,N/2+1:N),mj,M,N);
            H=H1(1:l:M0,1:l:N0);
            G=G1(1:l:M0,1:l:N0);
        case 0,
            f=unfold2D(y2(M+1:2*M,1:N),mj,M,N);
            l=l/2;
            Y1=[Y1 Y1;Y1 Y1];
            H=H1D(1:l:M0,1:l:N0);
            G=G1D(1:l:M0,1:l:N0);
    end;

    Y2=fftn(f); clear f;
    if mj==0,
        Y2=[Y2 Y2;Y2 Y2];
        M=2*M; N=2*N;
    end;

    % filter data
    Y1=Y1.*H + Y2.*G;

    j=j-1;
end;
x=real(ifftn(Y1));
return;

% ----------------------------------------------------------------------
% Unfold 2D subband
% ----------------------------------------------------------------------
function u=unfold2D(y,j,M,N)
switch j,
    case 0,
        u=y;
    case 1,
        u=zeros(M,N);
        u(1:2:M,1:2:N)=y(1:2:M,:);
        u(2:2:M,2:2:N)=y(2:2:M,:);
end;
return;


function [FA,FS]=FFTquincunxfilter2D(dim,alpha,type);

% FFTQUINCUNXFILTER2D Supplies filters for the 2D quincunx transform.
% 	[FFTanalysisfilters,FFTsynthesisfilters]=FFTquincunxfilter2D(dim,alpha,type)
% 	computes the frequency response of low- and high-pass filters.
%
% 	Input:
% 	dim = dimensions of the input signal
% 	alpha = degree of the filters, any real number >=0
%   type =
%     class I: McClellan-based filters
%       o = orthogonal; b = discrete linear B-spline (synthesis); d = dual
%     class II: Polyharmonic B-spline wavelets (Rabut-style localization)
%       Po = orthogonal; Pb = B-spline; Pd = dual
%     class III: Polyharmonic B-spline wavelets (isotropic-style
%                localization)
%       PO = orthogonal {=Po}; PB = B-spline; PD = dual
%
% Dimitri Van De Ville
%      Biomedical Imaging Group, BIO-E/STI
%      Swiss Federal Institute of Technology Lausanne
%      CH-1015 Lausanne EPFL, Switzerland

m=dim(1);
n=dim(2);

gamma=alpha+2;

% Setup downsampling matrix
D=[1 1; 1 -1]';

% Coordinates in the Fourier domain
[xo,yo]=ndgrid(2*pi*([1:m]-1)/m,2*pi*([1:n]-1)/n);

for iter=0:1,

    if iter==0, % First filter: no downsampling
        x=xo;
        y=yo;
    end;
    if iter>0,  % Coordinates after downsampling
        x=D(1,1)*xo+D(1,2)*yo;
        y=D(2,1)*xo+D(2,2)*yo;
        % D=D*D;    % prepare filter for next iteration
    end;

    if lower(type(1)) == 'p', % Isotropic polyharmonic splines

        if iter==0,
            [ac,acD,loc,B] = FFTquincunxpolyfilter(x,y,gamma,type(2));
        else
            %ac = fftshift(interp2(xo,yo,ac,mod(x,2*pi),mod(y,2*pi),'*nearest'),1);
            %acD= fftshift(interp2(xo,yo,acD,mod(x,2*pi),mod(y,2*pi),'*nearest'));
            %loc= fftshift(interp2(xo,yo,loc,mod(x,2*pi),mod(y,2*pi),'*nearest'),1);
            %B  = fftshift(interp2(xo,yo,B,mod(x,2*pi),mod(y,2*pi),'*nearest'),1);
            ac = interp2(xo,yo,ac0,mod(x,2*pi),mod(y,2*pi),'*nearest');
            acD= interp2(xo,yo,acD0,mod(x,2*pi),mod(y,2*pi),'*nearest');
            loc= interp2(xo,yo,loc0,mod(x,2*pi),mod(y,2*pi),'*nearest');
            B  = interp2(xo,yo,B0,mod(x,2*pi),mod(y,2*pi),'*nearest');
            %[ac,acD,loc,B] = FFTquincunxpolyfilter(x,y,gamma,type(2));
        end;
        ortho = acD./ac;

    else

        [ortho,B] = FFTquincunxmcclellan(x,y,alpha);

    end;

    % Lowpass filter
    [H,H1] = FFTquincunxfilter2D_lowpass(x,y,type,B,ortho);

    % Reversed filter
    B0 = B;
    if iter==0,
        B=fftshift(B); ortho=fftshift(ortho);
    else
        B=fftshift(B,1); ortho=fftshift(ortho,1);
    end;

    if lower(type(1)) == 'p',
        ac0=ac; acD0=acD; loc0=loc;
        if iter==0,
            ac=fftshift(ac);
            acD=fftshift(acD);
            loc=fftshift(loc);
        else
            ac=fftshift(ac,1);
            acD=fftshift(acD);
            loc=fftshift(loc,1);
        end;
    else
        ac=0; ac0=0; acD=0; acD0=0; loc=0; loc0=0;
    end;

    [Hd,H1d] = FFTquincunxfilter2D_highpass(x-pi,y-pi,type,B,ortho,ac,ac0,acD,acD0,loc,loc0);

    % Highpass filters: modulation
    G  = exp(i*x).*H1d;
    G1 = exp(-i*x).*Hd;

    % Fill up array with analysis and synthesis filters
    FA(:,:,iter*2+1) = H1;
    FA(:,:,iter*2+2) = G1;
    FS(:,:,iter*2+1) = H;
    FS(:,:,iter*2+2) = G;
end;



function [H,H1]=FFTquincunxfilter2D_highpass(x,y,type,B,ortho,ac,ac0,acD,acD0,loc,loc0);

% FFTQUINCUNXFILTER2D_HIGHPASS Supplies highpass filters for 2D quincunx transform.
% 	[Hsynthesis,Hanalysis]=FFTquincunxfilter2D_highpass(x,y,alpha,type)
% 	computes the frequency response of highpass filters.
%
% 	Input:
% 	x,y = coordinates in the frequency domain
% 	alpha = degree of the filters, any real number >=0
%       type = type of filter (ortho, dual, bspline)
%
% Dimitri Van De Ville
%      Biomedical Imaging Group, BIO-E/STI
%      Swiss Federal Institute of Technology Lausanne
%      CH-1015 Lausanne EPFL, Switzerland


if lower(type(1))=='p', % Polyharmonic splines

    type = [ type(2:length(type)) ];

    switch lower(type(1)),

        % Orthogonal filters
        case 'o',
            H = B*sqrt(2) ./ sqrt(ortho);
            H1  = conj(H);

            % Dual filters (B-spline at the analysis side)
        case 'd',
            H = sqrt(2)*conj(B).*ac;
            H1  = sqrt(2)*B./acD;

            % B-spline filters (B-spline at the synthesis side)
        case 'b',
            H1 = sqrt(2)*conj(B).*ac;
            H  = sqrt(2)*B./acD;

        case 'i',
            H = sqrt(2)*loc0./ac0;
            H1 = sqrt(2)*(B.^2).*ac./acD.*ac0./loc0;
            H1(find(isinf(H1)))=0;

    end;

else  % Simple fractional iterate with McClellan transform
    [H,H1]=FFTquincunxfilter2D_lowpass(x,y,type,B,ortho);
end;



function [H,H1]=FFTquincunxfilter2D_lowpass(x,y,type,B,ortho);

% FFTQUINCUNXFILTER2D_LOWPASS Supplies lowpass filters for 2D quincunx transform.
% 	[Hsynthesis,Hanalysis]=FFTquincunxfilter2D_lowpass(x,y,alpha,type)
% 	computes the frequency response of lowpass filters.
%
% 	Input:
% 	x,y = coordinates in the frequency domain
% 	alpha = degree of the filters, any real number >=0
%       type = type of filter (ortho, dual, bspline)
%
% Dimitri Van De Ville
%      Biomedical Imaging Group, BIO-E/STI
%      Swiss Federal Institute of Technology Lausanne
%      CH-1015 Lausanne EPFL, Switzerland

H=B;

if lower(type(1)) == 'p',
    type = [ type(2:length(type)) ];
end;

switch lower(type(1)),

    % Orthogonal filters
    case 'o',
        H = H*sqrt(2) ./ sqrt(ortho);
        H1  = conj(H);

        % Dual filters (B-spline at the analysis side)
    case 'd',
        H1 = sqrt(2)*conj(H);
        H = conj(H1./(ortho));

        % B-spline filters (B-spline at the synthesis side)
    case 'b',
        H = sqrt(2)*H;
        H1 = conj(H./(ortho));

        % Isotropic wavelet filter
    case 'i',
        H1 = sqrt(2)*conj(H);
        H = conj(H1./(ortho));

end;

function [ortho,H] = FFTquincunxmcclellan(x,y,alpha)

% FFTQUINCUNXMCCLELLAN Supplies orthonormalizing part of the 2D McClellan
%       filters for 2D quincunx transform.
%
% 	v=FFTquincunmcclellan(x,y,alpha)
%
% 	Input:
% 	x,y = coordinates in the frequency domain
% 	alpha = degree of the filters, any real number >=1
%
% Dimitri Van De Ville
%      Biomedical Imaging Group, BIO-E/STI
%      Swiss Federal Institute of Technology Lausanne
%      CH-1015 Lausanne EPFL, Switzerland


% McClellan transform filters
H  = (2*ones(size(x)) + (cos(x) + cos(y))).^((alpha+1)/2);
H  = H/4^((alpha+1)/2);
Hc = (2*ones(size(x)) - (cos(x) + cos(y))).^((alpha+1)/2);
Hc = Hc/4^((alpha+1)/2);

% Orthonormalizing denominator (l_2 dual)
ortho = H.*conj(H) + Hc.*conj(Hc);

function [ac,acD,loc,B] = FFTquincunxpolyfilter(x,y,gamma,type)

% FFTQUINCUNXPOLYFILTER Supplies orthonormalizing part of the 2D polyharmonic
%       spline filters for 2D quincunx transform.
%
% 	v=FFTquincunxpolyfilter(x,y,gamma,type)
%
% 	Input:
% 	x,y = coordinates in the frequency domain
% 	gamma = order of the filters, any real number >=0
%
% Dimitri Van De Ville
%      Biomedical Imaging Group, BIO-E/STI
%      Swiss Federal Institute of Technology Lausanne
%      CH-1015 Lausanne EPFL, Switzerland


% Get dimensions
[m n]=size(x);
m=2*m; n=2*n;

% Construct fine grid [0,2pi[ x [0,2pi[
[xo,yo]=ndgrid(2*pi*([1:m]-1)/m,2*pi*([1:n]-1)/n);

warning off MATLAB:divideByZero;

% Refinement filter for [2 0; 0 2]
if upper(type(1)) == type(1),
    loc = 8/3*(sin(xo/2).^2+sin(yo/2).^2)+2/3*(sin((xo+yo)/2).^2+sin((xo-yo)/2).^2);
    H  = 2^(-gamma)*((8/3*(sin(xo).^2+sin(yo).^2)+2/3*(sin(xo+yo).^2+sin(xo-yo).^2))./loc).^(gamma/2);
else
    loc = sin(xo/2).^2+sin(yo/2).^2;
    H  = 2^(-gamma)*((sin(xo).^2+sin(yo).^2)./loc).^(gamma/2);
end;
H(find(isnan(H))) = 1;

% Autocorrelation function
ac = autocorr2d(H.^2);

% Construct fine grid [0,2pi] x [0,2pi]
[xo2,yo2]=ndgrid(2*pi*([1:m/2+1]-1)/(m/2),2*pi*([1:n/2+1]-1)/(n/2));

% Extend autocorrelation function
ac(m/2+1,:)=ac(1,:);
ac(:,n/2+1)=ac(:,1);

% Compute autocorrelation function on subsampled grid; D=[1 1; 1 -1]
x2=mod(xo2+yo2,2*pi);
y2=mod(xo2-yo2,2*pi);

% Compute values on grid (x,y)
%------------------------------
% Autocorrelation filter
acD= interp2(xo2,yo2,ac,mod(x+y,2*pi),mod(x-y,2*pi),'*nearest');
ac = interp2(xo2,yo2,ac,mod(x,2*pi),mod(y,2*pi),'*nearest');

% Localization operator
loc = interp2(xo,yo,loc,mod(x,2*pi),mod(y,2*pi),'*nearest');
loc = loc.^(gamma/2);

% Scaling filter for quincunx lattice
if upper(type(1)) == type(1),
    B = 2^(-gamma/2)*((8/3*(sin((x+y)/2).^2+sin((x-y)/2).^2)+2/3*(sin(x).^2+sin(y).^2))./(8/3*(sin(x/2).^2+sin(y/2).^2)+2/3*(sin((x+y)/2).^2+sin((x-y)/2).^2))).^(gamma/2);
else
    B = 2^(-gamma/2)*((sin((x+y)/2).^2+sin((x-y)/2).^2)./(sin(x/2).^2+sin(y/2).^2)).^(gamma/2);
end;
B(find(isnan(B))) = 1;

function [v,fv] = poly(alpha,type)

% POLY - compute the polyharmonic B-spline
%
% 	Input:
% 	alpha = degree of the polyharmonic spline
%       type = type of B-spline (b,d,o,B,D,O)
%
% Dimitri Van De Ville
%      Biomedical Imaging Group, BIO-E/STI
%      Swiss Federal Institute of Technology Lausanne
%      CH-1015 Lausanne EPFL, Switzerland


warning off MATLAB:divideByZero;

N=16; % spatial support: [-N/4:N/4[
Z=16; % spatial zoom factor
%N=64;
%Z=2;

step=2*pi/N;
[x,y]=meshgrid(-Z*pi:step:Z*pi-step);
w1=x; w2=y;

% compute frequency response
gamma=alpha+2;

x = x/2; y = y/2;
loc = sin(x).^2+sin(y).^2;

% alternative localization
if upper(type(1)) == type(1),
    loc = ( 8/3*loc + 2/3*(sin(x+y).^2+sin(x-y).^2) ) / 4;
end;

pow=(x.^2+y.^2);

loc=loc.^(gamma/2);
pow=pow.^(gamma/2);

fv  = ( loc ./ pow );
fv(find(isnan(fv))) = 1;

% autocorrelation function
[xo,yo]=meshgrid(0:step/2:2*pi-step/2);

% refinement filter for [2 0; 0 2]
if upper(type(1)) == type(1),
    H  = 2^(-gamma)*((8/3*(sin(xo).^2+sin(yo).^2)+2/3*(sin(xo+yo).^2+sin(xo-yo).^2))./(8/3*(sin(xo/2).^2+sin(yo/2).^2)+2/3*(sin((xo+yo)/2).^2+sin((xo-yo)/2).^2))).^(gamma/2);
else
    H  = 2^(-gamma)*((sin(xo).^2+sin(yo).^2)./(sin(xo/2).^2+sin(yo/2).^2)).^(gamma/2);
end;
H(find(isnan(H))) = 1;

% autocorrelation function
ac0 = autocorr2d(H.^2);

sx = size(ac0,1); sy = size(ac0,2);
ac = zeros(size(fv));
for iterx=1:Z,
    for itery=1:Z,
        bx=(iterx-1)*sx+1;
        by=(itery-1)*sy+1;
        ac(bx:bx+sx-1,by:by+sy-1)=ac0;
    end;
end;
ac = fftshift(ac);

if lower(type(1)) == 'o',
    fv = fv ./ sqrt(ac);
end;

if lower(type(1)) == 'd',
    fv = fv ./ ac;
end;

% compute spatial version
fv = ifftshift(fv);              % shift to [0:2pi[
v = real((ifft2(fv)))*Z^2;       % compensate for zooming

% only keep the half [-N/4:N/4[ instead of [-N/2:N/2[ (to avoid aliasing)
[x,y]=meshgrid(-N/4:1/Z:N/4-1/Z);
v=fftshift(v);
v=v((N*Z)/4:(N*Z)*3/4-1,(N*Z)/4:(N*Z)*3/4-1);
v=ifftshift(v);

% optional: normalize energy (for movies)
if length(type)>1 & type(2) == 'n',
    s=sum(v(:).^2)/(Z*Z);
    v=v*sqrt(1/s);
end;

% surface plot with lighting
surfl(x,y,fftshift(v)); shading flat; view(-26,44);
xlabel('x_1');
ylabel('x_2');

function [v,fv] = polyw(alpha,type)

% POLYW - polyharmonic B-spline wavelet
%
% 	Input:
%
%       type
%         lowercase - Rabut style
%         uppercase - isotropic brand
%
% 	alpha = degree of the polyharmonic spline
%
% Dimitri Van De Ville
%      Biomedical Imaging Group, BIO-E/STI
%      Swiss Federal Institute of Technology Lausanne
%      CH-1015 Lausanne EPFL, Switzerland


gamma=alpha+2;

warning off MATLAB:divideByZero;

N=16;
Z=16;
step=2*pi/N;
[w1,w2]=meshgrid(-Z*pi:step:Z*pi-step);

% downsampled grid
w1D=(w1+w2)/2;
w2D=(w1-w2)/2;

% scaling function
w1D  = w1D/2; w2D = w2D/2;

loc  = 4*sin(w1D).^2+4*sin(w2D).^2;

if upper(type(1)) == type(1),
    loc = loc - 8/3*sin(w1D).^2.*sin(w2D).^2;
end;

pow = (2*w1D).^2+(2*w2D).^2;

loc=loc.^(gamma/2);
pow=pow.^(gamma/2);

fv1  = loc ./  pow;
fv1(find(isnan(fv1))) = 1;
w1D  = 2*w1D; w2D = 2*w2D;

% autocorrelation function
[w1o,w2o]=meshgrid(0:step/4:2*pi-step/4);

% refinement filter for [2 0; 0 2]
if upper(type(1)) == type(1),
    H  = 2^(-gamma)*((8/3*(sin(w1o).^2+sin(w2o).^2)+2/3*(sin(w1o+w2o).^2+sin(w1o-w2o).^2))./(8/3*(sin(w1o/2).^2+sin(w2o/2).^2)+2/3*(sin((w1o+w2o)/2).^2+sin((w1o-w2o)/2).^2))).^(gamma/2);
else
    H  = 2^(-gamma)*((sin(w1o).^2+sin(w2o).^2)./(sin(w1o/2).^2+sin(w2o/2).^2)).^(gamma/2);
end;
H(find(isnan(H))) = 1;

% autocorrelation function
ac0 = autocorr2d(H.^2);
ac0(size(ac0,1)+1,:)=ac0(1,:);
ac0(:,size(ac0,2)+1)=ac0(:,1);

[w1o,w2o]=meshgrid(0:step/2:2*pi);
ac = interp2(w1o,w2o,ac0,mod(w1D,2*pi),mod(w2D,2*pi),'*linear');

if lower(type(1)) == 'o' || lower(type(1)) == 'j',
    fv1 = fv1 ./ sqrt(ac);
end;
if lower(type(1)) == 'd',
    fv1 = fv1 ./ ac;
end;

% wavelet filter
w1D = -w1D-pi; w2D = -w2D-pi;

acD = interp2(w1o,w2o,ac0,mod(w1D,2*pi),mod(w2D,2*pi),'*linear');

w1D = w1D/2;  w2D = w2D/2;

% Quincunx scaling filter
if upper(type(1)) == type(1),
    t1 = 8/3*(sin(w1D+w2D).^2 + sin(w1D-w2D).^2) + 2/3*(sin(2*w1D).^2 + sin(2*w2D).^2);
    t2 = 8/3*(sin(w1D).^2 + sin(w2D).^2) + 2/3*(sin(w1D+w2D).^2 + sin(w1D-w2D).^2);
else
    t1 = sin(w1D+w2D).^2 + sin(w1D-w2D).^2;
    t2 = sin(w1D).^2 + sin(w2D).^2;
end;

% Dyadic scaling filter
if length(type)>1 & type(2)=='D',
    t1 = sin(2*w1D).^2 + sin(2*w2D).^2;
    t2 = sin(w1D).^2 + sin(w2D).^2;
end;

t=( 0.5 * t1./t2 ).^(gamma/2);
fv2 = conj(t);
fv2(find(isnan(fv2))) = 1;
w1D = 2*w1D; w2D = 2*w2D;
w1D = -w1D-pi; w2D = -w2D-pi;

if lower(type(1)) == 'i',
    fv2 = loc;
end;
if lower(type(1)) == 'j',
    fv2 = loc;
    %  fv2(find(isinf(abs(fv2)))) = 0;
end;

% shift
fv2 = fv2 .* exp(-i*w1D);

acD2 = interp2(w1o,w2o,ac0,mod(w1,2*pi),mod(w2,2*pi),'*linear');

if lower(type(1)) == 'o',
    fv3 = sqrt(acD./acD2);
end;
if lower(type(1)) == 'b',
    fv3 = acD;
end;
if lower(type(1)) == 'd',
    fv3 = 1./acD2;
end;
if lower(type(1)) == 'i',
    fv3 = 1./ac;
end;

% scale relation
fv = 2^(gamma/2-1)*fv1.*fv2.*fv3;
%fv=fv1;
fv = ifftshift(fv);

% compute spatial version
v = ifft2(fv)*Z^2;

[x1,x2]=meshgrid(-N/4:1/Z:N/4-1/Z);
v=fftshift(v);
v=v((N*Z)/4:(N*Z)*3/4-1,(N*Z)/4:(N*Z)*3/4-1);
v=ifftshift(v);

surfl(x1,x2,fftshift(real(v))); shading flat; view(-26,44);
xlabel('x_1');
ylabel('x_2');

Contact us at files@mathworks.com