https://github.com/adwanner/XrayAssistedStaining
Raw File
Tip revision: 62c9930d08bbdd1602614d515cd20b1cb1f89d15 authored by adwanner on 28 June 2022, 20:18:37 UTC
pip install --user
Tip revision: 62c9930
fcn_calc_relative_offset.m
function [dY1,dX1,dY2,dX2,cmax,C]= fcn_calc_relative_offset(varargin)
%inputs: fcn_calc_relative_offset(image1,image2,CorrMethod,MaxOffset,CorrThres,CenterAsRef,NPeaks)
dY1=[];
dY2=[];
dX1=[];
dX2=[];
cmax=[];
C=[];
NargIn=numel(varargin);

CorrMethod='redxcorr2normimages';
MaxOffset=[];
CorrThres=[];
CenterAsRef=false;

if NargIn>=1
    if ~isnumeric(varargin{1})
        disp('Error: Input variable 1 has to be numeric.')
        return;
    end
end

if NargIn>=2
    if ~isnumeric(varargin{2})
        disp('Error: Input variable 2 has to be numeric.')
        return;
    end
end

if NargIn>=3
    if ischar(varargin{3})
        CorrMethod=varargin{3};
    else
        disp('Error: Input variable 3 has to be a string,')
        disp('corresponding to one of the available correlation')
        disp('methods:')
        disp('''redxcorr2normimages''')
        disp('''redxcorr2normgradimages''')
        return;
    end
end

if NargIn>=4
    if isnumeric(varargin{4})
        MaxOffset=varargin{4};
    else
        disp('Input variable 4 has to be numeric,')
        disp('corresponding to the maximal offset to consider.')
        disp('It is either a scalar or a 4 elements vector:')
        disp('maxOffset=[Top,Bottom,Left,Right];')
        return;
    end
end

if NargIn>=5
    if isnumeric(varargin{5}) && numel(varargin{5})==1
        CorrThres=varargin{5};
    else
        if ~isempty(varargin{5})
            disp('Input variable 5 has to be numeric scalar,')
            disp('corresponding to the correlation threshold to consider.')
            return;
        end
    end
end

if NargIn>=6
    if isnumeric(varargin{6})
        varargin{6}=logical(varargin{6});
    end
    if islogical(varargin{6}) && numel(varargin{6})==1
        CenterAsRef=varargin{6};
    else
        if ~isempty(varargin{6})
            disp('Input variable 6 has to be a logical scalar value,')
            disp('corresponding to wheter the center of the images should')
            disp('be used as reference for maximal offset.')
            return;
        end
    end
end

if NargIn>=7
    NPeaks=varargin{7};
else
    NPeaks=1;
end
if isempty(NPeaks)
    NPeaks=1;
end

%we want size(A)>=size(T)
if size(varargin{1},1)>size(varargin{2},1) || size(varargin{1},2)>size(varargin{2},2)
    is1greater2=1;
    A=varargin{1};
    T=varargin{2};
else
    is1greater2=0;
    A=varargin{2};    
    T=varargin{1};
end

if any([std(double(A(:))),std(double(T(:)))]==0)
    disp('Error: The values of input variable 1 and/ or 2 must not be')
    disp('all the same.')
    return;
end

clear varargin;
[THeight,TWidth,TNSlices]=size(T);
[AHeight,AWidth,ANSlices]=size(A);

if CenterAsRef
    CmaxHeight=2*floor(THeight/2)-floor((THeight-1)/2)+...
            floor((AHeight+1)/2)-1;
    CmaxWidth=2*floor(TWidth/2)-floor((TWidth-1)/2)+...
            floor((AWidth+1)/2)-1;
    switch numel(MaxOffset)
        case 0
            MaxOffset=[CmaxHeight,CmaxHeight,...
                CmaxWidth,CmaxWidth];
        case 1
            MaxOffset=[...
                min(MaxOffset,CmaxHeight),...
                min(MaxOffset,CmaxHeight),...
                min(MaxOffset,CmaxWidth),...
                min(MaxOffset,CmaxWidth)];
        case 2
            MaxOffset=[...
                min(MaxOffset(1),CmaxHeight),...
                min(MaxOffset(1),CmaxHeight),...
                min(MaxOffset(2),CmaxWidth),...
                min(MaxOffset(2),CmaxWidth)];
        case 4
            MaxOffset=[...
                min(MaxOffset(1),CmaxHeight),...
                min(MaxOffset(2),CmaxHeight),...
                min(MaxOffset(3),CmaxWidth),...
                min(MaxOffset(4),CmaxWidth)];
        otherwise
            disp('Error: The input for ''MaxOffset'' is not valid.')
            return;
    end
