CT图像重建算法——迭代算法ART

迭代图像重建的方法可分为迭代迭代法和统计迭代法,代数迭代法以代数重建算法(Algebraic Reconstruction Technique,ART)为代表。ART适合于不完全投影数据的图像重建,其抗噪声干扰能力强,另外可以结合一些先验知识进行求解,ART最大的缺点是计算量大,重建速度慢。

代数重建算法(ART)是由Kaczmarz于1937年在求解相容线性方程组时提出的,随后得到 Tanabe 的进一步阐明。ART先假设一幅初始图像,通过“正向投影”得到一个计算的投影,然后将计算的投影与实际测量投影相比较,基于比较的差值来估计修正值,将修正值均匀地分配给射线经过的那些像素上,逐条射线地执行这一过程,直到满足要求。

clc;
clear all;
close all;
N=180;
N2=N^2;
I=phantom(N);
theta=linspace(0,180,61);
theta=theta(1:60);%投影角度
%产生投影数据%
P_num=260;%探测器通道个数
% P=ParallelBFP(theta,N,P_num);%解析法产生投影数据
P=radon(I,theta);
%获取投影矩阵%
delta=1;%网格大小
[W_ind,W_dat]=SystemMatrixV2(theta,N,P_num,delta);
%进行ART迭代
F=zeros(N2,1);
lambda=0.25;
c=0;
irt_num=10;
while (c<irt_num)
    for j=1:length(theta)
      for i=1:1:P_num
          %取得一条射线所穿过的网格编号和长度
          u=W_ind((j-1)*P_num+i,:);%编号
          v=W_dat((j-1)*P_num+i,:);%长度
          %如果射线不经过任何像素,不作计算
          if any(u)==0
              continue;
          end
          %恢复投影矩阵中与这一条射线对应的行向量w
          w=zeros(1,N2);
          ind=find(u>0);
          w(u(ind))=v(ind);
          PP=w*F;
          error=P(i,j)-PP;
          C=error/sum(w.^2).*w';
          F=F+lambda*C;
      end
    end
    F(F<0)=0;%小于0的像素值置为0;
    c=c+1;
end
F=reshape(F,N,N)';
figure(1);
imshow(I);xlabel('(a)180*180头模型图像');
figure(2);
imshow(F);xlabel('(b)ART算法重建的图像');





%计算投影矩阵
function [W_ind,W_dat]=SystemMatrixV2(theta,N,P_num,delta)
%P_num:每个投影角度下的射线条数(探测器通道个数)
%delta:网格大小
%W_ind:存储投影射线所穿过的网格的编号的矩阵,M行,2*N列
%W_dat:存储投影射线所穿过的网格的长度的矩阵,M行,2*N列

%%用于验证的一小段程序
% theta=45;
% N=10;
% P_num=15;
% delta=1;
%------
N2=N^2;
M=length(theta)*P_num;%投影射线的总条数
W_ind=zeros(M,2*N);
W_dat=zeros(M,2*N);
% t_max=sqrt(2)*N*delta;
% t=linspace(-t_max/2,t_max/2,P_num);
t=(-(P_num-1)/2:(P_num-1)/2+1);
%t=(-(P_num-1)/2:(P_num-1)/2)*delta;%探测器坐标

