mirror of
https://github.com/c-sooyoung/fold_slice.git
synced 2026-09-17 19:39:08 +09:00
initial commit
This commit is contained in:
@@ -0,0 +1,223 @@
|
||||
function [output, Greg] = dftregistration(buf1ft,buf2ft,usfac)
|
||||
% function [output Greg] = dftregistration(buf1ft,buf2ft,usfac);
|
||||
% Efficient subpixel image registration by crosscorrelation. This code
|
||||
% gives the same precision as the FFT upsampled cross correlation in a
|
||||
% small fraction of the computation time and with reduced memory
|
||||
% requirements. It obtains an initial estimate of the crosscorrelation peak
|
||||
% by an FFT and then refines the shift estimation by upsampling the DFT
|
||||
% only in a small neighborhood of that estimate by means of a
|
||||
% matrix-multiply DFT. With this procedure all the image points are used to
|
||||
% compute the upsampled crosscorrelation.
|
||||
% Manuel Guizar - Dec 13, 2007
|
||||
%
|
||||
% Rewrote all code not authored by either Manuel Guizar or Jim Fienup
|
||||
% Manuel Guizar - May 13, 2016
|
||||
%
|
||||
% Citation for this algorithm:
|
||||
% Manuel Guizar-Sicairos, Samuel T. Thurman, and James R. Fienup,
|
||||
% "Efficient subpixel image registration algorithms," Opt. Lett. 33,
|
||||
% 156-158 (2008).
|
||||
%
|
||||
% Inputs
|
||||
% buf1ft Fourier transform of reference image,
|
||||
% DC in (1,1) [DO NOT FFTSHIFT]
|
||||
% buf2ft Fourier transform of image to register,
|
||||
% DC in (1,1) [DO NOT FFTSHIFT]
|
||||
% usfac Upsampling factor (integer). Images will be registered to
|
||||
% within 1/usfac of a pixel. For example usfac = 20 means the
|
||||
% images will be registered within 1/20 of a pixel. (default = 1)
|
||||
%
|
||||
% Outputs
|
||||
% output = [error,diffphase,net_row_shift,net_col_shift]
|
||||
% error Translation invariant normalized RMS error between f and g
|
||||
% diffphase Global phase difference between the two images (should be
|
||||
% zero if images are non-negative).
|
||||
% net_row_shift net_col_shift Pixel shifts between images
|
||||
% Greg (Optional) Fourier transform of registered version of buf2ft,
|
||||
% the global phase difference is compensated for.
|
||||
|
||||
% Copyright (c) 2016, Manuel Guizar Sicairos, James R. Fienup, University of Rochester
|
||||
% All rights reserved.
|
||||
%
|
||||
% Redistribution and use in source and binary forms, with or without
|
||||
% modification, are permitted provided that the following conditions are
|
||||
% met:
|
||||
%
|
||||
% * Redistributions of source code must retain the above copyright
|
||||
% notice, this list of conditions and the following disclaimer.
|
||||
% * Redistributions in binary form must reproduce the above copyright
|
||||
% notice, this list of conditions and the following disclaimer in
|
||||
% the documentation and/or other materials provided with the distribution
|
||||
% * Neither the name of the University of Rochester nor the names
|
||||
% of its contributors may be used to endorse or promote products derived
|
||||
% from this software without specific prior written permission.
|
||||
%
|
||||
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
% POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
if ~exist('usfac','var')
|
||||
usfac = 1;
|
||||
end
|
||||
|
||||
[nr,nc]=size(buf2ft);
|
||||
Nr = ifftshift(-fix(nr/2):ceil(nr/2)-1);
|
||||
Nc = ifftshift(-fix(nc/2):ceil(nc/2)-1);
|
||||
|
||||
if usfac == 0
|
||||
% Simple computation of error and phase difference without registration
|
||||
CCmax = sum(buf1ft(:).*conj(buf2ft(:)));
|
||||
row_shift = 0;
|
||||
col_shift = 0;
|
||||
elseif usfac == 1
|
||||
% Single pixel registration
|
||||
CC = ifft2(buf1ft.*conj(buf2ft));
|
||||
CCabs = abs(CC);
|
||||
[row_shift, col_shift] = find(CCabs == max(CCabs(:)));
|
||||
CCmax = CC(row_shift,col_shift)*nr*nc;
|
||||
% Now change shifts so that they represent relative shifts and not indices
|
||||
row_shift = Nr(row_shift);
|
||||
col_shift = Nc(col_shift);
|
||||
elseif usfac > 1
|
||||
% Start with usfac == 2
|
||||
CC = ifft2(FTpad(buf1ft.*conj(buf2ft),[2*nr,2*nc]));
|
||||
CCabs = abs(CC);
|
||||
[row_shift, col_shift] = find(CCabs == max(CCabs(:)),1,'first');
|
||||
CCmax = CC(row_shift,col_shift)*nr*nc;
|
||||
% Now change shifts so that they represent relative shifts and not indices
|
||||
Nr2 = ifftshift(-fix(nr):ceil(nr)-1);
|
||||
Nc2 = ifftshift(-fix(nc):ceil(nc)-1);
|
||||
row_shift = Nr2(row_shift)/2;
|
||||
col_shift = Nc2(col_shift)/2;
|
||||
% If upsampling > 2, then refine estimate with matrix multiply DFT
|
||||
if usfac > 2,
|
||||
%%% DFT computation %%%
|
||||
% Initial shift estimate in upsampled grid
|
||||
row_shift = round(row_shift*usfac)/usfac;
|
||||
col_shift = round(col_shift*usfac)/usfac;
|
||||
dftshift = fix(ceil(usfac*1.5)/2); %% Center of output array at dftshift+1
|
||||
% Matrix multiply DFT around the current shift estimate
|
||||
CC = conj(dftups(buf2ft.*conj(buf1ft),ceil(usfac*1.5),ceil(usfac*1.5),usfac,...
|
||||
dftshift-row_shift*usfac,dftshift-col_shift*usfac));
|
||||
% Locate maximum and map back to original pixel grid
|
||||
CCabs = abs(CC);
|
||||
[rloc, cloc] = find(CCabs == max(CCabs(:)),1,'first');
|
||||
CCmax = CC(rloc,cloc);
|
||||
rloc = rloc - dftshift - 1;
|
||||
cloc = cloc - dftshift - 1;
|
||||
row_shift = row_shift + rloc/usfac;
|
||||
col_shift = col_shift + cloc/usfac;
|
||||
end
|
||||
|
||||
% If its only one row or column the shift along that dimension has no
|
||||
% effect. Set to zero.
|
||||
if nr == 1,
|
||||
row_shift = 0;
|
||||
end
|
||||
if nc == 1,
|
||||
col_shift = 0;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
rg00 = sum(abs(buf1ft(:)).^2);
|
||||
rf00 = sum(abs(buf2ft(:)).^2);
|
||||
error = 1.0 - abs(CCmax).^2/(rg00*rf00);
|
||||
error = sqrt(abs(error));
|
||||
diffphase = angle(CCmax);
|
||||
|
||||
output=[error,diffphase,row_shift,col_shift];
|
||||
|
||||
% Compute registered version of buf2ft
|
||||
if (nargout > 1)&&(usfac > 0),
|
||||
[Nc,Nr] = meshgrid(Nc,Nr);
|
||||
Greg = buf2ft.*exp(1i*2*pi*(-row_shift*Nr/nr-col_shift*Nc/nc));
|
||||
Greg = Greg*exp(1i*diffphase);
|
||||
elseif (nargout > 1)&&(usfac == 0)
|
||||
Greg = buf2ft*exp(1i*diffphase);
|
||||
end
|
||||
return
|
||||
|
||||
function out=dftups(in,nor,noc,usfac,roff,coff)
|
||||
% function out=dftups(in,nor,noc,usfac,roff,coff);
|
||||
% Upsampled DFT by matrix multiplies, can compute an upsampled DFT in just
|
||||
% a small region.
|
||||
% usfac Upsampling factor (default usfac = 1)
|
||||
% [nor,noc] Number of pixels in the output upsampled DFT, in
|
||||
% units of upsampled pixels (default = size(in))
|
||||
% roff, coff Row and column offsets, allow to shift the output array to
|
||||
% a region of interest on the DFT (default = 0)
|
||||
% Recieves DC in upper left corner, image center must be in (1,1)
|
||||
% Manuel Guizar - Dec 13, 2007
|
||||
% Modified from dftus, by J.R. Fienup 7/31/06
|
||||
|
||||
% This code is intended to provide the same result as if the following
|
||||
% operations were performed
|
||||
% - Embed the array "in" in an array that is usfac times larger in each
|
||||
% dimension. ifftshift to bring the center of the image to (1,1).
|
||||
% - Take the FFT of the larger array
|
||||
% - Extract an [nor, noc] region of the result. Starting with the
|
||||
% [roff+1 coff+1] element.
|
||||
|
||||
% It achieves this result by computing the DFT in the output array without
|
||||
% the need to zeropad. Much faster and memory efficient than the
|
||||
% zero-padded FFT approach if [nor noc] are much smaller than [nr*usfac nc*usfac]
|
||||
|
||||
[nr,nc]=size(in);
|
||||
% Set defaults
|
||||
if exist('roff', 'var')~=1, roff=0; end
|
||||
if exist('coff', 'var')~=1, coff=0; end
|
||||
if exist('usfac','var')~=1, usfac=1; end
|
||||
if exist('noc', 'var')~=1, noc=nc; end
|
||||
if exist('nor', 'var')~=1, nor=nr; end
|
||||
% Compute kernels and obtain DFT by matrix products
|
||||
kernc=exp((-1i*2*pi/(nc*usfac))*( ifftshift(0:nc-1).' - floor(nc/2) )*( (0:noc-1) - coff ));
|
||||
kernr=exp((-1i*2*pi/(nr*usfac))*( (0:nor-1).' - roff )*( ifftshift([0:nr-1]) - floor(nr/2) ));
|
||||
out=kernr*in*kernc;
|
||||
return
|
||||
|
||||
|
||||
function [ imFTout ] = FTpad(imFT,outsize)
|
||||
% imFTout = FTpad(imFT,outsize)
|
||||
% Pads or crops the Fourier transform to the desired ouput size. Taking
|
||||
% care that the zero frequency is put in the correct place for the output
|
||||
% for subsequent FT or IFT. Can be used for Fourier transform based
|
||||
% interpolation, i.e. dirichlet kernel interpolation.
|
||||
%
|
||||
% Inputs
|
||||
% imFT - Input complex array with DC in [1,1]
|
||||
% outsize - Output size of array [ny nx]
|
||||
%
|
||||
% Outputs
|
||||
% imout - Output complex image with DC in [1,1]
|
||||
% Manuel Guizar - 2014.06.02
|
||||
|
||||
if ~ismatrix(imFT)
|
||||
error('Maximum number of array dimensions is 2')
|
||||
end
|
||||
Nout = outsize;
|
||||
Nin = size(imFT);
|
||||
imFT = fftshift(imFT);
|
||||
center = floor(size(imFT)/2)+1;
|
||||
|
||||
imFTout = zeros(outsize,'like', imFT);
|
||||
centerout = floor(size(imFTout)/2)+1;
|
||||
|
||||
% imout(centerout(1)+[1:Nin(1)]-center(1),centerout(2)+[1:Nin(2)]-center(2)) ...
|
||||
% = imFT;
|
||||
cenout_cen = centerout - center;
|
||||
imFTout(max(cenout_cen(1)+1,1):min(cenout_cen(1)+Nin(1),Nout(1)),max(cenout_cen(2)+1,1):min(cenout_cen(2)+Nin(2),Nout(2))) ...
|
||||
= imFT(max(-cenout_cen(1)+1,1):min(-cenout_cen(1)+Nout(1),Nin(1)),max(-cenout_cen(2)+1,1):min(-cenout_cen(2)+Nout(2),Nin(2)));
|
||||
|
||||
imFTout = ifftshift(imFTout)*Nout(1)*Nout(2)/(Nin(1)*Nin(2));
|
||||
return
|
||||
|
||||
|
||||
Reference in New Issue
Block a user