def bp(self, prj: np.ndarray, angle_ind: int = None):
        """Back-projection of a single sinogram line to the volume.

        Parameters
        ----------
        prj : numpy.array_like
            The sinogram to back-project or a single line.
        angle_ind : int, optional
            The angle index to foward project. The default is None.

        Returns
        -------
        numpy.array_like
            The back-projected volume.
        """
        filter_name = _set_filter_name(None)
        if angle_ind is None:
            vol = np.empty([self.prj_shape[-1], *self.vol_shape],
                           dtype=prj.dtype)
            for ii_a, a in enumerate(self.angles_rot_deg):
                vol[ii_a, ...] = skt.iradon(prj[ii_a, :, np.newaxis], [a],
                                            **filter_name)
            return vol.sum(axis=0)
        else:
            return skt.iradon(prj[:, np.newaxis],
                              self.angles_rot_deg[angle_ind:angle_ind + 1:],
                              **filter_name)
Beispiel #2
0
def baseline(sinogram, noisy_sinogram, sino_scale, theta):
    r"""
    Use filtered backprojection for baseline recon.

    Invert the radon transform using filtered backprojection for both
    the noise-free and noisy sinograms.

    Since the sinogram was scaled using sino_scale as described above,
    we need to apply the inverse scaling to the reconstructions.

    Args:
        sinogram: sinogram from get_scaled_sinogram
        noisy_sinogram: noisy sinogram from add_noise
        sino_scale: scale from get_scaled_sinogram
        theta: angles of the views in the sinogram

    Returns:
        Filtered backprojection for sinogram and noisy_sinogram
    """

    # Invert the radon transform in the noise-free and noisy cases
    fbp_recon = iradon(sinogram, theta=theta, circle=True, filter_name='ramp')
    fbp_noisy_recon = iradon(noisy_sinogram, theta=theta, circle=True,
                             filter_name='ramp')

    # Scale to recover the appropriate units
    fbp_recon = fbp_recon / sino_scale
    fbp_noisy_recon = fbp_noisy_recon / sino_scale

    return fbp_recon, fbp_noisy_recon
