Python实现平行束滤波反投影——Inverse Radon Transformation

参考博文进行了平行束滤波反投影的修改,将时域滤波修改为频域滤波,重建后消除原博文中图像的竖条状伪影。

https://blog.csdn.net/hsyxxyg/article/details/106433940

频域平行束滤波反投影(反radon变换)

产生频域滤波信号:
nextpow2函数的实现可参见github:

https://github.com/freenowill/Denoise-/blob/ba99babb685f6c80f07a23275c8c2127de601815/Denoise/nextpow2/nextpow2.py#L20

def Ramp(channNum,channSpacing): 
    N = 2**nextpow2(2*channNum-1)
    ramp = np.zeros(N)
    for i1 in range(-(channNum-1),(channNum-1)):
        if i1==0:
            ramp[i1+channNum] = 1/(4*channSpacing*channSpacing)
        elif i1 % 2 ==0:
            ramp[i1+channNum] = 0
        elif i1 % 2 ==1:
            ramp[i1+channNum] = -1/((i1*np.pi*channSpacing)**2)
    # ramp = channSpacing*np.abs(np.fft.fft(ramp))
    ramp = channSpacing*np.abs(fft(ramp))
    # ramp = fftshift(ramp)

    return ramp

进行滤波反投影:

def IRandonTransform2(image, steps):
    AglPerView = np.pi/steps
    channels = 512
    origin = np.zeros((steps, channels, channels))
    step = list(np.arange(0,1,1/100))
    step2 = step.copy()
    step2.reverse()
    # 防止truncation,在投影通道方向进行过渡
    # 如果sinogram通道方向的边界为0可以不进行过渡,否则重建图像的边缘可能会有一个亮环
    step_temp = image[0,:] # (360,)
    step_temp = np.expand_dims(step_temp,axis=0) # (1,360)
    step_temp = step_temp.repeat(100,axis=0) # (100,360)
    step = np.array(step) # (100,)
    step = np.expand_dims(step,axis=1) # (100,1)
    step = step.repeat(360,axis=1) # (100,360)
    step = step*step_temp # (100,360)

    step2_temp = image[-1,:] # (360,)
    step2_temp = np.expand_dims(step2_temp,axis=0) # (1,360)
    step2_temp = step2_temp.repeat(100,axis=0) # (100,360)
    step2 = np.array(step2) # (100,)
    step2 = np.expand_dims(step2,axis=1) # (100,1)
    step2 = step2.repeat(360,axis=1) # (100,360)
    step2 = step2*step2_temp # (100,360)    

    proj = np.concatenate((step,image,step2),axis=0) # (712,360)
    proj = np.concatenate((proj,np.zeros((2048-712,360)))) # (2048,360)

    sino_fft = fft(proj,axis=0) # (2048,360)

    '''卷积滤波(频域)'''
    filterData = Ramp(2*len(step)+512,0.5) # (2048,)
    iLen = len(filterData)
    filterData = np.expand_dims(filterData,axis=1) #(2048,1)
    filterData = filterData.repeat(360,axis=1) # (2048,360)

    image_filter = filterData*sino_fft # (2048,360)

    image_filter_ = ifft(image_filter,axis=0) # (2048,360)

    image_filter2 = np.real(image_filter_) # (2048,360)
    image_filter_final = image_filter2[100:512+100,:] # (512,360)
    image_filter3 = np.fliplr(image_filter_final) # (512,360)

    for i in range(steps): # viewNum
        projectionValueFiltered = image_filter3[:,i]
        projectionValueExpandDim = np.expand_dims(projectionValueFiltered, axis=0) # 1*512
        projectionValueRepeat = projectionValueExpandDim.repeat(channels, axis=0) # 512*512
        origin[i] = ndimage.rotate(projectionValueRepeat, 180+i*180/steps, reshape=False).astype(np.float64)
    iradon = np.sum(origin, axis=0)
    iradon = iradon*AglPerView

    return iradon,image_filter_final 

主函数中用到的读图小函数:

def readdat(file,shape):
    fid = open(file,'rb')
    nefid = fid.read()
    fid.close()
    neimage = np.reshape(np.frombuffer(nefid,dtype=np.float32),shape,'F')
    return  neimage 

def readdicom(filename):
    img = pydicom.dcmread(filename).pixel_array.astype('int64')-24
    return img

主函数:

import numpy as np
from scipy import ndimage
from scipy.signal import convolve
import matplotlib.pyplot as plt
import pydicom
from scipy.fftpack import fft,ifft,fftshift,ifftshift
import ctypes as ct 
import scipy.io as scio
import matplotlib.image as mpimg

