def test_iradon_sart():
    debug = False

    image = rescale(PHANTOM, 0.8)
    theta_ordered = np.linspace(0., 180., image.shape[0], endpoint=False)
    theta_missing_wedge = np.linspace(0., 150., image.shape[0], endpoint=True)
    for theta, error_factor in ((theta_ordered, 1.),
                                (theta_missing_wedge, 2.)):
        sinogram = radon(image, theta, circle=True)
        reconstructed = iradon_sart(sinogram, theta)

        if debug:
            from matplotlib import pyplot as plt
            plt.figure()
            plt.subplot(221)
            plt.imshow(image, interpolation='nearest')
            plt.subplot(222)
            plt.imshow(sinogram, interpolation='nearest')
            plt.subplot(223)
            plt.imshow(reconstructed, interpolation='nearest')
            plt.subplot(224)
            plt.imshow(reconstructed - image, interpolation='nearest')
            plt.show()

        delta = np.mean(np.abs(reconstructed - image))
        print('delta (1 iteration) =', delta)
        assert delta < 0.02 * error_factor
        reconstructed = iradon_sart(sinogram, theta, reconstructed)
        delta = np.mean(np.abs(reconstructed - image))
        print('delta (2 iterations) =', delta)
        assert delta < 0.014 * error_factor
        reconstructed = iradon_sart(sinogram, theta, clip=(0, 1))
        delta = np.mean(np.abs(reconstructed - image))
        print('delta (1 iteration, clip) =', delta)
        assert delta < 0.018 * error_factor

        np.random.seed(1239867)
        shifts = np.random.uniform(-3, 3, sinogram.shape[1])
        x = np.arange(sinogram.shape[0])
        sinogram_shifted = np.vstack(np.interp(x + shifts[i], x,
                                               sinogram[:, i])
                                     for i in range(sinogram.shape[1])).T
        reconstructed = iradon_sart(sinogram_shifted, theta,
                                    projection_shifts=shifts)
        if debug:
            from matplotlib import pyplot as plt
            plt.figure()
            plt.subplot(221)
            plt.imshow(image, interpolation='nearest')
            plt.subplot(222)
            plt.imshow(sinogram_shifted, interpolation='nearest')
            plt.subplot(223)
            plt.imshow(reconstructed, interpolation='nearest')
            plt.subplot(224)
            plt.imshow(reconstructed - image, interpolation='nearest')
            plt.show()

        delta = np.mean(np.abs(reconstructed - image))
        print('delta (1 iteration, shifted sinogram) =', delta)
        assert delta < 0.022 * error_factor
Exemple #2
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)
Exemple #3
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
Exemple #4
0
def recon_scikit_sart(im, angles, iter):
	"""Reconstruct a sinogram with the SART 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.

	iterations : int
		Number of iterations for the SART technique.
	
	"""

	im = im.astype(double)	
	iter = int(iter)

	# Actual reconstruction with SART:
	rec = zeros((im.shape[1], im.shape[1]))
	for i in range(0, iter):      
		rec = iradon_sart(im.T, linspace(0, angles / pi * 180.0, im.shape[0]), rec)
	
	return rec.astype(float32)