def check_iradon_center(size, theta, circle):
    debug = False
    # Create a test sinogram corresponding to a single projection
    # with a single non-zero pixel at the rotation center
    if circle:
        sinogram = np.zeros((size, 1), dtype=np.float)
        sinogram[size // 2, 0] = 1.0
    else:
        diagonal = int(np.ceil(np.sqrt(2) * size))
        sinogram = np.zeros((diagonal, 1), dtype=np.float)
        sinogram[sinogram.shape[0] // 2, 0] = 1.0
    maxpoint = np.unravel_index(np.argmax(sinogram), sinogram.shape)
    print("shape of generated sinogram", sinogram.shape)
    print("maximum in generated sinogram", maxpoint)
    # Compare reconstructions for theta=angle and theta=angle + 180;
    # these should be exactly equal
    reconstruction = iradon(sinogram, theta=[theta], circle=circle)
    reconstruction_opposite = iradon(sinogram, theta=[theta + 180], circle=circle)
    print("rms deviance:", np.sqrt(np.mean((reconstruction_opposite - reconstruction) ** 2)))
    if debug:
        import matplotlib.pyplot as plt

        imkwargs = dict(cmap="gray", interpolation="nearest")
        plt.figure()
        plt.subplot(221)
        plt.imshow(sinogram, **imkwargs)
        plt.subplot(222)
        plt.imshow(reconstruction_opposite - reconstruction, **imkwargs)
        plt.subplot(223)
        plt.imshow(reconstruction, **imkwargs)
        plt.subplot(224)
        plt.imshow(reconstruction_opposite, **imkwargs)
        plt.show()

    assert np.allclose(reconstruction, reconstruction_opposite)
def check_radon_iradon_circle(interpolation, shape, output_size):
    # Forward and inverse radon on synthetic data
    image = _random_circle(shape)
    radius = min(shape) // 2
    sinogram_rectangle = radon(image, circle=False)
    reconstruction_rectangle = iradon(sinogram_rectangle,
                                      output_size=output_size,
                                      interpolation=interpolation,
                                      circle=False)
    sinogram_circle = radon(image, circle=True)
    reconstruction_circle = iradon(sinogram_circle,
                                   output_size=output_size,
                                   interpolation=interpolation,
                                   circle=True)
    # Crop rectangular reconstruction to match circle=True reconstruction
    width = reconstruction_circle.shape[0]
    excess = int(np.ceil((reconstruction_rectangle.shape[0] - width) / 2))
    s = np.s_[excess:width + excess, excess:width + excess]
    reconstruction_rectangle = reconstruction_rectangle[s]
    # Find the reconstruction circle, set reconstruction to zero outside
    c0, c1 = np.ogrid[0:width, 0:width]
    r = np.sqrt((c0 - width // 2)**2 + (c1 - width // 2)**2)
    reconstruction_rectangle[r > radius] = 0.
    print(reconstruction_circle.shape)
    print(reconstruction_rectangle.shape)
    np.allclose(reconstruction_rectangle, reconstruction_circle)
def calc_sirt(R, theta, Rmin, Rmax, nonnegconst, maxiter, nrows):

    R = (R - Rmin) / (Rmax - Rmin)

    S1 = np.sum(R)

    At = iradon(R, theta=theta, output_size=nrows)
    S2 = np.sum(At)
    At = (At / S2) * S1
    xk = At

    for k in range(maxiter):
        t = iradon(radon(xk, theta), theta)
        #normalize
        St = np.sum(t)
        t = (t / St) * S1
        #update using (At g - At A x_k)
        #new xk = xk + difference between reconstruction At_starting - t_previuous_step
        xk = xk + At - t

        if nonnegconst == 1:
            #delete values <0 aka not real!
            xk = xk.clip(min=0)

    return xk
Beispiel #6
0
def test_iradon_angles():
    """
    Test with different number of projections
    """
    size = 100
    # Synthetic data
    image = np.tri(size) + np.tri(size)[::-1]
    # Large number of projections: a good quality is expected
    nb_angles = 200
    theta = np.linspace(0, 180, nb_angles, endpoint=False)
    radon_image_200 = radon(image, theta=theta, circle=False)
    reconstructed = iradon(radon_image_200, circle=False)
    delta_200 = np.mean(
        abs(_rescale_intensity(image) - _rescale_intensity(reconstructed)))
    assert delta_200 < 0.03
    # Lower number of projections
    nb_angles = 80
    radon_image_80 = radon(image, theta=theta, circle=False)
    # Test whether the sum of all projections is approximately the same
    s = radon_image_80.sum(axis=0)
    assert np.allclose(s, s[0], rtol=0.01)
    reconstructed = iradon(radon_image_80, circle=False)
    delta_80 = np.mean(
        abs(image / np.max(image) - reconstructed / np.max(reconstructed)))
    # Loss of quality when the number of projections is reduced
    assert delta_80 > delta_200
Beispiel #7
0
def my_iradon(radon_image, theta=None, output_size=None, filter="ramp", interpolation="linear", circle=True):
    if not (type(output_size) is tuple):
        return iradon(
            radon_image,
            theta=theta,
            output_size=output_size,
            filter=filter,
            interpolation=interpolation,
            circle=circle
        )
    elif (output_size[0] - output_size[1]) % 2 > 0:
        raise Exception('margin size is not an integer')
    elif output_size[0] < output_size[1]:
        margin = int((output_size[1] - output_size[0]) / 2)
        image = iradon(
            radon_image,
            theta=theta,
            output_size=output_size[1],
            filter=filter,
            interpolation=interpolation,
            circle=circle
        )
        return image[margin:-margin, :]
    else:
        margin = int((output_size[0] - output_size[1]) / 2)
        image = iradon(
            radon_image,
            theta=theta,
            output_size=output_size[0],
            filter=filter,
            interpolation=interpolation,
            circle=circle
        )
        return image[:, margin:-margin]
Beispiel #8
0
def check_radon_iradon_circle(interpolation, shape, output_size):
    # Forward and inverse radon on synthetic data
    image = _random_circle(shape)
    radius = min(shape) // 2
    sinogram_rectangle = radon(image, circle=False)
    reconstruction_rectangle = iradon(sinogram_rectangle,
                                      output_size=output_size,
                                      interpolation=interpolation,
                                      circle=False)
    sinogram_circle = radon(image, circle=True)
    reconstruction_circle = iradon(sinogram_circle,
                                   output_size=output_size,
                                   interpolation=interpolation,
                                   circle=True)
    # Crop rectangular reconstruction to match circle=True reconstruction
    width = reconstruction_circle.shape[0]
    excess = int(np.ceil((reconstruction_rectangle.shape[0] - width) / 2))
    s = np.s_[excess:width + excess, excess:width + excess]
    reconstruction_rectangle = reconstruction_rectangle[s]
    # Find the reconstruction circle, set reconstruction to zero outside
    c0, c1 = np.ogrid[0:width, 0:width]
    r = np.sqrt((c0 - width // 2)**2 + (c1 - width // 2)**2)
    reconstruction_rectangle[r > radius] = 0.
    print(reconstruction_circle.shape)
    print(reconstruction_rectangle.shape)
    np.allclose(reconstruction_rectangle, reconstruction_circle)
def test_iradon_angles():
    """
    Test with different number of projections
    """
    size = 100
    # Synthetic data
    image = np.tri(size) + np.tri(size)[::-1]
    # Large number of projections: a good quality is expected
    nb_angles = 200
    radon_image_200 = radon(image, theta=np.linspace(0, 180, nb_angles,
                                                     endpoint=False))
    reconstructed = iradon(radon_image_200)
    delta_200 = np.mean(abs(_rescale_intensity(image) - _rescale_intensity(reconstructed)))
    assert delta_200 < 0.03
    # Lower number of projections
    nb_angles = 80
    radon_image_80 = radon(image, theta=np.linspace(0, 180, nb_angles,
                                                    endpoint=False))
    # Test whether the sum of all projections is approximately the same
    s = radon_image_80.sum(axis=0)
    assert np.allclose(s, s[0], rtol=0.01)
    reconstructed = iradon(radon_image_80)
    delta_80 = np.mean(abs(image / np.max(image) -
                           reconstructed / np.max(reconstructed)))
    # Loss of quality when the number of projections is reduced
    assert delta_80 > delta_200
    def fbp(self, prj: np.ndarray, fbp_filter: str):
        """Apply filtered back-projection of a sinogram or stack of sinograms.

        Parameters
        ----------
        prj : numpy.array_like
            The sinogram or stack of sinograms.
        fbp_filter : str
            The filter to use in the filtered back-projection.

        Returns
        -------
        vol : numpy.array_like
            The reconstructed volume.
        """
        filter_name = _set_filter_name(fbp_filter.lower())
        if len(prj.shape) > 2:
            num_lines = prj.shape[1]
            vol = np.empty([num_lines, *self.vol_shape], dtype=prj.dtype)

            for ii_v in range(num_lines):
                vol[ii_v, ...] = skt.iradon(prj[ii_v, ...].transpose(),
                                            self.angles_rot_deg, **filter_name)
            return vol
        else:
            return skt.iradon(prj.transpose(), self.angles_rot_deg,
                              **filter_name)
Beispiel #11
0
def main():
    image = imread(data_dir + "/phantom.png", as_gray=True)
    image = rescale(image, scale=0.2, mode='reflect', multichannel=False)

    fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(4.5, 12))

    ax1.set_title("Original")
    ax1.imshow(image, cmap=plt.cm.Greys_r)

    theta = np.linspace(0., 180., max(image.shape), endpoint=False)
    tic = time.time()
    sinogram = radon(image, theta=theta, circle=True)
    toc = time.time()
    ax2.set_title("Scikit Radon transform\n(t={0:.3f}s)".format(toc - tic))
    ax2.set_xlabel("Projection angle (deg)")
    ax2.set_ylabel("Projection position (pixels)")
    ax2.imshow(sinogram, cmap=plt.cm.Greys_r,
            extent=(0, 180, 0, sinogram.shape[0]), aspect='auto')

    pr = cProfile.Profile()
    pr.enable()
    tic = time.time()
    my_sinogram = my_radon(image, theta=theta, circle=True)
    toc = time.time()
    pr.disable()
    pr.print_stats(sort='cumtime')
    ax3.set_title("My Radon transform\n(t={0:.3f}s)".format(toc - tic))
    ax3.set_xlabel("Projection angle (deg)")
    ax3.set_ylabel("Projection position (pixels)")
    ax3.imshow(my_sinogram, cmap=plt.cm.Greys_r,
            extent=(0, 180, 0, my_sinogram.shape[0]), aspect='auto')

    fig.tight_layout()
    plt.show()

    reconstruction_fbp = iradon(sinogram, theta=theta, circle=True)
    my_reconstruction_fbp = iradon(my_sinogram, theta=theta, circle=True)

    error = reconstruction_fbp - image
    my_error = my_reconstruction_fbp - image

    imkwargs = dict(vmin=-0.2, vmax=0.2)
    fig, axes = plt.subplots(2, 2, figsize=(8, 4.5),
                                sharex=True, sharey=True)
    axes[0, 0].set_title("Reconstruction on\nScikit sinogram")
    axes[0, 0].imshow(reconstruction_fbp, cmap=plt.cm.Greys_r)
    axes[0, 1].set_title(f"Reconstruction error\n(error={np.sqrt(np.mean(error**2)):.3g})")
    axes[0, 1].imshow(reconstruction_fbp - image, cmap=plt.cm.Greys_r, **imkwargs)

    axes[1, 0].set_title("Reconstruction on\nmy sinogram")
    axes[1, 0].imshow(my_reconstruction_fbp, cmap=plt.cm.Greys_r)
    axes[1, 1].set_title(f"Reconstruction error\n(error={np.sqrt(np.mean(my_error**2)):.3g})")
    axes[1, 1].imshow(my_reconstruction_fbp - image, cmap=plt.cm.Greys_r, **imkwargs)

    plt.show()
Beispiel #12
0
def tiltaxisalign(im_series,tilt_angles,shift_and_tilt=('hold','hold')):
    series_shape = np.shape(im_series)
    
    new_series = im_series.copy()
    final_series = im_series.copy()
    
    #deg0_int = input('Which image is the 0 degree image? ')
    midy = int(series_shape[1]/2)
    
    axis_shift = shift_and_tilt[0]
    axis_tilt = shift_and_tilt[1]
    
    if axis_shift == 'hold':
        shift_continue = 1
    
        while shift_continue == 1:
            plt.imshow(iradon(np.rot90(new_series[:,midy,:]),  # rot
            theta = tilt_angles,output_size = series_shape[2]))# anti-clokwise
            plt.show()
            
            axis_shift = float(input('By how many pixels from the original mid-point should the tilt axis be shifted? '))
            
            for i in range(series_shape[0]):
                new_series[i,:,:] = interpolation.shift(im_series.copy()[i,:,:],(0,axis_shift)) # shift along np x-axis
                
            shift_continue = int(input('Would you like to apply further image shifts (1 for yes, 0 for no)? '))
                
    for i in range(series_shape[0]):
        final_series[i,:,:] = interpolation.shift(final_series[i,:,:],(0,axis_shift))
        
    topy = int(3*series_shape[1]/8)
    bottomy = int(5*series_shape[1]/8)

    if axis_tilt == 'hold':
        tilt_series = final_series.copy()
        tilt_continue = 1
        while tilt_continue == 1:
            plt.imshow(iradon(np.rot90(new_series[:,topy,:]), theta = tilt_angles,output_size = series_shape[2]))
            plt.show()
            plt.imshow(iradon(np.rot90(new_series[:,bottomy,:]), theta = tilt_angles,output_size = series_shape[2]))
            plt.show()
            
            axis_tilt = float(input('By what angle from the original y axis (in degrees) should the tilt axis be rotated? '))
            
            for i in range(series_shape[0]):
                new_series[i,:,:] = interpolation.rotate(tilt_series.copy()[i,:,:],axis_tilt,reshape=False)
                    
            tilt_continue = int(input('Would you like to try another tilt angle (1 for yes, 0 for no)? '))
                    
    for i in range(series_shape[0]):
        final_series[i,:,:] = interpolation.rotate(final_series[i,:,:],axis_tilt,reshape=False)
            
    shift_and_tilt = (axis_shift,axis_tilt)
            
    return(final_series, shift_and_tilt)
Beispiel #13
0
def test_iradon_dtype(preserve_range):
    sinogram = np.zeros((16, 1), dtype=int)
    sinogram[8, 0] = 1.
    sinogram64 = sinogram.astype('float64')
    sinogram32 = sinogram.astype('float32')

    assert iradon(sinogram, theta=[0],
                  preserve_range=preserve_range).dtype == 'float64'
    assert iradon(sinogram64, theta=[0],
                  preserve_range=preserve_range).dtype == sinogram64.dtype
    assert iradon(sinogram32, theta=[0],
                  preserve_range=preserve_range).dtype == sinogram32.dtype
Beispiel #14
0
def reconstruction(sinogram,
                   theta,
                   method='FBP',
                   output_size='None',
                   filter='ramp'):
    """Reconstructing with Filtered Back Projection by deflaut. Needs theta as 1D matrix, output_size 
	as a number or default and filter could be ramp, cosine..."""
    if method == 'FBP':
        if output_size == 'default':
            rec = iradon(sinogram.T, theta, filter=filter)
        else:
            rec = iradon(sinogram.T,
                         theta,
                         output_size=output_size,
                         filter=filter)
    return rec
Beispiel #15
0
def tomo_reconstruct_layer(rad_stack,cross_sectional_dim,layer_row=1024,start_tomo_ang=0., end_tomo_ang=360.,tomo_num_imgs=360, center=0.,pixel_size=0.00148):
    sinogram=np.squeeze(rad_stack[:,layer_row,:])

    rotation_axis_pos=-int(np.round(center/pixel_size))
    #rotation_axis_pos=13
    
    theta = np.linspace(start_tomo_ang, end_tomo_ang, tomo_num_imgs, endpoint=False)
    
    max_rad=int(cross_sectional_dim/pixel_size/2.*np.sqrt(2.))
    
    if rotation_axis_pos>=0:
        sinogram_cut=sinogram[:,2*rotation_axis_pos:]
    else:
        sinogram_cut=sinogram[:,:(2*rotation_axis_pos)]
    
    dist_from_edge=np.round(sinogram_cut.shape[1]/2.).astype(int)-max_rad                          
    
    sinogram_cut=sinogram_cut[:,dist_from_edge:-dist_from_edge]
    
    print('Inverting Sinogram....')
    reconstruction_fbp = iradon(sinogram_cut.T, theta=theta, circle=True)
    
    reconstruction_fbp=np.rot90(reconstruction_fbp,3)#Rotation to get the result consistent with hexrd, needs to be checked
    
    return reconstruction_fbp
Beispiel #16
0
def recon(dtheta, ax=None, axf1=None, axf2=None, filter="ramp"):
    dtheta = int(dtheta)
    theta = range(0, 180, dtheta)
    sinogram = st.radon(phantom, theta, circle=False)
    rc_phantom = st.iradon(sinogram, theta, circle=False, filter=filter)

    error = rc_phantom - phantom
    rms = np.sqrt(np.mean(error**2))

    ft = np.fft.fft2(rc_phantom, norm="ortho")
    ft[0, 0] = 0
    # ft = higt_pass_filter(ft, radius=0)
    spec = abs(np.fft.fftshift(ft))**2
    # maximum = np.max(spec)
    # spec /= maximum

    if ax:
        ax.imshow(rc_phantom, cmap=plt.cm.Greys_r)
        ax.set_title("{}˚, {}".format(dtheta, filter if filter else "None"))
        ax.set_xlabel("rms = {:.4f}".format(rms))
        ax.set_xticks([])
        ax.set_yticks([])
    if axf1:
        axf1.imshow(spec, cmap=plt.cm.Greys_r)
        axf1.axis("off")
    if axf2:
        slicef = spec[spec.shape[0] // 2]
        axf2.plot(slicef)
        axf2.axis([0, 160, 0, 1])
        axf2.set_xticks([])
        axf2.set_xlabel("frequency")
    return rms
    def fbp_reconstruction(self, theta=np.array([None]), backproject=False):
        """ Reconstruction from the low view CT sinograms.
		Inputs : 
		`theta` : 
		`backproject` : Do a backprojection instead of fbp
		"""

        # (expect artefacts even when reconstructing from pure sinusoids if image size is small)

        S_measured = self.measurement
        N = S_measured.shape[0]
        image_shape = self.shape[1::]

        assert self.shape[
            0] == N, 'Number of images not equal to number of sinograms'

        if (theta == None).all():
            num_thetas = S_measured.shape[2]
            theta = np.linspace(0., 179., num_thetas)

        if backproject == False:
            filt = 'ramp'
        else:
            filt = None

        recon = [
            iradon(S_measured[i], theta=theta, circle=False, filter=filt)
            for i in range(N)
        ]

        self.recon = np.array(recon)

        return self.recon
def core_denoise(sinogram,image_res,outerloops,innerloops,CGloops,
                     convtestnorm,lambdapen,thetas,jpegflag,
                     i,output,SVD_Flag):
    """ Core run through preprocessor and denoiser algorithm"""
    rec_FBP = iradon(sinogram[:,:,i],thetas,output_size = image_res,
                     circle = True, filter = 'hann')
    if (low_l2_meth == 0):
        TVrec,Err_diff = Radon_TV_Split_Bregman_LBFGS(sinogram[:,:,i],rec_FBP,
                                  thetas, outerloops,innerloops,image_res,
                                   convtestnorm,lambdapen,i)
    elif (low_l2_meth == 1):
        TVrec,Err_diff = PD_denoise(sinogram[:,:,i],rec_FBP,thetas,outerloops,
                                   innerloops,CGloops,image_res,convtestnorm,
                                   lambdapen,i)
    else:
        TVrec = rec_FBP  ,
        Err_diff = 0.
    print("[Slice %d] finished Split-Breg on Radon" )

    print("[Slice %d] is finished" % (i))
    output[:,:,i] = TVrec
    if jpegflag>0: #Want jpeg outputs
        filename = 'Slice'+str(i)+'.jpg'
        misc.imsave(filename,output[:,:,i])
    np.savetxt('Slice'+str(i)+'resid.txt',Err_diff)
def backproj(sinogram, FOV, ANGLES, symmetric, filter):
    theta = np.linspace(-int(FOV / 2),
                        int(FOV / 2),
                        ANGLES,
                        endpoint=symmetric)
    fbp_recon = iradon(sinogram, theta, circle=False, filter=filter)
    return fbp_recon
def test_torch_iradon():
    obj = imread(
        '/scratch0/ilya/locDoc/data/siim-medical-images/337/ID_0004_AGE_0056_CONTRAST_1_CT.png',
        as_grey=True)
    #obj = np.random.rand(256,256)
    ang = np.linspace(0., 180., 50, endpoint=False)
    proj = radon(obj, theta=ang, circle=False)
    # b 262
    # projG =
    rec = torch_iradon(proj, theta=ang, circle=False)
    rec2 = iradon(proj, theta=ang, circle=False)
    reconstructed = (
        rec.data).cpu().numpy()  # and get rid of first two dimensions
    rec3 = reconstructed[0, 0, :, :]
    im = Image.fromarray(rec3).convert('RGB')
    im.save('/cfarhomes/ilyak/Desktop/time.png')
    # plt.imshow(reconstructed[0,0,:,:], cmap='gray')
    # plt.show()
    # plt.imshow(rec2, cmap='gray')
    # plt.show()

    rec2n = (rec2 - np.min(rec2)) / (np.max(rec2) - np.min(rec2)) * 255.0
    rec3n = (rec3 - np.min(rec3)) / (np.max(rec3) - np.min(rec3)) * 255.0
    showme = plt.imshow(rec2n - rec3n)
    plt.colorbar(showme)
    plt.show()

    pdb.set_trace()
Beispiel #21
0
    def __init__(self, domain_dim, center=np.array([0])):

        self.domain_dim = domain_dim  # attention: self doppelt...
        self.center = center

        if not any(self.center):
            if len(self.domain_dim) == 2 and self.domain_dim[1] == 1:
                self.center = int((self.domain_dim[0] + 1) / 2)
            else:
                self.cemter = int((self.domain_dim + 1) / 2)

        # ToDO: input check

        if len(center) == 1:
            self.onevec = 1
        else:
            self.onevec = np.ones(len(self.domain_dim))

        roll_val = self.center - self.onevec

        self.theta = np.linspace(0., 180., 100,
                                 endpoint=False)  # max(self.domain_dim)

        fwfcthdl = lambda u: radon(u, theta=self.theta, circle=False)

        bwfcthdl = lambda f: iradon(f, theta=self.theta, circle=False)

        image_dim = (int(np.ceil(np.sqrt(2) * max(domain_dim))),
                     len(self.theta))

        super(CtRt, self).__init__(domain_dim, image_dim, fwfcthdl, bwfcthdl)
Beispiel #22
0
 def myAtA(self, img):
     img = img.cpu().detach().numpy()
     Aimg = radon(img, theta=self.theta, circle=True)
     AtAimg = iradon(Aimg, theta=self.theta)
     AtA = AtAimg + self.lam * img
     AtA = torch.from_numpy(AtA).cuda()
     return AtA
Beispiel #23
0
def SIRT(image,
         sinogram,
         theta,
         circle=True,
         alpha=0.1,
         n_iter=1e2,
         init=None):
    """
    image 再構成画像
    sinogram 投影データ
    theta 投影角度
    n_iter イテレーション
    """

    # initial
    if init is None:
        if circle == True:
            recon = np.zeros(image.shape)
            rr, cc = cir(image.shape[0] / 2, image.shape[1] / 2,
                         image.shape[0] / 2 - 1)
            recon[rr, cc] = 1
        else:
            recon = np.ones(image.shape)
    else:
        recon = init

    mse = []

    for iter in tqdm(range(n_iter), desc="sirt iter", leave=False):
        predict_image = radon(recon, theta, circle=circle)
        recon = recon + alpha * iradon(
            sinogram - predict_image, theta, circle=circle)

        recon[recon < 0] = 0
        recon[recon > 1] = 1

        if iter > 0:
            mse.append(mean_squared_error(recon, image))

        # make dir
        make_dir("result")
        make_dir("result/recon")
        make_dir("result/recon/sirt")
        make_dir("result/mse")

        # plot
        plt.imshow(recon)
        plt.colorbar()
        plt.title("sirt recon, iteration: %d" % (iter + 1))

        # save
        filename = "./result/recon/sirt/recon_sirt_iter" + str(iter + 1).zfill(
            3) + ".png"
        plt.savefig(filename)
        plt.pause(1)
        plt.close()

    np.save("./result/mse/mse_sirt.npy", mse)

    return recon
Beispiel #24
0
    def reconstruct(self, sinogram, centre_of_rotations, angles, vol_shape):
        in_pData = self.get_plugin_in_datasets()[0]
        sinogram = np.swapaxes(sinogram, 0, 1)
        sinogram = self._shift(sinogram, centre_of_rotations)
        sino = sinogram.astype(np.float64)
        theta = np.linspace(0, 180, sinogram.shape[1])
        result = transform.iradon(
            sino,
            theta=theta,
            output_size=(in_pData.get_shape()[1]),
            # self.parameters['output_size'],
            filter="ramp",  # self.parameters['filter'],
            interpolation="linear",
            # self.parameters['linear'],
            circle=False,
        )  # self.parameters[False])

        for i in range(self.parameters["iterations"]):
            print "Iteration %i" % i
            result = transform.iradon_sart(
                sino,
                theta=theta,
                image=result,
                # self.parameters['result'],
                projection_shifts=None,
                # self.parameters['None'],
                clip=None,
                # self.parameters[None],
                relaxation=0.15
                # self.parameters[0.15])
            )
        return result
Beispiel #25
0
 def reconstruct(self, sinogram, centre_of_rotation,
                 angles, shape, center):
     print sinogram.shape
     sinogram = np.swapaxes(sinogram, 0, 1)
     sinogram = self._shift(sinogram, centre_of_rotation)
     sino = np.nan_to_num(sinogram)
     theta = np.linspace(0, 180, sinogram.shape[1])
     result = \
         transform.iradon(sino, theta=theta,
                          output_size=(sinogram.shape[0]),
                          # self.parameters['output_size'],
                          filter='ramp',  # self.parameters['filter'],
                          interpolation='linear',
                          # self.parameters['linear'],
                          circle=False)  # self.parameters[False])
     for i in range(self.parameters["iterations"]):
         print "Iteration %i" % i
         result = transform.iradon_sart(sino, theta=theta, image=result,
                                        # self.parameters['result'],
                                        projection_shifts=None,
                                        # self.parameters['None'],
                                        clip=None,
                                        # self.parameters[None],
                                        relaxation=0.15
                                        # self.parameters[0.15])
                                        )
     return result
Beispiel #26
0
def iradon_and_save(sinogram_np, angles, wbp_dir, sart_dir, denoise_dir,
                    sart_denoise_dir):
    sinogram_np = sinogram_np * 0.6
    recon_np = iradon(sinogram_np, angles)[20:276, 20:276]
    Image.fromarray(recon_np * 255).convert("L").save(wbp_dir)
    recon_np = recon_np[np.newaxis, np.newaxis, :]
    tensor = torch.Tensor(recon_np).float()
    tensor = tensor.cuda(device)
    with torch.no_grad():
        out = model(tensor).detach()

    recon_np = out.cpu().numpy()[0][0] * 255
    Image.fromarray(recon_np).convert("L").save(denoise_dir)
    # ---------------------------
    recon_np = None
    for _ in range(10):
        recon_np = iradon_sart(sinogram_np.astype(np.float),
                               angles,
                               image=recon_np,
                               relaxation=0.25)
    recon_np = recon_np[20:276, 20:276]
    Image.fromarray(recon_np * 255).convert("L").save(sart_dir)
    recon_np = recon_np[np.newaxis, np.newaxis, :]
    tensor = torch.Tensor(recon_np).float()
    tensor = tensor.cuda(device)
    with torch.no_grad():
        out = model(tensor).detach()

    recon_np = out.cpu().numpy()[0][0] * 255
    Image.fromarray(recon_np).convert("L").save(sart_denoise_dir)
Beispiel #27
0
def get_fbp(ct_img, theta, circle=False, sart=False):
    """
    CT Img -> radon -> sinogram -> iradon -> FBP Img
    Using skimage transform method
    Parameters
    ----------
    theta :  projection angle in degree, dtype=np linspace
    circle : boolean, param of radon, default False
    sart : not implemented use only true, boolean, use iradon_sart, default False
    Returns
    -------
    sinogram, normalized fbp [0 1] ndarray
    Examples
    --------
    >>> sinogram, fbp = get_fbp(ct, theta)
    >>> plt.imshow(sinogram), plt.imshow(fbp)
    """
    if ct_img.min() < 0 or ct_img.max() > 1:
        raise ValueError("CT Img Range : [%d %d]" %
                         (ct_img.min(), ct_img.max()))

    sinogram = radon(ct_img, theta=theta, circle=circle)
    if sart is False:
        fbp = iradon(sinogram, theta=theta, circle=circle)
    else:
        # TODO: Check iradon_sart params
        raise NotImplementedError("not implemented sart")
        fbp = iradon_sart(sinogram, theta)

    if fbp.shape[0] != 512 or fbp.shape[1] != 512:
        raise ValueError("FBP Shape : [%d %d]" % (fbp.shape[0], fbp.shape[1]))

    np.clip(fbp, 0, 1, out=fbp)
    return sinogram, fbp
Beispiel #28
0
def reconstructImage(sinogram, theta, filter='ramp', inter='linear'):
    reconstructed_fbp = iradon(sinogram,
                               theta=theta,
                               circle=False,
                               filter=filter,
                               interpolation=inter)
    return reconstructed_fbp
Beispiel #29
0
    def test(self):
        self.load_model(self.test_epoch)
        self.model.eval()

        with torch.no_grad():
            # Must use the sample test dataset!!!
            X_fbp = torch.zeros_like(self.test_images)
            batch_size = self.test_images.shape[0]
            for i in range(batch_size):
                sino = self.test_data[i].squeeze()
                X0 = iradon(sino, theta=self.theta)
                X_fbp[i] = torch.from_numpy(X0)

            if self.model_name == "denoise_net":
                test_res = self.model(X_fbp.cuda().float())
            if self.model_name == "fista_net":
                [test_res, _] = self.model(X_fbp.cuda().float(),
                                           self.test_data.cuda().float())
                # torch.save(test_res, 'iteration_result.pt') # iteration result
                # test_res = test_res[5] # iteration result

            if self.model_name == "MoDL":
                test_res = self.model(X_fbp.cuda().float(),
                                      self.test_data.cuda().float())

        return test_res
Beispiel #30
0
    def process_frames(self, data):
        sino = data[0]
        centre_of_rotations, angles, vol_shape, init = self.get_frame_params()
        in_pData = self.get_plugin_in_datasets()[0]
        sinogram = np.swapaxes(sino, 0, 1)
        sinogram = self._shift(sinogram, centre_of_rotations)
        sino = sinogram.astype(np.float64)
        theta = np.linspace(0, 180, sinogram.shape[1])
        result = \
            transform.iradon(sino, theta=theta,
                             output_size=(in_pData.get_shape()[1]),
                             # self.parameters['output_size'],
                             filter='ramp',  # self.parameters['filter'],
                             interpolation='linear',
                             # self.parameters['linear'],
                             circle=False)  # self.parameters[False])

        for i in range(self.parameters["iterations"]):
            print "Iteration %i" % i
            result = transform.iradon_sart(
                sino,
                theta=theta,
                image=result,
                # self.parameters['result'],
                projection_shifts=None,
                # self.parameters['None'],
                clip=None,
                # self.parameters[None],
                relaxation=0.15
                # self.parameters[0.15])
            )
        return result
Beispiel #31
0
 def reconstruct(self, sinogram, centre_of_rotation, angles, shape, center):
     print sinogram.shape
     sinogram = np.swapaxes(sinogram, 0, 1)
     sinogram = self._shift(sinogram, centre_of_rotation)
     sino = np.nan_to_num(sinogram)
     theta = np.linspace(0, 180, sinogram.shape[1])
     result = \
         transform.iradon(sino, theta=theta,
                          output_size=(sinogram.shape[0]),
                          # self.parameters['output_size'],
                          filter='ramp',  # self.parameters['filter'],
                          interpolation='linear',
                          # self.parameters['linear'],
                          circle=False)  # self.parameters[False])
     for i in range(self.parameters["iterations"]):
         print "Iteration %i" % i
         result = transform.iradon_sart(
             sino,
             theta=theta,
             image=result,
             # self.parameters['result'],
             projection_shifts=None,
             # self.parameters['None'],
             clip=None,
             # self.parameters[None],
             relaxation=0.15
             # self.parameters[0.15])
         )
     return result
Beispiel #32
0
def slice_wise_iradon(sinograms, theta):
    recon_obj = np.zeros((Nx, ) + (min(Ny, Nz), ) * 2)
    for s in range(Nx):
        recon_obj[s, :, :] = st.iradon(sinograms[:, :, s],
                                       theta=theta,
                                       circle=True)
    return recon_obj
Beispiel #33
0
 def reconstructRad(self):
     self.reconstructedImage = abs(
         iradon(self.spectrum.T, theta=self.theta, circle=True))
     self.reconstructedImage = self.reconstructedImage - np.amin(
         self.reconstructedImage)
     self.reconstructedImage = self.reconstructedImage / np.amax(
         self.reconstructedImage)
def read_data(path, number_of_angles):

    training_images = []
    inverted_images = []
    th = np.linspace(0., 180., number_of_angles, endpoint=False)

    for file_name in glob.glob(path):  #+'/**/*.jpg', recursive=True):
        image = Image.open(file_name).resize((128, 128))
        image = np.asarray(image)

        max, min = image.max(), image.min()
        image = (image - min) / (max - min)

        training_images.append(image)
        inverted_images.append(
            iradon(radon(image, theta=th, circle=False, preserve_range=True),
                   circle=False))

    training_images = np.asarray(training_images)
    inverted_images = np.asarray(inverted_images)

    return np.expand_dims(
        inverted_images[:32256], axis=-1).astype('float32'), np.expand_dims(
            training_images[:32256],
            axis=-1).astype('float32'), np.expand_dims(
                inverted_images[32256:32768],
                axis=-1).astype('float32'), np.expand_dims(
                    training_images[32256:32768],
                    axis=-1).astype('float32'), np.expand_dims(
                        inverted_images[32768:],
                        axis=-1).astype('float32'), np.expand_dims(
                            training_images[32768:], axis=-1).astype('float32')
Beispiel #35
0
def _load_whole_data(current_version, file, dump_folder):
    hashstr = hashlib.sha256(
        ("".join(file) + current_version).encode()).hexdigest()
    dump_file = os.path.join(dump_folder, hashstr + ".h5")
    print(dump_file)
    rebuild_data = True
    if os.path.exists(dump_file):
        print("dump file existed")
        with h5py.File(dump_file, "r") as h5file:
            if "version" in list(h5file.keys()):
                if h5file["version"].value == current_version:
                    rebuild_data = False

    print("rebuild_data", rebuild_data)
    if rebuild_data:
        data = []
        mat_contents = sio.loadmat(file)
        gt = np.squeeze(mat_contents['data_gt'])
        sparse = np.zeros_like(gt)
        full = np.zeros_like(gt)

        for ind in range(gt.shape[2]):
            img = np.squeeze(gt[:, :, ind])
            theta = np.linspace(0., 180., 1e3, endpoint=False)
            sinogram = radon(img, theta=theta, circle=False)
            theta_down = theta[0:1000:20]
            sparse[:, :, ind] = iradon(sinogram[:, 0:1000:20],
                                       theta=theta_down,
                                       circle=False)
            full[:, :, ind] = iradon(sinogram, theta=theta, circle=False)
            print("iteration : ", ind, "/", gt.shape[2])

        norm_val = np.amax(sparse)
        print("norm_val", norm_val)
        print("finished rebuild")
        saveh5(
            {
                "label": full / norm_val * 255.,
                "sparse": sparse / norm_val * 255.,
                "version": current_version
            }, dump_file)

    f_handle = h5py.File(dump_file, "r")
    label = np.array(f_handle["label"])
    sparse = np.array(f_handle["sparse"])
    print("size of label, ", label.shape)
    print("size of sparse, ", sparse.shape)
Beispiel #36
0
 def sirt_xin(sinogram_np, angles, numIter=10):
     # SIRT
     # print("--start sirt_xin---")
     recon_SIRT = iradon(sinogram_np, theta=angles, filter=None, circle=True)
     for i in range(0, numIter):
         reprojs = radon(recon_SIRT, theta=angles, circle=True)
         ratio = sinogram_np / reprojs
         ratio[np.isinf(ratio)] = 1e8
         ratio[np.isnan(ratio)] = 1
         timet = iradon(ratio, theta=angles, filter=None, circle=True)
         timet[np.isinf(timet)] = 1
         timet[np.isnan(timet)] = 1
         recon_SIRT = recon_SIRT * timet
         # print('SIRT  %.3g' % i)
         # plt.imshow(recon_SIRT, cmap=plt.cm.Greys_r)
         # plt.show()
     return recon_SIRT
Beispiel #37
0
def radon_then_back_proj(img, N, ramp):
    angles = np.linspace(0, 180, N, endpoint=False)
    img_radon = transform.radon(img, theta=angles, circle=False)
    img_proj = transform.iradon(img_radon,
                                theta=angles,
                                circle=False,
                                filter_name='ramp' if ramp else None)
    return img_proj
Beispiel #38
0
def centreshift(data,angles,tiltrange,increment):
    series_shape = np.shape(data)
    new_series = data.copy()
    midy = int(series_shape[1]/2)
    for i in range(series_shape[0]):
        new_series[i,:,:] = interpolation.shift(data.copy()[i,:,:],(0,axis_shift))
        
    
    iradon(np.rot90(data[:,midy,:]), theta = angles,output_size = series_shape[2])
        
    
#if __name__ == "__main__":
    #x = hspy.load('C:/Users/Tom/Documents/TEM data/20150521_SS316needle/EDX Tomo/Cr/Signed_zero/cr_sub_hdr0_2.ali')
    '''x = h5py.File('C:/Users/Tom/Documents/TEM data/20150521_SS316needle/EDX Tomo/Cr/Signed_zero/cr_sub_hdr0_2_bin8.h5', "r")
    tilt_angles = np.linspace(-90.,90.,37)
    x_data = x['/0']
    reconstruction = reconstruct(x_data,tilt_angles)'''
    '''
def PD_denoise(sinogram,rec_FBP,thetas,outerloops,innerloops,
                           CGloops,image_res,convtestnorm,lambdapen,slicenum):

   """
   Solves the problem via the following formulation.  We minimize F(Ku)+G(u),
   where K:= (grad,R)^T and F(x):= ||x_1||_1+lambda/2||x_2-g||^2, and G(u):=0.
   Then, F^*(y) = \delta_p(y_1)+1/(2lambda)||y_2||^2+<g,y_2>.
   We then perform the primal dual algorithm of Chambolle-Pock '11.
   We assume it is better to have repeated G evaluations and fewer thing stored.
   Do not use; needs significant tuning/possible debugging.
   """
   uk = (TV_Split_utilities.generateSheppLogan(Phant_size))
   radius = min(uk.shape) // 2
   c0, c1 = np.ogrid[0:uk.shape[0], 0:uk.shape[1]]
   Circle_Mask = ((c0 - uk.shape[0] // 2) ** 2+ (c1 - uk.shape[1] // 2) ** 2)
   Circle_Mask = Circle_Mask <= 0.95*(radius ** 2)
   Circle_Mask = np.matrix(Circle_Mask)
   uk[0==Circle_Mask]=0.
   y_onek = np.gradient(0.*uk)
   y_twok = 0.*sinogram
   sigma = 1.e-2
   tau = 1.e-2
   theta = 1.
   ubark = uk
   Err_diff = np.zeros((int(.5*rec_FBP.size)))
   for i in range(int(.5*rec_FBP.size)):
        y_onek[0],y_onek[1], y_twok = resolvent_Fstar(y_onek[0]+sigma*
                  grad_one(ubark),y_onek[1]+sigma*grad_two(ubark),
                  y_twok+sigma*radon(ubark,thetas,circle=True),sigma,lambdapen,
                  sinogram)
        ubark = (1+theta)*resolvent_G(uk+tau*(-1.*Divu(y_onek)+iradon(y_twok,
                 thetas,output_size=image_res,circle=True,filter = 'ramp' )))-theta*uk
        ubark[0==Circle_Mask]=0.
        uk = resolvent_G(uk-tau*(-1.*Divu(y_onek)+iradon(y_twok,
                 thetas,output_size=image_res,circle=True,filter = 'ramp' )))
        uk[0==Circle_Mask]=0.
        Err_diff[i] = np.linalg.norm((ubark-uk)/theta)
        plt.imshow(uk);plt.pause(.0001)
        print('Slice %d]' %(slicenum))
        print('Outer Iterate = ' ,i)
        print('Update = ' ,Err_diff[i])
        if Err_diff[i]<1.e-5:
            break
   return uk,Err_diff
def tiff_sinos_pad(sinogram,flag,thetas):
    """
    Pads Octopus sinograms (after shape has been extracted elsewhere) so that
    applying radon to other data won't need a mask and will still be the right
    shape.  NOTE: Very Very hacked together.
    """
    from skimage.transform import radon, iradon
    if flag=='FBP':#apply Radon transform to FBP of sinogram to use as data
        imres=sinogram.shape[0]
        sinogram = radon(iradon(sinogram,thetas,output_size=imres,circle=True),
                         thetas,circle=False)
    elif flag=='pad':#Insert 0's into sinogram on either side
        imres=sinogram.shape[0]
        temp = radon(iradon(0.*sinogram,thetas,output_size=imres,circle=True),
                         thetas,circle=False)
        sizediff = abs(sinogram.shape[0]-temp.shape[0])
        if sizediff>0: #padding is needed
            sinogram = np.concatenate((temp[0:np.ceil(sizediff/2.),:],sinogram,
                                           temp[0:np.floor(sizediff/2.),:]))
    return sinogram
def low_L2_objgrad(u,sinogram, lambdapen,dkx,dky,bkx,bky,thetas,image_res,
                  Circle_Mask,TV,TVT,TVTTV):
    u = np.reshape(u,(image_res,image_res))
    u[0==Circle_Mask] = 0.
    dtheta = (thetas[1]-thetas[0])/180.
    dx = 1./image_res
    grad = (iradon(radon(u,thetas,circle = True)-sinogram,thetas,
                        output_size = image_res, circle = True,filter = None
                        ))*dtheta*dx*(2.*len(thetas))/np.pi
    grad -= dx*dx*((lambdapen*TVTTV*u+lambdapen*u*TVTTV) +lambdapen*(TVT*(dkx-
                bkx)+(dky-bky)*TV))
    return np.ravel(grad)
def check_radon_iradon_minimal(shape, slices):
    debug = False
    theta = np.arange(180)
    image = np.zeros(shape, dtype=np.float)
    image[slices] = 1.
    sinogram = radon(image, theta)
    reconstructed = iradon(sinogram, theta)
    print('\n\tMaximum deviation:', np.max(np.abs(image - reconstructed)))
    if debug:
        _debug_plot(image, reconstructed, sinogram)
    if image.sum() == 1:
        assert (np.unravel_index(np.argmax(reconstructed), image.shape)
                == np.unravel_index(np.argmax(image), image.shape))
Beispiel #43
0
def reconstruct(tilt_data,tilt_angles,algorithm='ASTRA_SIRT',iterations=20,geometry='parallel3d'):
    '''Function to reconstruct a tilt series.
    
    Data should be in the format (Angles,X,Y), where the tilt axis is situated about the mid column of the data.'''
    
    t0 = time.time()
    data_shape = np.shape(tilt_data)
    y_size = data_shape[1]
    
    recon = np.zeros((data_shape[2],y_size,data_shape[2]))
    #sino = np.zeros(data_shape)
    
    #Reconstruction using Filtered/Weighted Backprojection from skimage (check how filtering is done)
    if algorithm == 'SKI_FBP' or 'SKI_WBP':
        for y in range(0,y_size-1):
            recon[:,y,:] = iradon(np.rot90(tilt_data[:,y,:]), theta = tilt_angles,output_size = data_shape[2])
            
            #This is supposed to reorder axis to orientation for projection but not sure the x and y are correct
            for y in range(0,y_size-1):
                recon[:,y,:] = np.rot90(recon[:,y,:])
                recon[:,y,:] = np.rot90(recon[:,y,:])
                #recon[:,y,:] = np.rot90(recon[:,y,:])
            
    if algorithm == 'SKI_SART':
        for y in range(0,y_size-1):
            recon[:,y,:] = iradon_sart(np.rot90(tilt_data[:,y,:]), theta = tilt_angles,clip=(0,np.max(tilt_data)))
            
        if iterations > 1:
            for it in range(iterations-1):
                print("Iteration number "+str(it+2)+" in progress.")
                for y in range(0,y_size-1):
                    recon[:,y,:] = iradon_sart(np.rot90(tilt_data[:,y,:]), theta = tilt_angles,image=recon[:,y,:],clip=(0,np.max(tilt_data)))
                    
        #This is supposed to reorder axis to orientation for projection but not sure the x and y are correct
        for y in range(0,y_size-1):
            recon[:,y,:] = np.rot90(recon[:,y,:])
            recon[:,y,:] = np.rot90(recon[:,y,:])
            #recon[:,y,:] = np.rot90(recon[:,y,:])
                    
    if algorithm == 'ASTRA_SIRT':
        recon = astrarecon(tilt_data,tilt_angles,iterations,geometry)
      
        '''for z in xrange(0,data_shape[2]):
            recon[:,:,z] = np.rot90(recon[:,:,z])
            recon[:,:,z] = np.rot90(recon[:,:,z])
            recon[:,:,z] = np.rot90(recon[:,:,z])'''
        
    print("Reconstruction completed in {} seconds.".format(time.time() - t0))
            
    return(recon)
def inverAbel(x,y):
	x = numpy.array(x)
	y = list(y)
	dx = abs(x[1]-x[0])
	length = len(y)
	#~ print len(numpy.array(y*100))
	sino = numpy.array(y*100).reshape(100,length).transpose()
	reconstruction = iradon(sino)
	iry = reconstruction[:,math.ceil(len(reconstruction)*0.5)]/dx
	cropxs = int((length - len(iry))*0.5)-1
	cropxe = cropxs + len(iry)
	irx = x[cropxs:cropxe]
	#~ print len(irx),len(iry)
	return  irx,iry
 def reconstruct(self, sino, centre_of_rotations, angles, vol_shape, init):
     in_pData = self.get_plugin_in_datasets()[0]
     in_meta_data = self.get_in_meta_data()[0]
     sinogram = np.swapaxes(sino, 0, 1)
     sinogram = self._shift(sinogram, centre_of_rotations)
     theta = in_meta_data.get_meta_data('rotation_angle')
     result = \
         transform.iradon(sinogram, theta=theta,
                          output_size=(in_pData.get_shape()[1]),
                          # self.parameters['output_size'],
                          filter='ramp',  # self.parameters['filter'],
                          interpolation='linear',
                          # self.parameters['linear'],
                          circle=False)  # self.parameters[False])
     return result
def iridgelet(ridge):
    lvl, nr,nt = np.shape(ridge)
 #   for l in np.linspace(0,lvl-1,lvl):
#        x = ski.radon(ridge[l,:,:],theta = np.linspace(0,180-1,nt))
#        if l ==0:
#            nr,nt = np.shape(x)
#            rad_ridgelet = np.zeros((lvl,nr,nt))
#        rad_ridgelet[l,:,:] = x
    rad_ridgelet = ridge
    rad = np.zeros((nr,nt))
        
    for i in np.linspace(0,nt-1,nt):
        rad[:,i] = iuwt_1D(rad_ridgelet[:,:,i])
    img = ski.iradon(rad)
    return img
def check_radon_iradon(interpolation_type, filter_type):
    debug = False
    image = PHANTOM
    reconstructed = iradon(radon(image), filter=filter_type, interpolation=interpolation_type)
    delta = np.mean(np.abs(image - reconstructed))
    print("\n\tmean error:", delta)
    if debug:
        _debug_plot(image, reconstructed)
    if filter_type in ("ramp", "shepp-logan"):
        if interpolation_type == "nearest":
            allowed_delta = 0.03
        else:
            allowed_delta = 0.025
    else:
        allowed_delta = 0.05
    assert delta < allowed_delta
 def reconstruct(self, sinogram, centre_of_rotation,
                 angles, shape, center):
     print sinogram.shape
     sinogram = np.swapaxes(sinogram, 0, 1)
     sinogram = self._shift(sinogram, centre_of_rotation)
     sino = np.nan_to_num(sinogram)
     theta = np.linspace(0, 180, sinogram.shape[1])
     result = \
         transform.iradon(sino, theta=theta,
                          output_size=(sinogram.shape[0]),
                          # self.parameters['output_size'],
                          filter='ramp',  # self.parameters['filter'],
                          interpolation='linear',
                          # self.parameters['linear'],
                          circle=False)  # self.parameters[False])
     return result
def check_radon_iradon(interpolation_type, filter_type):
    debug = False
    image = PHANTOM
    reconstructed = iradon(radon(image, circle=False), filter=filter_type,
                           interpolation=interpolation_type)
    delta = np.mean(np.abs(image - reconstructed))
    print('\n\tmean error:', delta)
    if debug:
        _debug_plot(image, reconstructed)
    if filter_type in ('ramp', 'shepp-logan'):
        if interpolation_type == 'nearest':
            allowed_delta = 0.03
        else:
            allowed_delta = 0.025
    else:
        allowed_delta = 0.05
    assert delta < allowed_delta
def test_iradon_bias_circular_phantom():
    """
    test that a uniform circular phantom has a small reconstruction bias
    """
    pixels = 128
    xy = np.arange(-pixels / 2, pixels / 2) + 0.5
    x, y = np.meshgrid(xy, xy)
    image = x**2 + y**2 <= (pixels/4)**2

    theta = np.linspace(0., 180., max(image.shape), endpoint=False)
    sinogram = radon(image, theta=theta)

    reconstruction_fbp = iradon(sinogram, theta=theta)
    error = reconstruction_fbp - image
    
    tol = 5e-5
    roi_err = np.abs(np.mean(error))
    assert( roi_err < tol )
Beispiel #51
0
def recon_scikit_fbp(im, angles, filter_type):		
	"""Reconstruct a sinogram with the FBP algorithm of the Scikit-Image Python package

	Parameters
	----------
	im : array_like
		Sinogram image data as numpy array.

	angles : double
		Value in radians representing the number of angles of the input sinogram.

	filter_type : string
		A string with e.g. "ramp", "shepp-logan", "cosine", "hamming", "hann".
	
	"""
	# Filters: ramp, shepp-logan, cosine, hamming, hann
	# Interp: ‘linear’, ‘nearest’, and ‘cubic’
	rec = iradon(im.T, linspace(0, angles / pi * 180.0, im.shape[0], False), im.shape[1] , filter_type, 'nearest', True)
	
	return rec
    def process_frames(self, data):
        sino = data[0]
        centre_of_rotations, angles, vol_shape, init = self.get_frame_params()
        in_pData = self.get_plugin_in_datasets()[0]
        in_meta_data = self.get_in_meta_data()[0]
        sinogram = np.swapaxes(sino, 0, 1)
        sinogram = self._shift(sinogram, centre_of_rotations)
        theta = in_meta_data.get('rotation_angle')

        dim_detX = in_pData.get_data_dimension_by_axis_label('detector_x')
        size = self.parameters['output_size']
        size = in_pData.get_shape()[dim_detX] if size == 'auto' or \
            size is None else size

        result = \
            transform.iradon(sinogram, theta=theta,
                             output_size=(size),
                             filter=self.parameters['filter'],
                             interpolation=self.parameters['interpolation'],
                             circle=self.parameters['circle'])
        return result
Beispiel #53
0
def scikit_radon_back_projector(sinogram, geometry, range, out=None):
    """Calculate forward projection using scikit

    Parameters
    ----------
    sinogram : `DiscreteLpElement`
        Sinogram (projections) to backproject.
    geometry : `Geometry`
        The projection geometry to use.
    range : `DiscreteLp`
        range of this projection (volume space).
    out : ``range`` element, optional
        An element in range that the result should be written to.

    Returns
    -------
    sinogram : ``range`` element
        Sinogram given by the projection.
    """
    theta = scikit_theta(geometry)
    scikit_range = scikit_sinogram_space(geometry, range, sinogram.space)

    scikit_sinogram = scikit_range.element()
    scikit_sinogram.sampling(clamped_interpolation(range, sinogram))

    if out is None:
        out = range.element()
    else:
        # Only do asserts here since these are backend functions
        assert out in range

    out[:] = iradon(scikit_sinogram.asarray().T, theta,
                    output_size=range.shape[0], filter=None)

    # Empirically determined value, gives correct scaling
    scale = 4.0 * float(geometry.motion_params.length) / (2 * np.pi)
    out *= scale

    return out
 def _call(self, x):
     return self.range.element(iradon(x.asarray(), self.theta, self.npoint,
                                      filter=None))
Beispiel #55
0
phantom = np.zeros((phantomSize, phantomSize))

offset = (phantomSize - squareSize)/2

phantom[offset:offset+squareSize, offset:offset+squareSize] = squareAtt

nrProjections = 300
angleRange = 360.0
angleInc = nrProjections/angleRange
angles = np.linspace(0, angleRange, nrProjections)

sinogram = radon(phantom, theta=angles)

simple_backprojection = iradon(
        sinogram,
        theta=angles,
        filter=None,
        output_size=phantomSize
        )

filtered_backprojection = iradon(
        sinogram,
        theta=angles,
        filter="ramp",
        output_size=phantomSize
        )


fig, axes = plt.subplots(1, 3)
images = [phantom, simple_backprojection, filtered_backprojection]
names = ["phantom", "sbp", "fbp"]
image = imread(data_dir + "/phantom.png", as_grey=True)
image = zoom(image, 0.4)

plt.figure(figsize=(8, 8.5))

plt.subplot(221)
plt.title("Original");
plt.imshow(image, cmap=plt.cm.Greys_r)

plt.subplot(222)
projections = radon(image, theta=[0, 45, 90])
plt.plot(projections);
plt.title("Projections at\n0, 45 and 90 degrees")
plt.xlabel("Projection axis");
plt.ylabel("Intensity");

projections = radon(image)
plt.subplot(223)
plt.title("Radon transform\n(Sinogram)");
plt.xlabel("Projection axis");
plt.ylabel("Intensity");
plt.imshow(projections)

reconstruction = iradon(projections)
plt.subplot(224)
plt.title("Reconstruction\nfrom sinogram")
plt.imshow(reconstruction, cmap=plt.cm.Greys_r)

plt.subplots_adjust(hspace=0.4, wspace=0.5)
plt.show()
The mathematical foundation of the filtered back projection is the Fourier
slice theorem [2]_. It uses Fourier transform of the projection and
interpolation in Fourier space to obtain the 2D Fourier transform of the image,
which is then inverted to form the reconstructed image. The filtered back
projection is among the fastest methods of performing the inverse Radon
transform. The only tunable parameter for the FBP is the filter, which is
applied to the Fourier transformed projections. It may be used to suppress
high frequency noise in the reconstruction. ``skimage`` provides a few
different options for the filter.

"""

from skimage.transform import iradon

reconstruction_fbp = iradon(sinogram, theta=theta, circle=True)
error = reconstruction_fbp - image
print('FBP rms reconstruction error: %.3g' % np.sqrt(np.mean(error**2)))

imkwargs = dict(vmin=-0.2, vmax=0.2)
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4.5), sharex=True, sharey=True, subplot_kw={'adjustable':'box-forced'})
ax1.set_title("Reconstruction\nFiltered back projection")
ax1.imshow(reconstruction_fbp, cmap=plt.cm.Greys_r)
ax2.set_title("Reconstruction error\nFiltered back projection")
ax2.imshow(reconstruction_fbp - image, cmap=plt.cm.Greys_r, **imkwargs)
plt.show()

"""
.. image:: PLOT2RST.current_figure

Reconstruction with the Simultaneous Algebraic Reconstruction Technique
Beispiel #58
0
    def reconstruct(self, downsample=(4, 4), crop=True, median_filter=False, 
                    kernel=9, recon_alg='fbp', sart_iters=1, 
                    crop_circle=False, save=True, fancy_out=True):
        """
        Reconstruct the data using a radon transform. Reconstructed slices
        saved in folder specified upon class creation.

        # downsample: Downsample (local mean) data before reconstructing.
                      Specify mean kernel size (height, width).
        # pre_filter: If True apply median filter to data before reconstructing
        # kernel:     Kernel size to use for median filter
        """
            
        if self.cor_offset >= 0:
            images = self.im_stack[:, self.cor_offset:]
        else:
            images = self.im_stack[:, :self.cor_offset]
            
        images = images[:, :, self.p0:self.num_images + self.p0]
        
        if crop:
            left, right, top, bottom = self.crop
            images = images[top:bottom, left:right]
            
        images = downscale_local_mean(images, downsample + (1, ))
        recon_height, recon_width = images.shape[:2]
        self.recon_data = np.zeros((recon_width, recon_width, recon_height))

        if median_filter:
            print('Applying median filter...')
            for i in range(images.shape[-1]):
                sys.stdout.write('\rProgress: [{0:20s}] {1:.0f}%'.format('#' *
                                 int(20 * (i + 1) / images.shape[-1]),
                                 100 * ((i + 1) / images.shape[-1])))
                sys.stdout.flush()
                images[:, :, i] = medfilt(images[:, :, i], kernel_size=kernel)

        print('\nReconstructing...')
        if save:            
            save_folder = os.path.join(self.folder, 'reconstruction')
            
            if not os.path.exists(save_folder):
                os.makedirs(save_folder)
            for the_file in os.listdir(save_folder):
                file_path = os.path.join(save_folder, the_file)
                if os.path.isfile(file_path):
                        os.unlink(file_path)

        if fancy_out:
            fig, ax = plt.subplots(figsize=(4, 4))
            fig.canvas.set_window_title('Reconstruction')
            patch = Wedge((.5, .5), .375, 90, 90, width=0.1)
            ax.add_patch(patch)
            ax.axis('equal')
            ax.set_xlim([0, 1])
            ax.set_ylim([0, 1])
            ax.axis('off')
            t = ax.text(0.5, 0.5, '0%%', fontsize=15, ha='center', va='center')

        for j in range(recon_height):
            # Update figure every other slice
            if fancy_out and j % 2 == 0:
                patch.set_theta1(90 - 360 * (j + 1) / recon_height)
                progress = 100 * (j + 1) / recon_height
                t.set_text('%02d%%' % progress)
                plt.pause(0.001)
            else:
                sys.stdout.write('\rProgress: [{0:20s}] {1:.0f}%'.format('#' *
                                 int(20 * (j + 1) / recon_height),
                                 100 * ((j + 1) / recon_height)))
                sys.stdout.flush()
            sino_tmp = np.squeeze(images[j, :, :])
            
            if recon_alg is 'sart':
                image_tmp = iradon_sart(sino_tmp, theta=self.angles)
                for i in range(sart_iters - 1):
                    image_tmp = iradon_sart(sino_tmp, theta=self.angles, 
                                            image=image_tmp)
            else:
                image_tmp = iradon(sino_tmp, theta=self.angles, 
                                   filter=None, circle=True)
#            if crop_circle:
#                image_tmp = image_tmp[w0:wf, w0:wf]
                
            self.recon_data[:, :, j] = image_tmp
            
        if crop_circle:
            w = int((recon_width**2 / 2)**0.5) 
            w = w if (w - recon_width) % 2 == 0 else w - 1
            w0 = int((recon_width - w) / 2 )
            wf = int(w0 + w)
            self.recon_data = self.recon_data[w0:wf, w0:wf]
            
        if save:    
            for j in range(recon_height):
                image_tmp = self.recon_data[:, :, j]
                imsave(os.path.join(save_folder, '%04d.tif' % j), image_tmp)

        if fancy_out:
            plt.close()
def test_reconstruct_with_wrong_angles():
    a = np.zeros((3, 3))
    p = radon(a, theta=[0, 1, 2])
    iradon(p, theta=[0, 1, 2])
    assert_raises(ValueError, iradon, p, theta=[0, 1, 2, 3])
Beispiel #60
0
theta = np.linspace(0., 180., max(image.shape), endpoint=False)
sinogram    = radon(image, theta=theta, circle=True)

# add noise
if count > 0:
    val = sinogram.sum()
    sinogram    = np.random.poisson(sinogram / val * count).astype(np.float)
    sinogram    *= val / count

# normalization matrix
nview   = len(theta)
norm    = np.ones(shape)
wgts    = []
for sub in xrange(nsub):
    views   = range(sub, nview, nsub)
    wgt = iradon(norm[:, views], theta=theta[views], filter=None, circle=True)
    wgts.append(wgt)

# comparison OSEM, IRS
recons  = []
for b, rw, m in [(0, False, False), (beta, True, False), (beta, True, median)]:
    print   'beta', b, 'rw', rw
    
    # initial
    recon   = np.zeros(shape)
    rr, cc  = circle(shape[0] / 2, shape[1] / 2, shape[0] / 2 - 1)
    recon[rr, cc]   = 1

    if rw:
        weight  = np.ones(shape)