else
    switch numel(MaxOffset)
        case 0
            MaxOffset=[THeight,AHeight,...
                TWidth,AWidth];
        case 1
            MaxOffset=[...
                min(MaxOffset,THeight),...
                min(MaxOffset,AHeight),...
                min(MaxOffset,TWidth),...
                min(MaxOffset,AWidth)];
        case 2
            MaxOffset=[...
                min(MaxOffset(1),THeight),...
                min(MaxOffset(1),AHeight),...
                min(MaxOffset(2),TWidth),...
                min(MaxOffset(2),AWidth)];
        case 4
            MaxOffset=[...
                min(MaxOffset(1),THeight),...
                min(MaxOffset(2),AHeight),...
                min(MaxOffset(3),TWidth),...
                min(MaxOffset(4),AWidth)];
        otherwise
            disp('Error: The input for ''MaxOffset'' is not valid.')
            return;
    end
end
% fftsize(1) = FindClosestValidDimension(THeight+AHeight-1);
% fftsize(2) = FindClosestValidDimension(TWidth+AWidth-1);
fftsize(1)=2^nextpow2(THeight+AHeight-1);
fftsize(2)=2^nextpow2(TWidth +AWidth -1);

if CenterAsRef
    centerHeight=CmaxHeight+[-(MaxOffset(1)-1),(MaxOffset(2)-1)];
    centerWidth= CmaxWidth+[-(MaxOffset(3)-1),(MaxOffset(4)-1)];
else
    centerHeight=THeight+[-(MaxOffset(1)-1),(MaxOffset(2)-1)];
    centerWidth= TWidth +[-(MaxOffset(3)-1),(MaxOffset(4)-1)];
end

switch CorrMethod
    case 'redxcorr2normimages' %reduced xcorr2 with normalized images
    case 'redxcorr2normgradimages' %reduced xcorr2 with normalized gradient of images
        A=gradient(double(A));
        T=gradient(double(T));
%         [Ax,Ay]=gradient(double(A));
%         [Tx,Ty]=gradient(double(T));
%         A=Ax+Ay;
%         T=Tx+Ty;
%         clear Ax Ay Tx Ty
    otherwise
        CorrMethod='redxcorr2normimages'; %#ok<NASGU>
end
dX=nan(TNSlices,ANSlices);
dY=nan(TNSlices,ANSlices);
cmax=nan(TNSlices,ANSlices);
if nargout>=6
    C=zeros(centerHeight(2)-centerHeight(1)+1,...
        centerWidth(2)-centerWidth(1)+1,TNSlices,ANSlices);
end
for iaslice=1:ANSlices
    nA=rowcol_normalization(A(:,:,iaslice));
    if std(nA(:))==0
        continue;
    end
    fA=fft(nA,fftsize(1),1);
%         clear nA
    fA=permute(fA,[2,1]);
    fA=fft(fA,fftsize(2),1);
    fA=permute(fA,[2,1]);
    for itslice=1:TNSlices
        calcOK=false;
        while ~calcOK
            nT=rowcol_normalization(T(:,:,itslice));
            if std(nT(:))==0
                dY(itslice,iaslice)=NaN;
                dX(itslice,iaslice)=NaN;
                cmax(itslice,iaslice)=NaN;
                break;
            end
            nT=nT(end:-1:1,end:-1:1);
            fT=fft(nT,fftsize(1),1);
%             clear nT
            fT=permute(fT,[2,1]);
            fT=fft(fT,fftsize(2),1);
            fT=permute(fT,[2,1]);
%             inplaceprod(fT,fA);
            fT=fT.*fA;
            fC=fT;
%             clear fA fT
            if (MaxOffset(1)+MaxOffset(2))*fftsize(2)<=...
                    (MaxOffset(3)+MaxOffset(4))*fftsize(1)
                fC=ifft(fC,fftsize(1),1);
                fC=permute(fC,[2,1]);
                fC=fC(:,centerHeight(1):centerHeight(2));
                fC=ifft(fC,fftsize(2),1);
                fC=real(fC);
                fC=permute(fC,[2,1]);
                tempC=fC(:,centerWidth(1):centerWidth(2));
            else
                fC=permute(fC,[2,1]);
                fC=ifft(fC,fftsize(2),1);
                fC=permute(fC,[2,1]);
                fC=fC(:,centerWidth(1):centerWidth(2));
                fC=ifft(fC,fftsize(1),1);
                fC=real(fC);
                fC=permute(fC,[2,1]);
                fC=fC(:,centerHeight(1):centerHeight(2));
                tempC=permute(fC,[2,1]);            
            end
            
%             p=FastPeakFind(tempC);
%             p=reshape(p,2,[]);
%             ind=reshape(sub2ind(size(tempC),p(2,:),p(1,:)),[],1);
%             [~,order]=sort(tempC(ind),'descend');
%             ind=ind(order);
%             p=p(:,order);
%             imagesc(tempC); axis image; hold all;
%             plot(p(1,NPeaks),p(2,NPeaks),'r+')
%             uiwait();
            if NPeaks==1
                [ph ,ind] = max(tempC(:)); %#ok<ASGLU>
            else
                [ph,ind]=sort(tempC(:),'descend'); %#ok<ASGLU>
            end