for jj=1:length(theta)
    th=theta(jj);
    for ii=1:1:P_num
        %完成一条射线权因子向量的计算
        u=zeros(1,2*N);
        v=zeros(1,2*N);
       
        if th==0
            %如果超出网格范围,计算下一条
            if (t(ii)>=N/2*delta) || (t(ii)<=-N/2*delta)
                continue
            end
            kin=ceil(N/2+t(ii)/delta);
            kk=kin:N:(kin+N*(N-1));
            u(1:N)=kk;
            v(1:N)=ones(1,N)*delta;
           
            
        elseif th==90
            %如果超出网格范围,计算下一条
            if (t(ii)>=N/2*delta) || (t(ii)<=-N/2*delta)
                continue
            end
            kout=N*ceil(N/2-t(ii)/delta);
            kk=(kout-(N-1)):kout;
            u(1:N)=kk;
            v(1:N)=ones(1,N)*delta;
            %%投影角度等于0时%%
       
        else
            if th>90
                th_temp=th-90;
            elseif th<90
                th_temp=90-th;
            end
            th_temp=th_temp*pi/180;
            %确定射线y=mx+b的m和b
            b=t/cos(th_temp);
            m=tan(th_temp);
            y1d=(-N/2)*delta*m+b(ii);
            y2d=(N/2)*delta*m+b(ii);
            if (y1d<-N/2*delta && y2d<-N/2*delta)||(y1d>N/2*delta && y2d>N/2*delta)
                continue
            end
            %%确定入射点(xin,yin)、出射点(xout,yout)及参数d1%
            if y1d<=N/2*delta && y1d>=-N/2*delta && y2d>N/2*delta
                yin=y1d;
                yout=N/2*delta;
                xout=(yout-b(ii))/m;
                kin=N*floor(N/2-yin/delta)+1;
                kout=ceil(xout/delta)+N/2;
                d1=yin-floor(yin/delta)*delta;             
            elseif y1d<=N/2*delta && y1d>=-N/2*delta && y2d>=-N/2*delta && y2d<N/2*delta
                yin=y1d;
                yout=y2d;
                kin=N*floor(N/2-yin/delta)+1;
                kout=N*floor(N/2-yout/delta)+N;
                d1=yin-floor(yin/delta)*delta;
            elseif y1d<-N/2*delta && y2d>N/2*delta
                yin=-N/2*delta;
                yout=N/2*delta;
                xin=(yin-b(ii))/m;
                xout=(yout-b(ii))/m;
                kin=N*(N-1)+N/2+ceil(xin/delta);
                kout=ceil(xout/delta)+N/2;
                d1=N/2*delta+(floor(xin/delta)*delta*m+b(ii));
            elseif y1d<-N/2*delta && y2d>=-N/2*delta && y2d<N/2*delta
                yin=-N/2*delta;
                yout=y2d;
                xin=(yin-b(ii))/m;
                kin=N*(N-1)+N/2+ceil(xin/delta);
                kout=N*floor(N/2-yout/delta)+N;
                d1=N/2*delta+(floor(xin/delta)*delta*m+b(ii));
            else
                continue
            end
            %计算射线i穿过像素的编号和长度%
            k=kin;
            c=0;
            d2=d1+m*delta;
            while k>=1 && k<=N2
                c=c+1;
                if d1 >=0 && d2>delta
                    u(c)=k;
                    v(c)=(delta-d1)*sqrt(m^2+1)/m;
                    if k>N && k~=kout
                        k=k-N;
                        d1=d1-delta;
                        d2=d1+m*delta;
                    else
                        break;
                    end
                elseif d1>=0 && d2==delta
                    u(c)=k;
                    v(c)=delta*sqrt(m^2+1);
                    if  k>N && k~=kout
                        k=k-N-1;
                        d1=0;
                        d2=d1+m*delta;
                    else
                        break
                    end
                elseif d1>=0 && d2<delta
                    u(c)=k;
                    v(c)=delta*sqrt(m^2+1);
                    if k~=kout
                        k=k+1;
                        d1=d2;
                        d2=d1+m*delta;
                    else
                        break
                    end
                elseif d1<=0 && d2>=0 && d2<=delta
                    u(c)=k;
                    v(c)=d2*sqrt(m^2+1)/m;
                    if k~=kout
                        k=k+1;
                        d1=d2;
                        d2=d1+m*delta;
                    else
                        break
                    end
                elseif d1<=0 && d2>delta
                    u(c)=k;
                    v(c)=delta*sqrt(m^2+1)/m;
                    if k>N && k~=kout
                        k=k-N;
                        d1=d1-delta;
                        d2=d1+m*delta;
                    else
                        break
                    end
                elseif d1<=0 && d2==delta
                    u(c)=k;
                    v(c)=delta*sqrt(m^2+1)/m;
                    if k>N && k~=kout
                        k=k-N-1;
                        d1=0;
                        d2=m*delta;
                    else
                        break             
                    end
                end
              
            end
            %如果投影角度小于90,还需要利用投影射线关于y轴的对称性计算出权因子向量
            if th<90 
                u_temp=zeros(1,2*N);
                if any(u)==0
                    continue;
                end
                ind=find(u>0);
                for k=1:length(u(ind))
                    r=rem(u(k),N);
                    if r==0
                        u_temp(k)=u(k)-N+1;
                    else
                        u_temp(k)=u(k)-2*r+N+1;
                    end
                end
                u=u_temp;
            end
        end
        W_ind((jj-1)*P_num+ii,:)=u;
        W_dat((jj-1)*P_num+ii,:)=v;
    end
