肺部支气管分割算法

这是我学习编程以后做的第一个项目,课题是肺部支气管的分割算法。

代码分为两个部分,第一部分是将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


第一部分得到的三维矩阵我后来保存出来了。就是以下的1.3.6.1.4.1.9328.50.3.0362.mat。
接下来就是截取大概1/8位置的自动寻找种子点。

然后自适应阈值进行区域生长。

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

肺部支气管分割算法_第1张图片


当时写的很粗糙,可读性也不高,对不同人CT图像的适用性也不是特别好,暂时先贴出来吧,以后有时间了慢慢修改~

你可能感兴趣的:(MATLAB)