⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 branchcuts.m

📁 a usefull source code from internet
💻 M
字号:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% BranchCuts.m generates branch cuts based on the phase residues. This is
% done using the Goldstein method, as described in "Two-dimensional phase 
% unwrapping: theory, algorithms and software" by Dennis Ghiglia and 
% Mark Pritt.
% "residue_charge" is a matrix wherein positive residues are 1 and 
% negative residues are 0. 
% "max_box_radius" defines the maximum search radius for the balancing of 
% residues. If this is too large, areas will be isolated by the branch
% cuts.
% "IM_mask" is a binary matrix. This serves as an artificial border for the
% branch cuts to connect to.
% Created by B.S. Spottiswoode on 15/10/2004
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Edited by K. Van Caekenberghe on 17/03/2009
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function branch_cuts=BranchCuts(residue_charge, max_box_radius, IM_mask);

[rowdim, coldim]=size(residue_charge);

branch_cuts=~IM_mask; %Define initial branch cuts borders as the mask.
residue_charge_masked=residue_charge;
residue_charge(logical(~IM_mask))=0; %Remove all residues except those in the mask
cluster_counter=1; %Keep track of the number of residues in each cluster
satellite_residues=0; %Keep track of the number of satellite residues accounted for

residue_binary=(residue_charge~=0); %Logical matrix indicating the position of the residues
residue_balanced=zeros(rowdim, coldim); %Initially designate all residues as unbalanced

[rowres,colres] = find(residue_binary); %Find the coordinates of the residues
adjacent_residues=zeros(rowdim, coldim); %Defines the positions of additional residues found in the search box
missed_residues=0; %Keep track of the effective number of residues left unbalanced because of

