Switch to unified view

a b/combinedDeepLearningActiveContour/functions/calc_dist.m
1
function varargout = calc_dist(target_xy,reference_xy,para)
2
%calc perpendicular distance between target and reference contours
3
4
    
5
    %check closed contours
6
    if target_xy(1,1) == target_xy(end,1) && target_xy(1,2) == target_xy(end,2)
7
        target_xy = target_xy(1:end-1,:);
8
    end
9
    if reference_xy(1,1) == reference_xy(end,1) && reference_xy(1,2) == reference_xy(end,2)
10
        reference_xy = reference_xy(1:end-1,:);
11
    end
12
13
    %for finding a subset of reference that correspond to the current target
14
    target_mask = poly2mask (target_xy(:,1),target_xy(:,2),double(para.width),double(para.height));
15
    reference_mask = poly2mask (reference_xy(:,1),reference_xy(:,2),double(para.width),double(para.height));
16
    
17
    %centroid of refernece mask
18
    reference_cen = regionprops(logical(reference_mask),'Centroid');
19
    reference_cen_x = round(reference_cen.Centroid(1));
20
    reference_cen_y = round(reference_cen.Centroid(2));
21
    
22
    %check if target mask's centroid is in refernece's mask
23
    if  target_mask(reference_cen_y,reference_cen_x) ==1
24
        target_cen = reference_cen;
25
    else
26
        %target_mask=clean_segs(target_mask);
27
        target_cen = regionprops(logical(target_mask),'Centroid');
28
        
29
    end
30
31
    %calc degrees between contours points and centroid
32
    target_degree = atan2( target_xy(:,2)-target_cen.Centroid(2),target_xy(:,1)-target_cen.Centroid(1))*180/pi;
33
    reference_degree = atan2( reference_xy(:,2)-reference_cen.Centroid(2),reference_xy(:,1)-reference_cen.Centroid(1))*180/pi;
34
        
35
    %initialize
36
    distance=zeros(size(target_xy,1),1);
37
    
38
    for idx = 1: size(target_xy,1)
39
        %Get 3 points,[left current right]
40
        if idx == 1
41
            target_xy_3 = [target_xy(end,:); target_xy(idx:idx+1,:)];
42
        elseif (idx == size(target_xy,1))
43
            target_xy_3 = [target_xy(end-1:end,:); target_xy(1,:)];
44
        else
45
            target_xy_3 = target_xy(idx-1:idx+1,:);
46
        end
47
48
        %current target to reference distance
49
        target_curr_x = target_xy_3(2,1);
50
        target_curr_y = target_xy_3(2,2);
51
52
        %find a subset of reference that correspond to the current target
53
        if ( abs(target_degree(idx)) >= 150 )
54
            reference_xy_subset = reference_xy(find(abs(reference_degree)>=130),:);
55
        else
56
            reference_xy_subset = reference_xy(find(abs(reference_degree-target_degree(idx))<50),:);
57
        end
58
        
59
        %plot reference_xy_subset
60
        %hold on; plot(reference_xy_subset(:,1)-min_showbox_x(1)+showbox_offset, reference_xy_subset(:,2)-min_showbox_y(1)+showbox_offset ,'r*')
61
        
62
        %fit line
63
        target_X = target_xy_3(:,1);
64
        target_Y = target_xy_3(:,2);
65
        
66
        %3 points are the same
67
        if ( sum(abs(target_X - target_X(2))) + sum(abs(target_Y - target_Y(2))) == 0 )
68
            continue;
69
        end
70
        
71
        target_LINE = [target_X ones(size(target_X))] \ target_Y; %left division-least squares,  %y=LINE(1)*x+LINE(2)
72
        target_LINE_inv = [target_Y ones(size(target_Y))] \ target_X; %left division-least squares,  %x=LINE(1)*y+LINE(2)  Reverse the coordinates.
73
        
74
        %if the line is very close to parallel with the Y axis, and the residuals for the fit
75
        %improve by reversing the coordinates, then use the line found by
76
        %reversing the coordinates.
77
        if ( abs(target_LINE_inv(1))< 0.1 && sum(abs([target_Y ones(size(target_Y))] * target_LINE_inv - target_X)) < sum(abs([target_X ones(size(target_X))] * target_LINE - target_Y)))
78
            target_LINE = 1./(target_LINE_inv + 0.00001) ;
79
            %hold on; plot(target_X- min_showbox_x(1) + showbox_offset,target_Y - min_showbox_y(1) + showbox_offset,'Y*')
80
        end
81
        
82
        %Determine the line normal to the above tangent line (target_LINE).
83
        %Normal line: Ax+By+C=0;
84
        if abs(target_LINE(1)) < 0.01 %fit line parallel to X axis, normal parallel to Y axis
85
            A_N = 1;
86
            B_N = 0;
87
            C_N = -target_curr_x;
88
            reference_xy_subset_to_normal_distance = abs(reference_xy_subset(:,1)- target_curr_x); 
89
        elseif abs(target_LINE(1)) > 100 %fit line parallel to Y axis, normal parallel to X axis
90
            A_N = 0;
