Files
2026-08-07 15:56:42 +09:00

364 lines
13 KiB
Matlab
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
function [img1_aligned, img2_aligned, delta_all] = fun_align_img(img1,img2,asize,pix)
% [resolution] = aligned_FSC(file1,file2,params)
%
% Receives two filenames with path for ptychography reconstructions and a
% structure with parameters. The routine reads the reconstructions, matches
% the linear phase between them, registers the images, and returns the
% resolution estimates based on first and last crossing of the FSC with the
% threshold.
%
% References relevant to this code:
% For using this FSC code with ptychography: J. Vila-Comamala, et al., "Characterization of high-resolution diffractive X-ray optics by ptychographic coherent diffractive imaging," Opt. Express 19, 21333-21344 (2011).
% For subpixel alignment: M. Guizar-Sicairos, et al., "Efficient subpixel image registration algorithms," Opt. Lett. 33, 156 (2008).
% For matching of phase ramp by approximate least squared error: M. Guizar-Sicairos, et al., "Phase tomography from x-ray coherent diffractive imaging projections," Opt. Express 19, 21345-21357 (2011).
%
% Outputs:
%
% resolution A two element variable that contains the resolution
% obtained from first and last crossing of the FSC curve with
% the threshold curve.
%
% Inputs:
%
% file1 Filename with path of reconstruction 1
% file2 Filename with path of reconstruction 2
% params Structure with parameters as described below
%
% params.flipped_images Flip one input image horizontally (= true or false).
% Useful when comparing 0 and 180 degree projections
% in tomography (default = false).
% params.crop = ''; for using the default half size of the probe
% = 'manual' for using GUI to select region. This will display the range, e.g. {600:800, 600:800}
% = {600:800, 600:800} for custom vertical and horizontal cropping, respectively
% params.GUIguess To click for an initial alignment guess, if used it ignores
% the values of params.guessx and params.guessy (default
% = false)
% params.guessx
% params.guessy An intial guess for x and y alignment (default = [])
% params.remove_ramp Try to remove linear phase from whole image before initial
% alignment (default = true)
% params.image_prop = 'complex'
% = 'phasor' (phase with unit amplitude, default)
% = 'phase' (Note: phase should not be used if there is phase wrapping)
% params.taper = 20 (default) Pixels to taper images - Increase until the FSC does not change anymore
% params.plotting Display plots (default = false)
% params.dispfsc Display FSC plot (default = true)
% params.SNRt SNR for FSC threshold curve
% SNRt = 0.2071 for 1/2 bit threshold for resolution of the average of the 2 images
% SNRt = 0.5 for 1 bit threshold for resolution of each individual image (default)
% params.thickring Thickness of Fourier domain ring for FSC in pixels (default = 1)
% params.freq_thr To ignore the crossings before freq_thr for determining resolution (default 0.02)
% params.out_fn Filename of output of jpeg for FSC
%*-----------------------------------------------------------------------*
%|                                                                       |
%|  Except where otherwise noted, this work is licensed under a          |
%|  Creative Commons Attribution-NonCommercial-ShareAlike 4.0            |
%|  International (CC BY-NC-SA 4.0) license.                             |
%|                                                                       |
%|  Copyright (c) 2017 by Paul Scherrer Institute (http://www.psi.ch)    |
%|                                                                       |
%|      Authors: CXS group
%|                                                                       |
%*-----------------------------------------------------------------------*
%
% You may use this code with the following provisions:
%
% If this code, or subfunctions or parts of it, is used for research in a
%   publication or if it is fully or partially rewritten for another
%   computing language the authors and institution should be acknowledged
%   in written form and additionally you should cite the references relevant
% to this code.
%
% A publication that focuses on describing features, or parameters, that
%    are already existing in the code should be first discussed with the
%    authors.
%   
% This code and subroutines are part of a continuous development, they
%    are provided “as they are” without guarantees or liability on part
%    of PSI or the authors. It is the user responsibility to ensure its
%    proper use and the correctness of the results.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Checks and defaults %%%
flag_imread = 1;
GUIguess = false;
plotting = false;
crop = '';
guessx = [];
guessy = [];
remove_ramp = false;
image_prop = 'complex';
taper = 20;
dispfsc = true;
SNRt = 0.5;
thickring = 5;
freq_thr = 0.02;
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
img1_orig = img1;
img2_orig = img2;
screensize = get( 0, 'Screensize' );
% Show phase images (not cropped)%
if plotting
figure(2)
set(gcf,'Outerposition',[1 screensize(4)-550 500 500]) %[left, bottom, width, height
if ~flag_imread
imagesc(angle(img1));
else
imagesc(img1);
end
axis xy equal tight
colormap bone
if ~flag_imread
aux = angle(img1); %angle(img1(round(asize(1)/2):end-round(asize(1)/2),round(asize(2)/2):end-round(asize(2)/2)));
else
aux = img1;
end
caxis([min(aux(:)) max(aux(:))]); colorbar
title(file{1},'interpreter','none')
figure(3)
if ~flag_imread
imagesc(angle(img2));
else
imagesc(img2);
end
axis xy equal tight
colormap bone
if ~flag_imread
aux = angle(img2); %angle(img2(round(asize(1)/2):end-round(asize(1)/2),round(asize(2)/2):end-round(asize(2)/2)));
else
aux = img2;
end
caxis([min(aux(:)) max(aux(:))]); colorbar
title(file{2},'interpreter','none')
set(gcf,'Outerposition',[500 screensize(4)-550 500 500]) %[left, bottom, width, height
end
% Crop images - default is half the size of the probe on each side plus
% whatever needed to make them of equal size
minsize1 = min(size(img1,1),size(img2,1));
minsize2 = min(size(img1,2),size(img2,2));
if isempty(crop)
crop = {round(asize(1)/2):minsize1-round(asize(1)/2), ...
round(asize(2)/2):minsize2-round(asize(1)/2)};
elseif strcmpi(crop, 'manual')
figure()
imagesc(angle(img1))
colormap bone
axis image xy
title('Select compared region')
rect = round(getrect);
crop = {rect(2)+(1:rect(4)),rect(1)+(1:rect(3))};
disp('===========================')
fprintf('Selected region: {%i:%i,%i:%i}\n',rect(2), rect(2)+rect(4), rect(1), rect(1)+rect(3));
disp('===========================')
pause(1)
end
img1 = img1(crop{:});
img2 = img2(crop{:});
if GUIguess
figure(2)
disp(['Click on a feature on figure 2'])
[xin yin] = ginput(1);
figure(3)
disp(['Click on a feature on figure 3'])
[xin2 yin2] = ginput(1);
guessx = round(xin-xin2);
guessy = round(yin-yin2);
end
if ~isempty(guessx)
switch sign(guessx)
case 1
img1 = img1(:,1+guessx:end);
img2 = img2(:,1:end-guessx);
case -1
img1 = img1(:,1:end+guessx);
img2 = img2(:,1-guessx:end);
end
end
if ~isempty(guessy)
switch sign(guessy)
case 1
img1 = img1(1+guessy:end,:);
img2 = img2(1:end-guessy,:);
case -1
img1 = img1(1:end+guessy,:);
img2 = img2(1-guessy:end,:);
end
end
% Remove ramp
if remove_ramp
disp('Removing ramp for initial alignment')
img1 = remove_linearphase_v2(img1,ones(size(img1)),100);
img2 = remove_linearphase_v2(img2,ones(size(img2)),100);
end
if plotting
figure(4)
set(gcf,'Outerposition',[1 1 500 476]) %[left, bottom, width, height
if ~flag_imread
imagesc(angle(img1));
else
imagesc(img1);
end
axis xy equal tight
colormap bone; colorbar
title(file{1},'interpreter','none')
figure(5)
if ~flag_imread
imagesc(angle(img2));
else
imagesc(img2);
end
axis xy equal tight
colormap bone; colorbar
title(file{2},'interpreter','none')
set(gcf,'Outerposition',[500 1 500 476]) %[left, bottom, width, height
end
%%% Initial alignment %%%
fprintf('\nInitial alignment\n')
if ~flag_imread
switch lower(image_prop)
case 'complex'
imgalign1 = img1;
imgalign2 = img2;
disp('Registering complex valued images')
case 'phasor'
imgalign1 = ones(size(img1)).*exp(1i*angle(img1));
imgalign2 = ones(size(img1)).*exp(1i*angle(img2));
disp('Registering phasor of complex valued images')
case 'phase'
imgalign1 = angle(img1);
imgalign2 = angle(img2);
disp('Registering phase of complex valued images')
end
else
imgalign1 = img1;
imgalign2 = img2;
end
upsamp = 100;
displ = 1;
W = 1;
x1 = [];%[1:150];
x2 = x1;
y1 = [];%[1:238];
y2 = y1;
% imgalign2 = shiftpp2(imgalign2,10,-10); % To test range adjustment
[subim1, subim2, delta, deltafine, regionsout] = registersubimages_2(imgalign1,imgalign2, x1, y1, x2, y2, upsamp, displ,1);
%%% Fine alignment (second round) %%%
% Remove ramp for fine alignment
disp('Removing ramp for fine alignment')
%%% A patch for deltafine large
if max(regionsout.y2+round(delta(1)))>size(img2,1)
warning('First subpixel registration refinement found large values')
regionsout.y2 = [min(regionsout.y2):size(img2,1)-round(delta(1))];
regionsout.y1 = regionsout.y2;
end
if max(regionsout.x2+round(delta(2)))>size(img2,2)
warning('First subpixel registration refinement found large values')
regionsout.x2 = [min(regionsout.x2):size(img2,2)-round(delta(2))];
regionsout.x1 = regionsout.x2;
end
%%%
subimg1 = img1(regionsout.y1,regionsout.x1);
subimg2 = img2(regionsout.y2+round(delta(1)),regionsout.x2+round(delta(2)));
if ~flag_imread
subimg1 = remove_linearphase_v2(subimg1,ones(size(subimg1)),100);
subimg2 = remove_linearphase_v2(subimg2,ones(size(subimg2)),100);
end
if ~flag_imread
switch lower(image_prop)
case 'complex'
subimgalign1 = subimg1;
subimgalign2 = subimg2;
disp('Registering complex valued images')
case 'phasor'
subimgalign1 = ones(size(subimg1)).*exp(1i*angle(subimg1));
subimgalign2 = ones(size(subimg1)).*exp(1i*angle(subimg2));
disp('Registering phasor of complex valued images')
case 'phase'
subimgalign1 = angle(subimg1);
subimgalign2 = angle(subimg2);
disp('Registering phase of complex valued images')
end
else
subimgalign1 = subimg1;
subimgalign2 = subimg2;
end
% Fine alignment %
disp(sprintf('\nFine alignment'))
[subim1, subim2, delta2, deltafine2, regionsout] = registersubimages_2(subimgalign1,subimgalign2, x1, y1, x2, y2, upsamp, displ,1);
%%% Tapering %%%
filterx = fract_hanning_pad(size(subim1,2),size(subim1,2),size(subim1,2)-2*taper);
filterx = fftshift(filterx(1,:));
filterx = repmat(filterx,[size(subim1,1) 1]);
filtery = fract_hanning_pad(size(subim1,1),size(subim1,1),size(subim1,1)-2*taper);
filtery = fftshift(filtery(:,1));
filtery = repmat(filtery,[1 size(subim1,2)]);
filterxy = filterx.*filtery;
% Taper subimages %
subim1 = subim1.*filterxy;% + (1-filterxy).*mean(subim1(:));
subim2 = subim2.*filterxy;% + (1-filterxy).*mean(subim2(:));
if plotting
figure(4)
set(gcf,'Outerposition',[1 1 500 476]) %[left, bottom, width, height
if strcmpi(image_prop,'phase') || flag_imread
imagesc(subim1);
else
imagesc(angle(subim1));
end
axis xy equal tight
colormap bone; colorbar
title(file{1},'interpreter','none')
figure(5)
if strcmpi(image_prop,'phase') || flag_imread
imagesc(real(subim2));
else
imagesc(angle(subim2));
end
axis xy equal tight
colormap bone; colorbar
title(file{2},'interpreter','none')
set(gcf,'Outerposition',[500 1 500 476]) %[left, bottom, width, height
end
%% Computing the FSC
param.st_title = sprintf('taper %d',taper);
param.pixel_size = pix;
[resolution FSC T freq] = fourier_shell_corr_3D_2(subim1,subim2, param);
if 0
img1_aligned = img1_orig;
img1_aligned(asize(1)/2:asize(1)/2+size(subim1,1)-1, asize(2)/2:asize(2)/2+size(subim1,2)-1) = subim1;
img2_aligned = img2_orig;
img2_aligned(asize(1)/2:asize(1)/2+size(subim2,1)-1, asize(2)/2:asize(2)/2+size(subim2,2)-1) = subim2;
else
img1_aligned = subim1;
img2_aligned = subim2;
end
delta_all = round(delta) + delta2;
return