%disp('Calculating branch cuts ...');
tic;
temp=size(rowres);
for i=1:temp(1); %Loop through the residues
    radius=1; %Set the initial box size
    r_active=rowres(i); %Coordinates of the active residue
    c_active=colres(i);
    count_nearby_residues_flag=1; %Flag to indicate whether or not to keep track of the nearby residues
    cluster_counter=1; %Reset the cluster counter
    adjacent_residues=zeros(rowdim, coldim); %Reset the adjacent residues indicator
    charge_counter=residue_charge_masked(r_active, c_active); %Store the initial residue charge
    if residue_balanced(r_active, c_active)~=1 %Has this residue already been balanced?
        while (charge_counter~=0) %Loop until balanced
            
            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
            %This portion of code serves to search the box perimeter,
            %place branch cuts, and keep track of the summed residue charge
            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
            for m=r_active-radius:r_active+radius %Coordinates of the box border pixels  ***I COULD MAKE THIS MORE EFFICIENT***
                for n=c_active-radius:c_active+radius
                    if (abs(m - r_active)==radius | abs(n - c_active)==radius) & charge_counter~=0 %Ensure that only the border pixels are being scrutinised
                        if m<=1 | m>=rowdim | n<=1 | n>=coldim %Is the current pixel on the image border?
                            if m>=rowdim m=rowdim; end %Make sure that the indices aren't too large for the matrix
                            if n>coldim n=coldim; end
                            if n<1 n=1; end
                            if m<1 m=1; end
                            branch_cuts=PlaceBranchCutInternal(branch_cuts, r_active, c_active, m, n); %Place a branch cut between the active point and the border
                            cluster_counter=cluster_counter+1; %Keep track of how many residues have been clustered
                            charge_counter=0; %Label the charge as balanced
                            residue_balanced(r_active, c_active)=1; %Mark the centre residue as balanced
                        end
                        if IM_mask(m,n)==0
                            branch_cuts=PlaceBranchCutInternal(branch_cuts, r_active, c_active, m, n); %Place a branch cut between the active point and the mask border
                            cluster_counter=cluster_counter+1; %Keep track of how many residues have been clustered
                            charge_counter=0; %Label the charge as balanced
                            residue_balanced(r_active, c_active)=1; %Mark the centre residue as balanced
                        end
                        if residue_binary(m,n)==1 %Is the current pixel a residue?
                            if count_nearby_residues_flag==1 %Are we keeping track of the residues encountered?
                                adjacent_residues(m,n)=1; %Mark the current residue as adjacent
                            end 
                            branch_cuts=PlaceBranchCutInternal(branch_cuts, r_active, c_active, m, n); %Place a branch cut regardless of the charge_counter value
                            cluster_counter=cluster_counter+1; %Keep track of how many residues have been clustered
                            if residue_balanced(m,n)==0; 
                                residue_balanced(m,n)=1; %Mark the current residue as balanced
                                charge_counter=charge_counter + residue_charge_masked(m,n); %Update the charge counter            
                            end
                            if charge_counter==0 %Is the active residue balanced?
                                residue_balanced(r_active, c_active)=1; %Mark the centre (active) residue as balanced
                            end
                        end
                    end
                end
            end
            
            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
            %This next portion of code centres the box on the adjacent
            %residues. If the charge is still not balanced after moving
            %through all adjacent residues, increase the box radius and
            %centre the box around the initial residue.
            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
            if sum(sum(adjacent_residues))==0 %If there are no adjacent residues:
                radius=radius+1; %Enlarge the box    
                r_active=rowres(i); %Centre the larger box about the original active residue
                c_active=colres(i);
            else  %If there are adjacent residues:
                if count_nearby_residues_flag==1; %Run this bit once per box being searched
                    [r_adjacent,c_adjacent] = find(adjacent_residues); %Find the coordinates of the adjacent residues
                    adjacent_size=size(r_adjacent); %How many residues are on the perimeter
                    r_active=r_adjacent(1); %Centre the search box about a nearby residue
                    c_active=c_adjacent(1);
                    adjacent_residue_count=1;
                    residue_balanced(r_active, c_active)=1; %Mark the centre (active) residue as balanced before moving on
                    count_nearby_residues_flag=0; %Disable further counting of adjacent residues
                else
                    %disp(['Moving block size ', int2str(radius), ' for point ', int2str(i)]);
                    adjacent_residue_count=adjacent_residue_count + 1; %Move to the next nearby residue
                    if adjacent_residue_count<=adjacent_size(1)
                        r_active=r_adjacent(adjacent_residue_count); %Centre the search box about the next nearby residue 
                        c_active=c_adjacent(adjacent_residue_count);
                    else %Ok, we're done with this box
                        radius=radius+1; %Enlarge the box and move on   
                        r_active=rowres(i); %Centre the larger box about the original active residue
                        c_active=colres(i);
                        adjacent_residues=zeros(rowdim, coldim); %Reset the adjacent residues indicator
                        count_nearby_residues_flag=1; %Enable further counting of adjacent residues
                    end
                end
            end
            
            if radius>max_box_radius %Enforce a maximum boundary condition
                %disp('Warning: unreasonably large search area...');
                if cluster_counter~=1 %The single satellite residues will still be taken care of
                    missed_residues=missed_residues+1; %This effectively means that we have an unbalanced residue 
                else
                    satellite_residues=satellite_residues+1; %This residues is about to be accounted for...                       
                end
                charge_counter=0;
                
                %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                %This next portion of code ensures that single satellite
                %residues are not left unaccounted for. The box is simply
                %expanded regardless until the border or ANY other residue
                %is found.
                %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                while cluster_counter==1 %If the centre residue is a single satellite, then continue to increase the search radius
                     r_active=rowres(i); %Centre the box on the original residue
                     c_active=colres(i);
                     for m=r_active-radius:r_active+radius %Coordinates of the box border pixels  ***This code works but could definitely be made more efficient***
                        for n=c_active-radius:c_active+radius
                            if (abs(m - r_active)==radius | abs(n - c_active)==radius) %Ensure that only the border pixels are being scrutinised
                                if m<=1 | m>=rowdim | n<=1 | n>=coldim %Is the current pixel on the image border?
                                    if m>=rowdim m=rowdim; end %Make sure that the indices aren't too large for the matrix
                                    if n>coldim n=coldim; end
                                    if n<1 n=1; end
                                    if m<1 m=1; end
                                    branch_cuts=PlaceBranchCutInternal(branch_cuts, r_active, c_active, m, n); %Place a branch cut between the active point and the border
                                    cluster_counter=cluster_counter+1; %Keep track of how many residues have been clustered
                                    residue_balanced(r_active, c_active)=1; %Mark the centre (active) residue as balanced
                                end
                                if IM_mask(m,n)==0 %Does the point fall on the mask
                                    branch_cuts=PlaceBranchCutInternal(branch_cuts, r_active, c_active, m, n); %Place a branch cut between the active point and the mask border
                                    cluster_counter=cluster_counter+1; %Keep track of how many residues have been clustered
                                    residue_balanced(r_active, c_active)=1; %Mark the centre (active) residue as balanced
                                end
                                if residue_binary(m,n)==1 %Is the current pixel a residue?
                                    branch_cuts=PlaceBranchCutInternal(branch_cuts, r_active, c_active, m, n); %Place a branch cut regardless of the charge_counter value
                                    cluster_counter=cluster_counter+1; %Keep track of how many residues have been clustered
                                    residue_balanced(r_active, c_active)=1; %Mark the centre (active) residue as balanced
                                end
                            end
                        end
                    end
                    radius=radius+1; %Enlarge the box and continue searching
                end
            end  
        end % of " while (charge_counter~=0) "
    end % of " if residue_balanced(r_active, c_active)~=1 "