Exemple #5
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
Exemple #6
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()
reconstruction techniques: the Simultaneous Algebraic Reconstruction Technique
(SART) [1]_ [4]_. It uses Kaczmarz' method [3]_ as the iterative solver. A good
reconstruction is normally obtained in a single iteration, making the method
computationally effective. Running one or more extra iterations will normally
improve the reconstruction of sharp, high frequency features and reduce the
mean squared error at the expense of increased high frequency noise (the user
will need to decide on what number of iterations is best suited to the problem
at hand. The implementation in ``skimage`` allows prior information of the
form of a lower and upper threshold on the reconstructed values to be supplied
to the reconstruction.

"""

from skimage.transform import iradon_sart

reconstruction_sart = iradon_sart(sinogram, theta=theta)
error = reconstruction_sart - image
print('SART (1 iteration) rms reconstruction error: %.3g'
      % np.sqrt(np.mean(error**2)))

fig, ax = plt.subplots(2, 2, figsize=(8, 8.5), sharex=True, sharey=True, subplot_kw={'adjustable':'box-forced'})
ax1, ax2, ax3, ax4 = ax.ravel()
ax1.set_title("Reconstruction\nSART")
ax1.imshow(reconstruction_sart, cmap=plt.cm.Greys_r)
ax2.set_title("Reconstruction error\nSART")
ax2.imshow(reconstruction_sart - image, cmap=plt.cm.Greys_r, **imkwargs)

# Run a second iteration of SART by supplying the reconstruction
# from the first iteration as an initial estimate
reconstruction_sart2 = iradon_sart(sinogram, theta=theta,
                                   image=reconstruction_sart)
def test_iradon_sart():
    debug = False

    image = rescale(PHANTOM, 0.8)
    theta_ordered = np.linspace(0., 180., image.shape[0], endpoint=False)
    theta_missing_wedge = np.linspace(0., 150., image.shape[0], endpoint=True)
    for theta, error_factor in ((theta_ordered, 1.), (theta_missing_wedge,
                                                      2.)):
        sinogram = radon(image, theta, circle=True)
        reconstructed = iradon_sart(sinogram, theta)

        if debug:
            from matplotlib import pyplot as plt
            plt.figure()
            plt.subplot(221)
            plt.imshow(image, interpolation='nearest')
            plt.subplot(222)
            plt.imshow(sinogram, interpolation='nearest')
            plt.subplot(223)
            plt.imshow(reconstructed, interpolation='nearest')
            plt.subplot(224)
            plt.imshow(reconstructed - image, interpolation='nearest')
            plt.show()

        delta = np.mean(np.abs(reconstructed - image))
        print('delta (1 iteration) =', delta)
        assert delta < 0.02 * error_factor
        reconstructed = iradon_sart(sinogram, theta, reconstructed)
        delta = np.mean(np.abs(reconstructed - image))
        print('delta (2 iterations) =', delta)
        assert delta < 0.014 * error_factor
        reconstructed = iradon_sart(sinogram, theta, clip=(0, 1))
        delta = np.mean(np.abs(reconstructed - image))
        print('delta (1 iteration, clip) =', delta)
        assert delta < 0.018 * error_factor

        np.random.seed(1239867)
        shifts = np.random.uniform(-3, 3, sinogram.shape[1])
        x = np.arange(sinogram.shape[0])
        sinogram_shifted = np.vstack(
            np.interp(x + shifts[i], x, sinogram[:, i])
            for i in range(sinogram.shape[1])).T
        reconstructed = iradon_sart(sinogram_shifted,
                                    theta,
                                    projection_shifts=shifts)
        if debug:
            from matplotlib import pyplot as plt
            plt.figure()
            plt.subplot(221)
            plt.imshow(image, interpolation='nearest')
            plt.subplot(222)
            plt.imshow(sinogram_shifted, interpolation='nearest')
            plt.subplot(223)
            plt.imshow(reconstructed, interpolation='nearest')
            plt.subplot(224)
            plt.imshow(reconstructed - image, interpolation='nearest')
            plt.show()

        delta = np.mean(np.abs(reconstructed - image))
        print('delta (1 iteration, shifted sinogram) =', delta)
        assert delta < 0.022 * error_factor
#
# ``skimage`` provides one of the more popular variations of the algebraic
# reconstruction techniques: the Simultaneous Algebraic Reconstruction
# Technique (SART) [4]_. It uses Kaczmarz' method as the iterative
# solver. A good reconstruction is normally obtained in a single iteration,
# making the method computationally effective. Running one or more extra
# iterations will normally improve the reconstruction of sharp, high
# frequency features and reduce the mean squared error at the expense of
# increased high frequency noise (the user will need to decide on what number
# of iterations is best suited to the problem at hand. The implementation in
# ``skimage`` allows prior information of the form of a lower and upper
# threshold on the reconstructed values to be supplied to the reconstruction.

from skimage.transform import iradon_sart

reconstruction_sart = iradon_sart(sinogram, theta=theta)
error = reconstruction_sart - image
print("SART (1 iteration) rms reconstruction error: "
      f"{np.sqrt(np.mean(error**2)):.3g}")

fig, axes = plt.subplots(2, 2, figsize=(8, 8.5), sharex=True, sharey=True)
ax = axes.ravel()

ax[0].set_title("Reconstruction\nSART")
ax[0].imshow(reconstruction_sart, cmap=plt.cm.Greys_r)

ax[1].set_title("Reconstruction error\nSART")
ax[1].imshow(reconstruction_sart - image, cmap=plt.cm.Greys_r, **imkwargs)

# Run a second iteration of SART by supplying the reconstruction
# from the first iteration as an initial estimate
Exemple #10
0
def iradon(sino, angles, filter='none'):
    """Wrapper for potentially a bunch of different backprojector
    implementations, wrapped with a common call signature. Selection of
    the implementation and specific parameters for individual implementations
    are pulled from the config file.

    Parameters
    ----------
    sino : 2d ndarray of floats
        sinogram to backproject
    angles : 1d array-like
        sinogram projection angles
    filter : str
        A string that selects the iradon filter type based on those supported by xlict.
        One of 'ramp', 'shepp-logan', 'cosine', 'hamming', 'hann', 'none'

    Returns
    -------
    2d ndarray of float32's

    """
    implementation = config.iradon_implementation

    if implementation == 'skimage_iradon':
        im = st.iradon(sino,
                       theta=angles,
                       circle=config.skimage_iradon_circle,
                       filter=config.skimage_iradon_filter)

    elif implementation == 'skimage_iradon_sart':
        # Clip solution to positive values. MLEM requires this.
        im = st.iradon_sart(sino,
                            theta=angles,
                            clip=(1e-6,
                                  sino.max() * sino.shape[0] * sino.shape[1]))

    elif implementation in ('xlict_recon_mpi_fbp', 'xlict_recon_gridrec'):
        outdir = config.xlict_recon_mpi_fbp_PATH_OUTPUT_DATA  # output directory
        indir = config.xlict_recon_mpi_fbp_PATH_INPUT_TIFFS  # input directory
        base_filename = 'temp_sino.tif'

        def xtract_exe_string(filename, indir, outdir, angles, ps):
            assert filter in {
                'ramp', 'shepp-logan', 'cosine', 'hamming', 'hann', 'none'
            }
            # lookup dict for reconstruction filter type and filter enable flag
            filter_control = {
                'ramp': (0, 1),
                'shepp-logan': (1, 1),
                'cosine': (2, 1),
                'hamming': (3, 1),
                'hann': (4, 1),
                'none': (0, 0),
            }

            recon_filter, filter_enable = filter_control[filter]
            rm = {
                'xlict_recon_mpi_fbp': 0,
                'xlict_recon_gridrec': 1
            }[implementation]
            xtract_options = \
                r'-id {indir} --sino {prg} -od {outdir} -pfct r_.tif -rmu 1 ' \
                r'-e {e_keV} --recon_method {rm} -fr {recon_filter} ' \
                r'-as {astep} --recon_filter_enabled {filter_enable} ' \
                r'-ps {ps} -corm {corm} --force_cpu {force_cpu}'.format(
                    indir=indir,
                    prg=filename,  # read file name
                    outdir=outdir,
                    e_keV=config.energy_keV,
                    rm=rm,  # 0 (FBP), 1 (Gridrec)
                    recon_filter=recon_filter,
                    filter_enable=filter_enable,
                    astep=angles[1] - angles[0],  # Angle step (deg)
                    ps=ps,  # pixel size (um)
                    force_cpu=config.xlict_force_cpu,
                    corm=config.xlict_recon_mpi_corm,  # centre-of-rot'n offset
                )
            return xtract_options

        sino = sino.T  # orient sinogram axes to what X-TRACT expects
        # write to disk for XTRACT
        filename = os.path.join(indir, base_filename)
        helpers.write_tiff32(filename, sino)

        # reconstruct (XLI/XTRACT writes the result to disk), then read result from disk
        xes = xtract_exe_string(base_filename, indir, outdir, angles, ps=1)
        PATH_XTRACT_EXE = config.xlict_recon_mpi_exe
        with open(os.devnull, 'w') as fnull:
            _ = subprocess.call('{} {}'.format(PATH_XTRACT_EXE, xes),
                                stdout=fnull,
                                stderr=subprocess.STDOUT)

        im = helpers.read_tiff32(os.path.join(outdir, 'r_0.tif'))
        # Reorient the reconstruction to match the convention established by other
        # reconstructors here.
        im = im.T

        # Apply a hard circular mask to the result, to match the behaviour of skimage
        im = helpers.zero_outside_circle(im)

        # write im to the output path with name r_<nnn+1>.tif,
        # where nnn is the highest number in the existing files
        files = os.listdir(outdir)
        if 'r_0.tif' in files:
            matches = sorted(
                fnmatch.filter(files, 'r_[0-9][0-9][0-9][0-9].tif'))
            if not matches:
                dest = 'r_0000.tif'
            else:
                # files exist matching r_nnn.tif; get the highest and add 1
                nnn = int(matches[-1][2:5])
                dest = 'r_%04d.tif' % (nnn + 1)
            helpers.write_tiff32(os.path.join(outdir, dest), im)

        im *= 5e-5  # This factor was determined by direct comparison with iradon above

    return im
Exemple #11
0
def loadfile(fname,col): #load the imformation of the given colum of the textfile as np a numpy array
    return np.loadtxt(fname, usecols=(col,))
data1 = [] #blank list to append each measurement for each column
t = 361
theta = np.arange(0,t,18)

for i in theta: #loads each file for the representing angel
    x= loadfile("Scan4_"+str(i)+"Deg.txt",1)
    print(x)
    data1.append(x)

sinogram= np.column_stack(data1) # rearranges the data to form a projection sinogram obataned fro the files


y= loadfile("Scan4_0Deg.txt",0) + 10
reconstruction = iradon_sart(sinogram, theta=theta,relaxation=0.15) # reconstructed the image obatianed from the sinogram 
# variable to generated the indidual curves of coicidence signal 
errodata = data**(1/2) # error of each measurement which is proportional to the sqaureroot of the count
p = [0,1,2,3,4,5,6,7]
color = ['b', 'g', 'r', 'c', 'm', 'y', 'k','silver','navy','chocolate','lime']


# figure provides 3 different subplots
fig = plt.figure(figsize=(25, 10))
ax1 = plt.subplot2grid((2, 4),(0,2),colspan=2)
ax2 = plt.subplot2grid((2, 4),(0,0),colspan=2, rowspan=2)
ax3 = plt.subplot2grid((2, 4),(1,2),colspan=2)

#this plots the projection sinogram obtained from the multiple scans at different angels
ax1.imshow(sinogram, cmap='gray',extent=[0,t-1,-10,10],aspect='auto',interpolation='quadric')
ax1.set_ylabel('Projection Axis (mm)')
Exemple #12
0
 def iradon_recon(s, angles, filt):
     if reconstruct_sart:
         return iradon_sart(s, angles)
     else:
         return iradon(s, angles, filter=filt)
Exemple #13
0
theta = np.linspace(0., 180., max(image.shape), endpoint=False)
sinogram = radon(image, theta=theta, circle=False)
# print(sinogram.shape)
# print(theta)
# print(sinogram[10])
ax[1].set_title("Sinogram")
ax[1].set_xlabel("Sudut (deg)")
ax[1].set_ylabel("Posisi (pixels)")
ax[1].imshow(sinogram,
             extent=(0, 180, 0, sinogram.shape[0]),
             aspect='auto',
             cmap='Greys_r')

# fig.tight_layout()

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

# imkwargs = dict(vmin=-0.2, vmax=0.2)

# ax[2].set_title("Rekonstruksi Citra\nFiltered Backprojection")
# ax[0].set_title("Rekonstruksi Citra\nbackproj")
# ax[0].imshow(reconstruction_fbp, cmap='Greys_r')
# ax[3].set_title("Reconstruction error\nFiltered back projection")
# ax[3].imshow(reconstruction_fbp - image, cmap=plt.cm.Greys_r, **imkwargs)
plt.show()
with Image.open(file_path) as img:
    img = img.convert("L")
P = np.asarray(img) / 255.
plt.imshow(P, cmap=plt.cm.Greys_r)
plt.show()

sinogram = radon(P, theta=angles, circle=True)

# SART
iter = 30
relaxation = 0.8
weight = 1
max_iter = 5
epsilon = 1e-6

recon_SART = iradon_sart(sinogram, theta=angles, relaxation=relaxation)
last_error = np.mean((recon_SART - P) ** 2)
frames = []
for i in tqdm(range(iter)):
    recon_SART = iradon_sart(sinogram, theta=angles, image=recon_SART, relaxation=relaxation)
    frames.append(recon_SART)
    recon_SART = denoise_tv_bregman(recon_SART, weight=weight, max_iter=max_iter)
    frames.append(recon_SART)
    now_error = np.mean((recon_SART - P) ** 2)
    if abs(last_error - now_error) > epsilon:
        # print("ERROR:%04f" % now_error)
        last_error = now_error
    else:
        print("Finish!")
        break
plt.imshow(recon_SART, cmap=plt.cm.Greys_r)
Exemple #15
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()
Exemple #16
0
def test_iradon_sart_wrong_dtype():
    sinogram = np.zeros((16, 1))

    with pytest.raises(ValueError):
        iradon_sart(sinogram, dtype=int)
Exemple #17
0
def geometric_transformations(original_images, transformation):
    """
    geometric transformations
    :param original_images:
    :param transformation:
    :return:
    """

    nb_images, img_rows, img_cols, nb_channels = original_images.shape
    # TODO: checking number of channels and some customization for datasets
    # TODO: more variations, after testing is done
    transformed_images = []
    if (transformation == TRANSFORMATION.geo_radon):
        for img in original_images:
            img = (img - 0.5) * 2.
            if (nb_channels == 3):
                img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
            img = img.reshape(img_rows, img_cols)
            theta = np.linspace(-100., 180., max(img.shape), endpoint=False)
            img_trans = np.float32(radon(img, theta=theta, circle=True))
            img_trans = (img_trans / 2.) + 0.5
            if (nb_channels == 3):
                img_trans = cv2.cvtColor(img_trans, cv2.COLOR_GRAY2RGB)
            transformed_images.append(img_trans)
    elif (transformation == TRANSFORMATION.geo_iradon):
        for img in original_images:
            img = (img - 0.5) * 2.
            if (nb_channels == 3):
                img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
            img = img.reshape(img_rows, img_cols)
            theta = np.linspace(-100., 128., max(img.shape), endpoint=False)
            img_radon = radon(img, theta=theta, circle=True)
            img_trans = np.float32(iradon(img_radon, theta=theta, circle=True))
            if (nb_channels == 3):
                img_trans = cv2.cvtColor(img_trans, cv2.COLOR_GRAY2RGB)
            img_trans = (img_trans / 2.) + 0.5
            transformed_images.append(img_trans)
    elif (transformation == TRANSFORMATION.geo_iradon_sart):
        for img in original_images:
            img = (img - 0.5) * 2.
            if (nb_channels == 3):
                img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
            img = img.reshape(img_rows, img_cols)
            theta = np.linspace(-150., 150., max(img.shape), endpoint=False)
            img_radon = radon(img, theta=theta, circle=True)
            img_trans = np.float32(iradon_sart(img_radon, theta=theta))
            if (nb_channels == 3):
                img_trans = cv2.cvtColor(img_trans, cv2.COLOR_GRAY2RGB)
            img_trans = (img_trans / 2.) + 0.5
            transformed_images.append(img_trans)
    elif (transformation == TRANSFORMATION.geo_swirl):
        strength = 3
        radius = 65
        if (nb_channels == 3):
            strength = 1.5
            radius = 45
        for img in original_images:
            img_trans = swirl(img, strength=strength, radius=radius)
            transformed_images.append(img_trans)
    else:
        raise ValueError('{} is not supported.'.format(transformation))
    """
    stack images
    """
    transformed_images = np.stack(transformed_images, axis=0)

    if (nb_channels == 1):
        transformed_images = transformed_images.reshape(
            (nb_images, img_rows, img_cols, nb_channels))

    return np.array(transformed_images)
Exemple #18
0
m = max(image.shape)
theta = np.linspace(0, 180, m, endpoint=False)

transformed = radon(image, theta=theta, circle=True)

transformed += np.random.randn(*transformed.shape)

t0 = time.clock()
# interpolation='cubic' is 0.02 rms error better but 350 times slower
reconstructed = iradon(transformed, theta=theta, circle=True)
t1 = time.clock()
reconstructed2 = None
n = 10
for _ in range(n):
    reconstructed2 = iradon_sart(transformed,
                                 theta=theta,
                                 image=reconstructed2,
                                 clip=[0, 1])
t2 = time.clock()

print("seconds:")
print(t1 - t0)
print((t2 - t1) / n, "times", n)
print("")


def print_errors(difference):
    print("max error:", np.max(np.abs(difference)))
    print("rms error:", np.sqrt(np.mean(np.square(difference))))
    print("")

def test_iradon_sart():
    from skimage.io import imread
    from skimage import data_dir
    from skimage.transform import rescale, radon, iradon_sart

    debug = False

    shepp_logan = imread(os.path.join(data_dir, "phantom.png"), as_grey=True)
    image = rescale(shepp_logan, scale=0.4)
    theta_ordered = np.linspace(0., 180., image.shape[0], endpoint=False)
    theta_missing_wedge = np.linspace(0., 150., image.shape[0], endpoint=True)
    for theta, error_factor in ((theta_ordered, 1.),
                                (theta_missing_wedge, 2.)):
        sinogram = radon(image, theta, circle=True)
        reconstructed = iradon_sart(sinogram, theta)

        if debug:
            from matplotlib import pyplot as plt
            plt.figure()
            plt.subplot(221)
            plt.imshow(image, interpolation='nearest')
            plt.subplot(222)
            plt.imshow(sinogram, interpolation='nearest')
            plt.subplot(223)
            plt.imshow(reconstructed, interpolation='nearest')
            plt.subplot(224)
            plt.imshow(reconstructed - image, interpolation='nearest')
            plt.show()

        delta = np.mean(np.abs(reconstructed - image))
        print('delta (1 iteration) =', delta)
        assert delta < 0.016 * error_factor
        reconstructed = iradon_sart(sinogram, theta, reconstructed)
        delta = np.mean(np.abs(reconstructed - image))
        print('delta (2 iterations) =', delta)
        assert delta < 0.013 * error_factor
        reconstructed = iradon_sart(sinogram, theta, clip=(0, 1))
        delta = np.mean(np.abs(reconstructed - image))
        print('delta (1 iteration, clip) =', delta)
        assert delta < 0.015 * error_factor

        np.random.seed(1239867)
        shifts = np.random.uniform(-3, 3, sinogram.shape[1])
        x = np.arange(sinogram.shape[0])
        sinogram_shifted = np.vstack(np.interp(x + shifts[i], x,
                                               sinogram[:, i])
                                     for i in range(sinogram.shape[1])).T
        reconstructed = iradon_sart(sinogram_shifted, theta,
                                    projection_shifts=shifts)
        if debug:
            from matplotlib import pyplot as plt
            plt.figure()
            plt.subplot(221)
            plt.imshow(image, interpolation='nearest')
            plt.subplot(222)
            plt.imshow(sinogram_shifted, interpolation='nearest')
            plt.subplot(223)
            plt.imshow(reconstructed, interpolation='nearest')
            plt.subplot(224)
            plt.imshow(reconstructed - image, interpolation='nearest')
            plt.show()

        delta = np.mean(np.abs(reconstructed - image))
        print('delta (1 iteration, shifted sinogram) =', delta)
        assert delta < 0.018 * error_factor
Exemple #20
0
def test_iradon_sart():
    from skimage.io import imread
    from skimage import data_dir
    from skimage.transform import rescale, radon, iradon_sart

    debug = False

    shepp_logan = imread(os.path.join(data_dir, "phantom.png"), as_grey=True)
    image = rescale(shepp_logan, scale=0.4)
    theta_ordered = np.linspace(0., 180., image.shape[0], endpoint=False)
    theta_missing_wedge = np.linspace(0., 150., image.shape[0], endpoint=True)
    for theta, error_factor in ((theta_ordered, 1.), (theta_missing_wedge,
                                                      2.)):
        sinogram = radon(image, theta, circle=True)
        reconstructed = iradon_sart(sinogram, theta)

        if debug:
            from matplotlib import pyplot as plt
            plt.figure()
            plt.subplot(221)
            plt.imshow(image, interpolation='nearest')
            plt.subplot(222)
            plt.imshow(sinogram, interpolation='nearest')
            plt.subplot(223)
            plt.imshow(reconstructed, interpolation='nearest')
            plt.subplot(224)
            plt.imshow(reconstructed - image, interpolation='nearest')
            plt.show()

        delta = np.mean(np.abs(reconstructed - image))
        print('delta (1 iteration) =', delta)
        assert delta < 0.016 * error_factor
        reconstructed = iradon_sart(sinogram, theta, reconstructed)
        delta = np.mean(np.abs(reconstructed - image))
        print('delta (2 iterations) =', delta)
        assert delta < 0.013 * error_factor
        reconstructed = iradon_sart(sinogram, theta, clip=(0, 1))
        delta = np.mean(np.abs(reconstructed - image))
        print('delta (1 iteration, clip) =', delta)
        assert delta < 0.015 * error_factor

        np.random.seed(1239867)
        shifts = np.random.uniform(-3, 3, sinogram.shape[1])
        x = np.arange(sinogram.shape[0])
        sinogram_shifted = np.vstack(
            np.interp(x + shifts[i], x, sinogram[:, i])
            for i in range(sinogram.shape[1])).T
        reconstructed = iradon_sart(sinogram_shifted,
                                    theta,
                                    projection_shifts=shifts)
        if debug:
            from matplotlib import pyplot as plt
            plt.figure()
            plt.subplot(221)
            plt.imshow(image, interpolation='nearest')
            plt.subplot(222)
            plt.imshow(sinogram_shifted, interpolation='nearest')
            plt.subplot(223)
            plt.imshow(reconstructed, interpolation='nearest')
            plt.subplot(224)
            plt.imshow(reconstructed - image, interpolation='nearest')
            plt.show()

        delta = np.mean(np.abs(reconstructed - image))
        print('delta (1 iteration, shifted sinogram) =', delta)
        assert delta < 0.018 * error_factor
		xp = np.append(xp,[len(p)-1])
		yp = np.append(yp,yp[-1])
		
		# print type(yp),type(xp)
		#print xp, yp
		# Now interpolate to acquire 
		xnew = np.linspace(0, len(p),len(p))
		# print len(xnew)
		yinterp = np.interp(xnew, xp, yp)
		interp_projections.append(yinterp)

	interp_projections = np.array(interp_projections).transpose()

	reconstruction = iradon(interp_projections, theta=deg, circle=True)
	# SART reconstruction: 
	reconstruction_sart = iradon_sart(interp_projections, theta=np.array(deg))
	reconstruction_sart2 = iradon_sart(interp_projections, theta=np.array(deg),
                                   image=reconstruction_sart)

	rad = reconstruction_sart2
	if j == 0:
		# med = np.median(reconstruction)
		# std = 3*np.std(reconstruction)
		inter_min 			= interp_projections.min()
		inter_max 			= interp_projections.max()
		minimal_value_fbp 	= reconstruction.min()
		maximal_value_fbp 	= reconstruction.max()
		minimal_value_sart 	= reconstruction_sart2.min()
		maximal_value_sart 	= reconstruction_sart2.max()
	  	firstreconstruction = reconstruction_sart2
	else: 
Exemple #22
0
    # t_SinoBack = np.tile(t_ComplexBack, t_SudutProj*t_SensorInterp).reshape(t_SudutProj, t_SensorInterp)
    t_SinoBack = np.tile(t_ComplexBack,
                         t_SudutInterp * t_SensorInterp).reshape(
                             t_SudutInterp, t_SensorInterp)
    # print(t_SinoBack)

    ## Reconstruksi Citra
    # t_Theta = np.linspace(0., 360., t_SudutProj, endpoint=False)
    t_Theta = np.linspace(0., 360., t_SudutInterp, endpoint=False)
    t_SinoDeembeding = t_SinoSudutInterp - t_SinoBack
    # t_SinoDeembeding = t_SinoInterp-t_SinoBack
    # t_SinoDeembeding = t_SinoInterp
    # t_Reconstruction = iradon_sart(np.abs(t_SinoInterp.transpose()) - np.abs(t_SinoBack.transpose()), theta=t_Theta, relaxation=0.1)
    # t_Reconstruction = iradon_sart(np.abs(t_Sino.transpose()), theta=t_Theta, relaxation=0.1)
    t_Reconstruction = iradon_sart(np.abs(t_SinoDeembeding.transpose()),
                                   theta=t_Theta,
                                   relaxation=0.1)
    # for i in range(20):
    # t_Reconstruction = iradon_sart(np.abs(t_SinoDeembeding.transpose()), theta=t_Theta, relaxation=0.1)
    # t_Reconstruction = iradon(t_SinoDeembeding.transpose(), filter="ramp" ,interpolation="linear", circle=False, theta=t_Theta)
    # u_sinR = odt.sinogram_as_rytov(t_SinoDeembeding / t_SinoBack)
    # u_sinR = odt.sinogram_as_rytov(t_SinoSudutInterp)
    # angles = np.linspace(0, 2*np.pi, t_SudutInterp, endpoint=False)
    # res = 9.0
    # nmed = 2.4
    # lD = 1.5
    # fR = odt.backpropagate_2d(u_sinR, angles, res, nmed, lD * res)
    # nR = odt.odt_to_ri(fR, res, nmed)

    ## Interpolasi multivariate
    # t_InterpVal = 100
Exemple #23
0
def slice(sinogram, theta):
    '''
    Convert a sinogram to a slice
    '''
    return iradon_sart(sinogram, theta)