ori_image = readdicom(r'E:\Metal Artifact Reduction\DLrelatedMAC_512_360_ratio1_noNorm\7_SimSource_img\noMetal\1_output_noM.dcm')
proj = readdat(r'E:\Metal Artifact Reduction\DLrelatedMAC_512_360_ratio1_noNorm\7_SimSource_img\Label_Train\1_label_train.dat',[512,360])
iradon,image_filter_final = IRandonTransform2(proj, 360)
plt.subplot(2, 2, 1)
plt.imshow(ori_image, cmap='gray')
plt.title('original image')
plt.subplot(2, 2, 2)
plt.imshow(iradon, cmap='gray')
plt.title('iradon image')
plt.subplot(2,2,3)
plt.imshow(proj,'gray')
plt.title('original projection')
plt.subplot(2,2,4)
plt.imshow(image_filter_final,'gray')
plt.title('filtered projection')
plt.show()

滤波反投影结果

对原始图像投影值进行Ramp滤波反投影的结果图

  • 2
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
由于没有提供具体的数据集和重建算法,以下代码仅提供基本的滤波函数实现: 1. RL滤波函数: ```matlab function h = RL_filter(N, d0, a) % N: filter size % d0: cutoff frequency % a: parameter h = zeros(N,1); for i = 1:N u = (i - N/2 - 1)/(N/2); if abs(u) <= d0/a h(i) = 1; elseif abs(u) > d0/a && abs(u) <= d0 h(i) = 0.5 * (1 + cos(pi*a*(abs(u)-d0/a)/(d0-d0/a))); else h(i) = 0; end end end ``` 2. SL滤波函数: ```matlab function h = SL_filter(N, d0, a) % N: filter size % d0: cutoff frequency % a: parameter h = zeros(N,1); for i = 1:N u = (i - N/2 - 1)/(N/2); if abs(u) <= d0/a h(i) = 1; elseif abs(u) > d0/a && abs(u) <= d0 h(i) = (d0 - abs(u))/(d0 - d0/a); else h(i) = 0; end end end ``` 3. Hamming窗函数: ```matlab function w = Hamming_window(N, alpha) % N: window size % alpha: parameter w = zeros(N,1); for i = 1:N w(i) = alpha - (1-alpha)*cos((2*pi*(i-1))/(N-1)); end end ``` 4. Hanning窗函数: ```matlab function w = Hanning_window(N) % N: window size w = zeros(N,1); for i = 1:N w(i) = 0.5 - 0.5*cos((2*pi*(i-1))/(N-1)); end end ``` 5. Cosine窗函数: ```matlab function w = Cosine_window(N) % N: window size w = zeros(N,1); for i = 1:N w(i) = sin((pi*(i-0.5))/N); end end ``` 6. 滤波反投影重建代码: ```matlab function img = FBPR_reconstruction(proj, theta, N, d, filter, window) % proj: projection data (N x n_theta) % theta: projection angles (n_theta x 1) % N: image size (N x N) % d: pixel size % filter: filter function (handle) % window: window function (N x N) n_theta = length(theta); img = zeros(N,N); for i = 1:n_theta % filtering proj(:,i) = filter_projection(proj(:,i), filter, N, d); % backprojection img = img + backprojection(proj(:,i), theta(i), N, d); end % windowing img = img .* window; % normalization img = img / (pi*n_theta/2); end function proj_f = filter_projection(proj, filter, N, d) % proj: projection data % filter: filter function (handle) % N: image size (N x N) % d: pixel size % FFT proj_f = fft(proj); % frequency axis freq = (-N/2:N/2-1)/(N*d); % filtering filter_f = filter(N, freq); proj_f = proj_f .* filter_f.'; % inverse FFT proj_f = ifft(proj_f); end function img_bp = backprojection(proj, theta, N, d) % proj: projection data % theta: projection angle % N: image size (N x N) % d: pixel size img_bp = zeros(N,N); % coordinates of image center xc = (N+1)/2; yc = (N+1)/2; % coordinates of image pixels [x,y] = meshgrid(1:N,1:N); x = (x - xc)*d; y = (y - yc)*d; % backprojection for i = 1:length(proj) t = theta(i); p = proj(i); img_bp = img_bp + p * interp1([cos(t-pi/2),cos(t+pi/2)],[x(:),y(:)],cos(t)*x(:)+sin(t)*y(:),'linear',0); end end ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值