end

t=toc;
%disp(['Branch cut operation completed in ',int2str(t),' seconds.']);
%disp(['Unbalanced residues = ', num2str(100*missed_residues/sum(sum(residue_binary))), ' %']);
%disp(['Satellite residues accounted for = ', num2str(satellite_residues)]);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% PlaceBranchCutInternal.m places a branch cut between the points [r1, c1] and 
% [r2, c2]. The matrix branch_cuts is binary, with 1's depicting a 
% branch cut. 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function branch_cuts=PlaceBranchCutInternal(branch_cuts, r1, c1, r2, c2); 

branch_cuts(r1,c1)=1; %Fill the initial points
branch_cuts(r2,c2)=1;
radius=sqrt((r2-r1)^2 + (c2-c1)^2); %Distance between points
warning off MATLAB:divideByZero;            
m=(c2-c1)/(r2-r1); %Line gradient
theta=atan(m); %Line angle

if c1==c2 %Cater for the infinite gradient
    if r2>r1
        for i=1:radius
            r_fill=r1 + i;  
            branch_cuts(r_fill, c1)=1;
        end
        return;
    else
        for i=1:radius
            r_fill=r2 + i;   
            branch_cuts(r_fill, c1)=1;
        end
        return;
    end
end

%Use different plot functions for the different quadrants (This is very clumsy, 
%I'm sure there is a better way of doing it...)
if theta<0 & c2<c1                           
    for i=1:radius %Number of points to fill in
        r_fill=r1 + round(i*cos(theta));    
        c_fill=c1 + round(i*sin(theta));
        branch_cuts(r_fill, c_fill)=1;
    end
    return;
elseif theta<0 & c2>c1 
     for i=1:radius %Number of points to fill in
        r_fill=r2 + round(i*cos(theta));
        c_fill=c2 + round(i*sin(theta));
        branch_cuts(r_fill, c_fill)=1;
    end
    return;
end

if theta>0 & c2>c1                          
    for i=1:radius %Number of points to fill in
        r_fill=r1 + round(i*cos(theta));    
        c_fill=c1 + round(i*sin(theta));
        branch_cuts(r_fill, c_fill)=1;
    end
    return;
elseif theta>0 & c2<c1 
     for i=1:radius %Number of points to fill in
        r_fill=r2 + round(i*cos(theta));
        c_fill=c2 + round(i*sin(theta));
        branch_cuts(r_fill, c_fill)=1;
    end
    return;
end

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -