%FILE: DigitalFilterDemo.m %Creates and tests a digital filter for converting % a cubic-phase PSF to a diffraction-limited PSF % %Create a digital representation of the cubic PSF: % (We really don't care what the underlying optics % are here -- the idea is to make a shape-changing filter) N = 101; %Size of array; rs = 25; %Size of digital filter (arbitrary) Psize = .5; %Relative size of pupil in the array (radius) x = linspace(-1,1,N); [X,Y] = meshgrid(x,x); R = sqrt(X.^2 + Y.^2); %R is now an array with values equal to the distance % from the center of the N x N array: %Create a circular, uniform pupil, filling 1/5 the array: P = zeros(N,N); P(R<=Psize) = 1; %Find the diffraction limited PSF and it's OTF: DFpsf = fftshift(fft2(ifftshift(P))); DFpsf = DFpsf.*conj(DFpsf); %Normalize the psf: DFpsf = DFpsf/sum(sum(DFpsf)); DFotf = fftshift(fft2(ifftshift(DFpsf))); %Normalize the OTF: DFotf = DFotf/max(max(abs(DFotf))); % figure(1) subplot(1,2,1) imagesc(DFpsf),axis image set(gca,'XTickLabel',[],'YTickLabel',[]) %mesh(DFpsf) colormap(gray) title('Diffraction-Limited PSF') subplot(1,2,2) imagesc(abs(DFotf)),axis image set(gca,'XTickLabel',[],'YTickLabel',[]) %mesh(abs(DFotf)); title('Diffraction-Limited MTF') % %Add cubic phase to the pupil: Ac = 2/(Psize^3); %Waves of cubic phase at edge of pupil C = Ac*(X.^3 + Y.^3); Pc = P.*exp(i*2*pi*C); Pc(R>Psize) = 0; %Clip amplitude and phase to actual pupil size. % %Find the PSF and OTF for the cubic-phase pupil: Cpsf = fftshift(fft2(ifftshift(Pc))); Cpsf = Cpsf.*conj(Cpsf); %Normalize the PSF: Cpsf = Cpsf/sum(sum(Cpsf)); Cotf = fftshift(fft2(ifftshift(Cpsf))); %Normalize Cotf: Cotf = Cotf/max(max(abs(Cotf))); % figure(2) subplot(1,2,1) imagesc(Cpsf),axis image set(gca,'XTickLabel',[],'YTickLabel',[]) %mesh(Cpsf) colormap(gray) title('Cubic-Phase PSF') subplot(1,2,2) imagesc(abs(Cotf)),axis image set(gca,'XTickLabel',[],'YTickLabel',[]) %mesh(abs(Cotf)); title('Cubic-Phase MTF') % %Make a digital filter to convert the Cubic PSF to a % diffraction-limited PSF. % %************Make Cubic Filter*********************** %Make Filter for Cubic PSF: %Calculate components for pseudo Weiner Filter: %NOTE: Cotf can be a weighted sum of OTFs if the filter has to % reconstruct a number of similar PSFs. H = conj(Cotf); Hsq = Cotf .* conj(Cotf); %Make Frequency Filter: (Note we are using the Diff-lim OTF % as a limiting bandwith.) W = DFotf; %Bandwidth limit of filter wp = 0.001; %"Weiner parameter" => avoids divide by zero F = (W .* H) ./ (Hsq + wp); %F is now the frequency domain filter: %Long Space Filter: %IMPORTANT NOTE: The frequency arrays, W,H,Hsq,& F are shifted so % that the DC component is in the center. This is fine for % display purposes, and even for the filter arithmetic above, % but it is NOT OK for the FFT function, which insists on having % the DC component at the start of the array. Hence you MUST % make sure the array is ordered that way before using any FFT % algorithm: F2 = fftshift(F); f = real(ifftshift(ifft2(F2))); %Adjust filter for unity gain: f_long = f/sum(sum(f)); lng = sum(sum(f.^2)); %Noise gain of long filter %Truncated Space Filter: E = (N-rs)*0.5; E1 = floor(E); E2 = ceil(E); rs = [E1:N-E2]; f_short =f(rs,rs); % %Display the filters: figure(3) subplot(1,2,1) mesh(f_long) colormap(gray) title('Full-Size Space Filter') subplot(1,2,2) mesh(f_short) title('Truncated Space Filter') % %Apply the filters to the cubic psf: f_l_psf = conv2(Cpsf,f_long,'same'); f_s_psf = conv2(Cpsf,f_short,'same'); % %Display the results: figure(4) subplot(1,2,1) imagesc(f_l_psf),axis image, colormap(gray) set(gca,'XTickLabel',[],'YTickLabel',[]) title('Filtered PSF (long filter') subplot(1,2,2) imagesc(f_s_psf),axis image set(gca,'XTickLabel',[],'YTickLabel',[]) title('Filtered PSF (short filter')