%             [iy2 ,ix2] = ind2sub(size(tempC),ind2(1));
%             plot(ix2,iy2,'k+')            
            
            [iy ,ix] = ind2sub(size(tempC),ind(NPeaks));

            weight=tempC(ind(NPeaks));
            weight=weight/sum(weight);
            if CenterAsRef
                dY(itslice,iaslice)=iy'*weight-MaxOffset(1);
                dX(itslice,iaslice)=ix'*weight-MaxOffset(3);
            else
                dY(itslice,iaslice)=iy'*weight-MaxOffset(1);
                dX(itslice,iaslice)=ix'*weight-MaxOffset(3);
            end
            
            
%             overlap_area=(min(THeight,AHeight)-dY(itslice,iaslice))*...
%                 (min(TWidth,AWidth)-dX(itslice,iaslice));
%             overlap_area=min(THeight,AHeight)*min(TWidth,AWidth);
%             cmax(itslice,iaslice)=cmax(itslice,iaslice)/overlap_area;
            [iOverlapX,iOverlapY,~,jOverlapX,jOverlapY]=...
            fcn_get_overlap(...
                0,0,0,TWidth,THeight,1,...
                -dX(itslice,iaslice),-dY(itslice,iaslice),0,AWidth,AHeight,1);
            iOverlapX=round(iOverlapX);
            iOverlapY=round(iOverlapY);
            jOverlapX=round(jOverlapX);
            jOverlapY=round(jOverlapY);
            overlapT=double(T(iOverlapY(1):iOverlapY(2),iOverlapX(1):iOverlapX(2),itslice));
            overlapA=double(A(jOverlapY(1):jOverlapY(2),jOverlapX(1):jOverlapX(2),iaslice));

            NPx=numel(overlapT);
            sumOp=1/NPx*ones(1,NPx);
            
            overlapT=overlapT(:);
            tempMean=sumOp*overlapT;
            overlapT=overlapT-tempMean;
            tempStd=overlapT'*overlapT;
            tempStd=sqrt(tempStd/(NPx-1));
            overlapT=overlapT/tempStd;

            overlapA=overlapA(:);
            tempMean=sumOp*overlapA;
            overlapA=overlapA-tempMean;
            tempStd=overlapA'*overlapA;
            tempStd=sqrt(tempStd/(NPx-1));
            overlapA=overlapA/tempStd;

            cmax(itslice,iaslice)=overlapT'*overlapA/(NPx-1);

            if nargout>=6
                C(:,:,itslice,iaslice)=tempC;%#ok<AGROW> %/overlap_area;
            end
 
%             tempC = tempC - mean(tempC(:));
%             tempC = tempC/sqrt(tempC(:)'*tempC(:)/length(tempC(:)));        
%             [cmax(itslice,iaslice) ilin] = max(tempC(:));
%             C(:,:,itslice,iaslice)=tempC;
            
%             
%             imagesc(tempC); colorbar;
%             impoint(gca,ix,iy);
%             drawnow;
            if isempty(CorrThres)
                calcOK=true;
            else
                if cmax(itslice,iaslice)<CorrThres && ~all(MaxOffset==[THeight,AHeight,...
                        TWidth,AWidth])
                    disp(['cmax= ' num2str(cmax(itslice,iaslice)) '. CorrThres= ' num2str(CorrThres) '.'])
                    disp('Re-run calculations of offsets with new MaxOffset boundaries:')
                    MaxOffset=[THeight,AHeight,...
                        TWidth,AWidth];            
                    disp(num2str(MaxOffset));
                    calcOK=false;
                else
                    calcOK=true;
                end
            end
        end
    end        
end
if is1greater2
    dY1=dY;
    dX1=dX;
    dY2=-dY;
    dX2=-dX;
else
    dY1=-dY;
    dX1=-dX;
    dY2=dY;
    dX2=dX;
end
% close all;
% figure; imagesc(C); colorbar;
% impoint(gca,ix,iy);
% drawnow;
end

function A=rowcol_normalization(A)
    [AHeight,AWidth]=size(A);
    A=double(A);
    %% first normalize rows (in X direction) 
    if AWidth>1
        Mean=A*ones(AWidth,1)/AWidth; %faster than sum(...) or mean
        A=A-Mean*ones(1,AWidth);
        Norm=sqrt((A.*A)*ones(AWidth,1)/AWidth);
        Norm(Norm==0)=1;
        A=A./(Norm*ones(1,AWidth));
%         Norm=1./Norm;
%         inplaceprod(A,Norm*ones(1,AWidth));
    end
    if AHeight>1
        %% 2nd normalize columns (in Y direction) 
        A=A';
        Mean=A*ones(AHeight,1)/AHeight; %faster than sum(...) or mean
        A=A-Mean*ones(1,AHeight);
        Norm=sqrt((A.*A)*ones(AHeight,1)/AHeight);
        Norm(Norm==0)=1;
        A=A./(Norm*ones(1,AHeight));
%         Norm=1./Norm;
%         inplaceprod(A,Norm*ones(1,AHeight));
        A=A';
    end
end
back to top