|
a |
|
b/Thoracic Organs Segmentation code/RibCageApproximation.m |
|
|
1 |
function [FinalCurve]=RibCageApproximation(I,Thres); |
|
|
2 |
%Draw a closed curve which approximates the cross |
|
|
3 |
%section of the rib cage in CT slices. |
|
|
4 |
% [FinalCurve]=RibCageApproximation(I,Thres); |
|
|
5 |
% Input parameters |
|
|
6 |
% Img=> the CT slice |
|
|
7 |
% Thres=> the desired threshold for the ribs (bones) extraction. |
|
|
8 |
|
|
|
9 |
Img=squeeze(I); |
|
|
10 |
|
|
|
11 |
%apply threshold |
|
|
12 |
BinaryImage=Img>Thres; |
|
|
13 |
%perform morphological open operation |
|
|
14 |
BinaryImage = imopen(BinaryImage,strel([1 1;1 1])); |
|
|
15 |
|
|
|
16 |
%find the pixels of the rib cage. |
|
|
17 |
[x,y]=find(BinaryImage==1); |
|
|
18 |
|
|
|
19 |
%define the center of the image. |
|
|
20 |
ImgCenter =round( [size(BinaryImage)]./2); |
|
|
21 |
|
|
|
22 |
|
|
|
23 |
%Estimate the vector between bone pixels and image centre |
|
|
24 |
vector = [x-ImgCenter(1),y-ImgCenter(2)]; |
|
|
25 |
%Vector's angle in degrees. |
|
|
26 |
Angle = mod(360+180/pi*atan2(vector(:,2),vector(:,1)),360); |
|
|
27 |
|
|
|
28 |
|
|
|
29 |
%In each directions (0, 10,...., 360 degrees), define the bone pixel which is closer to the image |
|
|
30 |
%center and keep it for the interpolation process. |
|
|
31 |
|
|
|
32 |
Theta=[0:10:360];k=0; |
|
|
33 |
|
|
|
34 |
Ind=cell([length(Theta)-1,1]); |
|
|
35 |
for i =1:length(Theta)-1 |
|
|
36 |
[Ind{i,1}] = find(Angle>=Theta(i) & Angle<Theta(i+1)); |
|
|
37 |
if ~isempty(Ind{i,1}) |
|
|
38 |
IndMinDist = FunctionMinDistance(x(Ind{i,1}),y(Ind{i,1}),ImgCenter(1),ImgCenter(2)); |
|
|
39 |
k=k+1; |
|
|
40 |
IndOfMinDistance(k,1)=Ind{i,1}(IndMinDist(1),1); |
|
|
41 |
|
|
|
42 |
end |
|
|
43 |
end |
|
|
44 |
|
|
|
45 |
|
|
|
46 |
%Set points with the minimum distance from the center of the ribs cavity in an order |
|
|
47 |
[xi, yi]=PixelsInOrder(x(IndOfMinDistance),y(IndOfMinDistance),ImgCenter(1),ImgCenter(2)); |
|
|
48 |
|
|
|
49 |
%Cubic interpolation |
|
|
50 |
[xii, yii] = Curvefitting(xi,yi,0.2); |
|
|
51 |
xii = round(xii);yii=round(yii); |
|
|
52 |
|
|
|
53 |
%Draw the final curve |
|
|
54 |
FinalCurve=zeros(size(BinaryImage)); |
|
|
55 |
|
|
|
56 |
for i =1:length(xii) |
|
|
57 |
FinalCurve(xii(i),yii(i))=1; |
|
|
58 |
end |
|
|
59 |
|
|
|
60 |
|
|
|
61 |
|
|
|
62 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
|
63 |
%% |
|
|
64 |
function IndOfMinDistance = FunctionMinDistance(I,J,c1,c2) |
|
|
65 |
%This function calculates the distance between each contour (I,J) point and |
|
|
66 |
%the centre of the contour |
|
|
67 |
%and finds the edge with the minimum distance |
|
|
68 |
% IndOfMinDistance = FunctionMinDistance(I,J,c1,c2) |
|
|
69 |
|
|
|
70 |
% Input Parameters |
|
|
71 |
% [I,J] points coordinates |
|
|
72 |
% [c1,c2] coordinates of the centre of the contour |
|
|
73 |
|
|
|
74 |
MinDistance = zeros(length(I),1); |
|
|
75 |
|
|
|
76 |
MinDistance(:) = sqrt((I(:)-c1).^2+(J(:)-c2).^2); |
|
|
77 |
IndOfMinDistance =find (MinDistance <= min (MinDistance)); |
|
|
78 |
|
|
|
79 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
|
80 |
function [Final_x, Final_y]=PixelsInOrder(x,y,c1,c2); |
|
|
81 |
|
|
|
82 |
%Define a cartesian system xy with center[c1,c2], |
|
|
83 |
%Set the points [x,y] in a circular order according to theirs angles |
|
|
84 |
% [Final_x, Final_y]=PixelsInOrder(x,y,c1,c2); |
|
|
85 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
|
86 |
|
|
|
87 |
c1=round(c1);c2=round(c2); |
|
|
88 |
|
|
|
89 |
vector = [x-c1,y-c2]; |
|
|
90 |
%estimate the angle between the cartesian axis x and the points [x,y] |
|
|
91 |
Theta = mod(360+180/pi*atan2(vector(:,2),vector(:,1)),360); |
|
|
92 |
|
|
|
93 |
%sort the [x,y] points |
|
|
94 |
[ThetaSorted,Ind] = sort(Theta); |
|
|
95 |
|
|
|
96 |
Final_x=zeros(length(x),1); |
|
|
97 |
Final_y=zeros(length(y),1); |
|
|
98 |
Final_x(1:length(x)) =x(Ind); |
|
|
99 |
Final_y(1:length(y)) =y(Ind); |
|
|
100 |
|
|
|
101 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
|
102 |
function [xi,yi] = Curvefitting(x,y,RES) |
|
|
103 |
% Interpolate(cubic) the points of the image in order to create a close curve |
|
|
104 |
% [xi,yi] =Curvefitting(x,y,RES) |
|
|
105 |
% |
|
|
106 |
% RES: resolution desired |
|
|
107 |
|
|
|
108 |
% |
|
|
109 |
% Modified Code by A. Koulouri |
|
|
110 |
% |
|
|
111 |
% Chenyang Xu and Jerry L. Prince, 3/8/96, 6/17/97 |
|
|
112 |
% Copyright (c) 1996-97 by Chenyang Xu and Jerry L. Prince |
|
|
113 |
% Image Analysis and Communications Lab, Johns Hopkins University |
|
|
114 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
|
115 |
% convert to column vector |
|
|
116 |
x = x(:); y = y(:); |
|
|
117 |
|
|
|
118 |
N = length(x); |
|
|
119 |
|
|
|
120 |
% make it a circular list since we are dealing with closed contour |
|
|
121 |
x = [x;x(1)]; |
|
|
122 |
y = [y;y(1)]; |
|
|
123 |
|
|
|
124 |
dx = x([2:N+1])- x(1:N); |
|
|
125 |
dy = y([2:N+1])- y(1:N); |
|
|
126 |
d = sqrt(dx.*dx+dy.*dy); % compute the distance from previous node for point 2:N+1 |
|
|
127 |
|
|
|
128 |
d = [0;d]; % point 1 to point 1 is 0 |
|
|
129 |
|
|
|
130 |
% now compute the arc length of all the points from the first point [x(1), |
|
|
131 |
% y(1)]. |
|
|
132 |
% we use matrix multiply to achieve summing |
|
|
133 |
M = length(d); |
|
|
134 |
d = (d'*uppertri(M,M))'; |
|
|
135 |
|
|
|
136 |
% now ready to reparametrize the closed curve in terms of arc length |
|
|
137 |
maxd = d(M); |
|
|
138 |
|
|
|
139 |
if (maxd/RES<3) |
|
|
140 |
error('RES too big compare to the length of original curve'); |
|
|
141 |
end |
|
|
142 |
|
|
|
143 |
di = 0:RES:maxd; |
|
|
144 |
|
|
|
145 |
xi = interp1(d,x,di,'cubic'); |
|
|
146 |
yi = interp1(d,y,di,'cubic'); |
|
|
147 |
|
|
|
148 |
N = length(xi); |
|
|
149 |
|
|
|
150 |
if (maxd - di(length(di)) <RES/2) % deal with end boundary condition |
|
|
151 |
xi = xi(1:N-1); |
|
|
152 |
yi = yi(1:N-1); |
|
|
153 |
end |
|
|
154 |
|
|
|
155 |
function X = uppertri(M,N) |
|
|
156 |
% UPPERTRI Upper triagonal matrix |
|
|
157 |
% UPPER(M,N) is a M-by-N triagonal matrix |
|
|
158 |
|
|
|
159 |
[J,I] = meshgrid(1:M,1:N); |
|
|
160 |
X = (J>=I); |
|
|
161 |
|
|
|
162 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
|
163 |
|
|
|
164 |
|
|
|
165 |
|
|
|
166 |
|