91
            B_N = 1;
92
            C_N = -target_curr_y;
93
            reference_xy_subset_to_normal_distance = abs(reference_xy_subset(:,2)- target_curr_y); 
94
        else
95
            A_N = -1/target_LINE(1);
96
            B_N = -1;
97
            C_N = target_curr_y - A_N * target_curr_x;
98
            reference_xy_subset_to_normal_distance = abs( (A_N*reference_xy_subset(:,1) + B_N*reference_xy_subset(:,2) + C_N))/sqrt(A_N^2 + B_N^2);%normal: y=N(1)*x+N(2);
99
        end
100
101
        %find reference point most close to normal
102
        [min_dist_subset, min_idx_subset] = min(reference_xy_subset_to_normal_distance);
103
      
104
        %if there are more than one min distance points, choose the one most close to current target
105
        min_idx_subset_1= find(reference_xy_subset_to_normal_distance <= 0.5); 
106
        
107
        if (length(min_idx_subset_1)>=2)
108
             min_dist_subset_to_target_curr_distance = sqrt((target_curr_x -  reference_xy_subset(min_idx_subset_1,1)).^2 + (target_curr_y - reference_xy_subset(min_idx_subset_1,2)).^2);
109
             [min_dist_subset, min_idx_subset_2] = min(min_dist_subset_to_target_curr_distance);
110
             reference_to_min_dist_subset_distance = sqrt((reference_xy(:,1) -  reference_xy_subset(min_idx_subset_1(min_idx_subset_2),1)).^2 + (reference_xy(:,2) - reference_xy_subset(min_idx_subset_1(min_idx_subset_2),2)).^2);
111
        else
112
             reference_to_min_dist_subset_distance = sqrt((reference_xy(:,1) -  reference_xy_subset(min_idx_subset,1)).^2 + (reference_xy(:,2) - reference_xy_subset(min_idx_subset,2)).^2);
113
        end
114
         
115
        min_idx_temp = find(reference_to_min_dist_subset_distance == 0);
116
        min_idx = min_idx_temp(1);
117
118
        %Get 3 points of reference,[left most-close-to-normal right]
119
        if min_idx == 1
120
            reference_xy_3 = [reference_xy(end,:); reference_xy(min_idx:min_idx+1,:)];
121
        elseif (min_idx == size(reference_xy,1))
122
            reference_xy_3 = [reference_xy(end-1:end,:); reference_xy(1,:)];
123
        else
124
            reference_xy_3 = reference_xy(min_idx-1:min_idx+1,:);
125
        end
126
127
        %fit reference line: Ax+By+C=0; 
128
        reference_X = reference_xy_3(:,1);
129
        reference_Y = reference_xy_3(:,2);
130
        reference_LINE = [reference_X ones(size(reference_X))] \ reference_Y; %left division-least squares,         %y=LINE(1)*x+LINE(2)
131
      
132
        reference_LINE_inv = [reference_Y ones(size(reference_Y))] \ reference_X; %left division-least squares,  %y=LINE(1)*x+LINE(2)
133
      
134
        %fit line parallel to Y axis,
135
        if ( abs(reference_LINE_inv(1))< 0.1 && sum(abs([reference_Y ones(size(reference_Y))] * reference_LINE_inv - reference_X)) < sum(abs([reference_X ones(size(reference_X))] * reference_LINE - reference_Y)))
136
            reference_LINE = 1./(reference_LINE_inv + 0.00001) ;
137
            %hold on; plot(target_X- min_showbox_x(1) + showbox_offset,target_Y - min_showbox_y(1) + showbox_offset,'Y*')
138
        end
139
        
140
        if abs(reference_LINE(1)) < 0.01 % reference line parallel to X axis
141
            A_R = 0;
142
            B_R = 1;
143
            C_R = -reference_Y(2);
144
        elseif abs(reference_LINE(1)) >100  % reference line parallel to Y axis
145
            A_R = 1;
146
            B_R = 0;
147
            C_R = -reference_X(2);
148
        else
149
            A_R = reference_LINE(1);
150
            B_R = -1;
151
            C_R = reference_Y(2) - A_R * reference_X(2);
152
        end
153
        
154
        %intersection of normal and reference line
155
        AA=[A_N B_N; A_R B_R];
156
        BB =[-C_N; -C_R];
157
        XX =AA\BB; %  AA is a square matrix, AA\BB is roughly the same as inv(AA)*BB
158
159
        %validate intersection point
160
        XX_reference_distance = sqrt((XX(1) -  reference_xy_subset(:,1)).^2 + (XX(2) - reference_xy_subset(:,2)).^2  );
161
        if min(XX_reference_distance)<1.5
162
            %distance
163
            distance(idx) = sqrt((target_curr_x - XX(1))^2 + (target_curr_y - XX(2))^2);
164
       
165
        else
166
            distance(idx) = -999;
167
        end
168
    end
169
    
170
    %in mm
171
    distance = distance * para.pixel_spacing(1);
172
    distance_effective = distance(distance>0);
173
    varargout{1} =mean(distance_effective); 
174
    
175
end