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
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 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
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)
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
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
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
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)')
def iradon_recon(s, angles, filt): if reconstruct_sart: return iradon_sart(s, angles) else: return iradon(s, angles, filter=filt)
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)
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_iradon_sart_wrong_dtype(): sinogram = np.zeros((16, 1)) with pytest.raises(ValueError): iradon_sart(sinogram, dtype=int)
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)
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
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:
# 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
def slice(sinogram, theta): ''' Convert a sinogram to a slice ''' return iradon_sart(sinogram, theta)