这是我学习编程以后做的第一个项目,课题是肺部支气管的分割算法。
代码分为两个部分,第一部分是将CT图像顺序读入三维矩阵保存
d = ls('*.dcm');%列出子文件中格式为.dcm的所有文件d
m = size(d,1);%获取文件数m
[group, element] = dicomlookup('InstanceNumber');%查看文件编号
sdata(m) = struct('imagename','','instance',0);%创建m行2列空的数据命名为imagename和instance
for i = 1:m
metadata = dicominfo(d(i,:));%逐个读取文件信息
position = metadata.(dicomlookup(group, element));%读取文件instancenumber到position
sdata(i) = struct('imagename',d(i,:),'instance',position);%逐个将文件名和position赋到sdata中的imagename列与instance列
end
[unused, order] = sort([sdata(:).instance],'ascend');%将sdata中的instance列按升序排序
sorted = sdata(order).';%将order转置成为sorted
for i = 1:m
d(i,:) = sorted(i).imagename;%逐个读取文件名到d的各行
end
topimage = dicomread(d(1,:));%读取第一张图片
metadata = dicominfo(d(1,:));%读取第一张图片信息
[group1, element1] = dicomlookup('PixelSpacing');%获取像素空间
[group2, element2] = dicomlookup('SliceThickness');%获取层厚
resolution = metadata.(dicomlookup(group1, element1));%读取图片像素空间到resolution
xthickness = resolution(1); ythickness = resolution(2);%读取行和列到resolution(1)和resolution(2)
zthickness = metadata.(dicomlookup(group2, element2));%读取层厚到zthickness
threedarray = zeros(size(topimage,1),size(topimage,2),size(d,1));%获取一个同尺寸的三维全零矩阵
M = zeros(size(topimage,1),size(topimage,2),size(d,1));%此三维矩阵命名为M
threedarray(:,:,1) = topimage;%将第一张图片放在第一层
for i = 2:size(d,1)
threedarray(:,:,i) = dicomread(d(i,:));%从第二层开始逐张读入图片
end
list=dir('*.dcm');%获得I:\(勿删)CT影像病例数据库\32(2组)\2013-10-17\文件夹下的文件
m=length(list);%文件数k
D=zeros(512,512,m);%生成一个512*512*k的三维全零矩阵D
for j=1:m
D(:,:,j)=threedarray(:,:,j).*metadata.RescaleSlope+metadata.RescaleIntercept;%通过文件信息中RescaleSlope值与RescaleIntercept值进行运算将D三维矩阵中的像素点转为CT值存入M三维矩阵中
end
然后自适应阈值进行区域生长。
clc;
clear
load('1.3.6.1.4.1.9328.50.3.0362.mat')
D=M;
a=size(D);
m=a(1,3);
n=m/8;
n=round(n);
I=D(:,:,n);
figure,imshow(I,[]);
BW1=edge(I,'log');%边缘检测
figure,imshow(BW1);
h=bwareaopen(BW1,50);
IM2 = imclearborder(h);
figure,imshow(IM2);
f=imfill(IM2,'holes');
figure,imshow(f);
for i=1:150
for j=1:512
if f(i,j)==1
f(i,j)=0;
end
end
end
for i=350:512
for j=1:512
if f(i,j)==1
f(i,j)=0;
end
end
end
for i=1:512
for j=1:200
if f(i,j)==1
f(i,j)=0;
end
end
end
for i=1:512
for j=350:512
if f(i,j)==1
f(i,j)=0;
end
end
end
figure,imshow(f)
%imLabel=bwlabel(f);
%stats = regionprops(imLabel,'Area'); %求各连通域的大小
%bw2 = ismember(imLabel, find([stats.Area] >=600));%除去面积小于800的连通域
%BW=imclearborder(bw2);
%figure,imshow(BW);
imLabel1=bwlabel(f);
stats = regionprops(imLabel1,'Area'); %求各连通域的大小
area = cat(1,stats.Area);
index = find(area == max(area)); %求最小连通域的索引
img = ismember(imLabel1,index);
figure,imshow(img,[]);
Stats=regionprops(img,'Centroid');%取质心
x=Stats.Centroid(1);
y=Stats.Centroid(2);
x1=round(x);
y1=round(y);
z1=n;
Mat=D;
R=cell(1);
R{1}=500000;
seed=[y1,x1,z1];
ppp=1;
l=1;
[r, c, p] = size(Mat);
J = false(r, c, p);%输出矩阵
qqq=0;
queue = [seed(1), seed(2), seed(3)];%种子队列
for threshold = -990:5:1000
if qqq<0.05
while size(queue, 1)
x = queue(1,1);
y = queue(1,2);
z = queue(1,3);
queue(1,:) = [];
for i = -1:1
for j = -1:1
for k = -1:1
if x+i > 0 && x+i <= r && y+j > 0 && y+j <= c &&z+k > 0 && z+k <= p &&...
any([i, j, k]) &&...
~J(x+i, y+j, z+k) &&...
Mat(x+i, y+j, z+k) <= threshold
J(x+i, y+j, z+k) = true;
queue(end+1,:) = [x+i, y+j, z+k];
ppp=ppp+1;
end
end
end
end
end
l=l+1;
R{l}=ppp;
qqq=(R{l}-R{l-1})/R{l-1};
else qqq>0.05
break
end
end
最后其实还有一个重建显示的m文件。也贴在下面。
function Render_con(air_way,S_X,S_Y,S_Z)
%air_way:气管三维矩阵
%S_X,S_Y,S_Z,各维度尺寸
H = [];
loop=1:S_Z;
per_air_way=zeros(S_X,S_Y,S_Z);
per_air_way(:,:,S_Z-loop+1)=air_way(:,:,loop);
[x,y,z,H] = reducevolume(per_air_way,[1,1,1]);
% [x,y,z,H] = reducevolume(air_way,[1,1,1]);
figure;
f1 = isosurface(x,y,z,H,0.8,'verbose');
p1=patch(f1,'FaceColor','red','EdgeColor','none');
isonormals(x,y,z,H,p1);
f2=isocaps(x,y,z,H,0.8);
p2=patch(f2,'FaceColor','interp','EdgeColor','none');
view(0,0);
axis tight;
daspect([300,300,300]);
colormap(gray(100));
camlight;
% lighting phong;
% lightangle(0,30);
lighting phong;
lightangle(90,30);
% lighting phong;
% lightangle(180,30);
%
% lighting phong;
% lightangle(270,30);
end