initial commit

This commit is contained in:
2026-08-07 15:56:42 +09:00
commit 91ad25aca9
1012 changed files with 159314 additions and 0 deletions
+364
View File
@@ -0,0 +1,364 @@
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