end

function P=ParalleBFP(theta,N,N_d)
shep=[1 .69 .92 0 0 0
    -.8 .6624 .8740 0 -.0184 0
    -.2 .1100 .3100 .22 0 -18
    -.2 .1600 .4100 -.22 0 18
    .1 .2100 .2500 0 .35 0
    .1 .0460 .0460 0 .1 0
    .1 .0460 .0460 0 -.1 0
    .1 .0460 .0230 -.08 -.605 0
    .1 .0230 .0230 0 -.606 0
    .1 .0230 .0460 .06 -.605 0];
theta_num=length(theta);
P=zeros(N_d,theta_num); %存放投影数据
rho=shep(:,1); %椭圆对应密度
ae=0.5*N*shep(:,2);%椭圆短半轴
be=0.5*N*shep(:,3);%椭圆长半轴
xe=0.5*N*shep(:,4);%椭圆中心x坐标
ye=0.5*N*shep(:,5);%椭圆中心y坐标
alpha=shep(:,6);%椭圆旋转角度
alpha=alpha*pi/180;
theta=theta*pi/180;%角度换算弧度
TT=-(N_d-1)/2:(N_d-1)/2;%探测器坐标
for k1=1:theta_num
    P_theta=zeros(1,N_d);
    for k2=1:max(size(xe))
        a =(ae(k2)*cos(theta(k1)-alpha(k2)))^2+(be(k2)*sin(theta(k1)-alpha(k2)))^2;
        temp=a-(TT-xe(k2)*cos(theta(k1))-ye(k2)*sin(theta(k1))).^2;
        ind=temp>0;%根号内值需为非负
        P_theta(ind)=P_theta(ind)+rho(k2)*(2*ae(k2)*be(k2)*sqrt(temp(ind)))./a;
    end
    P(:,k1)=P_theta;
end

相关推荐

  1. 医学CT成像的算法 SART和OS-SART算法

    2024-06-07 11:46:01       34 阅读
  2. 算法】归并排序(法)

    2024-06-07 11:46:01       17 阅读
  3. 算法】求平方根 - 二分法/牛顿

    2024-06-07 11:46:01       15 阅读
  4. ICP(最近点)定位算法

    2024-06-07 11:46:01       13 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-07 11:46:01       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-07 11:46:01       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-07 11:46:01       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-07 11:46:01       18 阅读

热门阅读

  1. 探索Web前端三大主流框架:React,Angular和Vue.js

    2024-06-07 11:46:01       9 阅读
  2. MongoDB 分布式 概述

    2024-06-07 11:46:01       7 阅读
  3. CSS中的长度单位详解

    2024-06-07 11:46:01       7 阅读
  4. 【面试题】Node.js高频面试题

    2024-06-07 11:46:01       10 阅读
  5. 开发常用的组件库

    2024-06-07 11:46:01       6 阅读
  6. Oracle 误删数据后回滚

    2024-06-07 11:46:01       8 阅读
  7. 正则表达式基础

    2024-06-07 11:46:01       7 阅读
  8. linux 如何解压 zip

    2024-06-07 11:46:01       8 阅读