def super_lhsf(x0, tracer, factor=2): ## Extend sinogram to [0,2pi) m0, n0 = x0.shape n0_h = np.int(0.5 * n0) s_2pi = extend_full_period(x0) ig = np.unique(np.argwhere(s_2pi != tracer)[:, 1]) ib = np.unique(np.argwhere(s_2pi == tracer)[:, 1]) print(ig.shape) print(s_2pi.shape) print(s_2pi[:, ig].shape) print(n0_h) ## Resample each projection at cosinusoidal nodes s_2pi = s_2pi[:, ig].reshape(2 * m0, n0_h) sc_a = resampling_cosine_nodes(s_2pi) dis.plot(sc_a, 'SC') sc = np.zeros((2 * m0, 2 * sc_a.shape[1]), dtype=myfloat) print(sc.shape) print(sc_a.shape) sc[:, ::2] = sc_a sc[:, 1::2] = 0.0 dis.plot(sc, 'SC') m1, n1 = sc.shape mh1 = int(m1 * 0.5) nh1 = int(n1 * 0.5) ## Indexes for Fourier-Chebyshev filtering ic = get_ind_zerout(n1, m0) ## Get traced and non-traced elements sx = sc.copy() #sx[:,ib] = 0.0 nc = n1 norm = np.sqrt(1.0 / (2.0 * (nc + 1))) ## Decomposition and filter c = norm * fp.dst(sx, type=1, axis=1) b = np.fft.fftshift(np.fft.fft(c, axis=0), axes=0) b[ic[:, 0], ic[:, 1]] = 0.0 ## Reconstruction c[:] = np.real(np.fft.ifft(np.fft.ifftshift(b, axes=0), axis=0)) ci = np.imag(np.fft.ifft(np.fft.ifftshift(b, axes=0), axis=0)) sx_r = norm * fp.dst(c, type=1, axis=1) sx_i = norm * fp.dst(ci, type=1, axis=1) sx[:] = np.sqrt(sx_r**2 + sx_i**2) ## Renormalize sx[:] = factor * sx ## Crop original sinogram interval [0,pi) and first channel half (transl. of 1) sx = sx[:mh1, :] ## Interpolate back on equispaced nodes x = resampling_equisp_nodes(sx, n0) print('\n') return x
def main(): print('\n') print('#########################################################') print('#########################################################') print('### ###') print('### ANALYTICAL RADON TRANSFORM OF ###') print('### RADIALLY SYMMETRIC FUNCTIONS ###') print('### ###') print('#########################################################') print('#########################################################') print('\n') ## Get arguments args = getArgs() ## Get input parameters npix = args.npix nang = args.nang deg = args.degree dpc = args.dpc print('\nNumber of pixels: ', npix) print('Number of views: ', nang) print('Function degree: ', deg) print('Option DPC: ', dpc) ## Create LUT for the radially symmetric functions lut = create_lut(npix) ## Create Shepp-Logan phantom phantom = create_phantom(npix, deg, lut) ## Write phantom write_output_file(phantom, 'image', args) ## Plot phantom if args.plot is True: dis.plot( phantom, 'Radon phantom with ' + str(npix) + ' X ' + str(npix) + ' pixels') ## Compute analitically radon transform of the phantom if args.nang is not None: print('\nCalculating analytical radon transform of the phantom ....') sinogram = radon_transform_analytical(lut, npix, nang, deg, dpc) if args.dpc is False: sinogram[:, :] = sinogram[:, ::-1] sinogram[:, :] = np.roll(sinogram, 1, axis=1) ## Write sinogram write_output_file(sinogram, 'sinogram', args) ## Plot Shepp-Logan phantom if args.plot is True: dis.plot( sinogram, 'Sinogram ' + str(nang) + ' views X ' + str(npix) + ' pixels') print('\n\n')
def lhsf_analysis(s): ## Get dimensions of the sinogram na, n = s.shape ## Decompose sinogram into Fourier-Chebyshev basis b = decomposition(s) nc = b.shape[1] dis.plot(np.real(b), 'Fourier-Chebyshev decomposition') ## Zero-out coefficients at ( m , k ) s.t ( |m| > k ) or ( |m| + k even ) ii = get_ind_zerout(nc, na) ## Compute number and power percentage of wrong coefficients n_wro = len(ii) bb = b[ii[:, 0], ii[:, 1]] iii = np.argwhere(np.abs(bb) > 0.5) value = len(iii) / myfloat(n_wro) * 100.0 print('\nFourier-Chebyshev analysis of the forward projection:') print('Wrong Fourier-Chebyshev coefficients: ', value, ' %') pb_tot = np.linalg.norm(b) pb_wro = np.linalg.norm(bb) value = pb_wro / myfloat(pb_tot) * 100.0 print('Wrong Fourier-Chebyshev power: ', value, ' %\n') b[ii[:, 0], ii[:, 1]] = 0.0 ## Reverse FFT and sine transform sf = reconstruction(b, n) return sf
def main(): print('\nADD BLURRING TO IMAGES\n') ## Get input arguments args = getArgs() ## Get input and output path pathin = args.pathin if pathin[len(pathin) - 1] != '/': pathin += '/' if args.pathout is None: pathout = pathin else: pathout = args.pathout if pathout[len(pathout) - 1] != '/': pathout += '/' print('\nInput path:\n', pathin) print('\nOutput path:\n', pathout) ## Get single image filein = args.filein imagein = io.readImage(pathin + filein) nrows, ncols = imagein.shape print('\nReading image:\n', filein, '\n') print('Image size: ', nrows, ' X ', ncols) ## Check plot if args.plot is True: dis.plot(imagein, 'Input image') ## Allocate memory for the noisy temporary image image_blur = np.zeros((nrows, ncols), dtype=myfloat) ## Get blurring radii if args.sigma_range is None: sigma_list = args.sigma_list sigma_arr = np.array(sigma_list.split(':'), dtype=myfloat) nimg = len(sigma_arr) else: sigma_list = args.sigma_range sigma_list = np.array(sigma_list.split('-'), dtype=myfloat) sigma_arr = np.linspace(sigma_list[0], sigma_list[1], sigma_list[2]) nimg = len(sigma_arr) ## Loop on each gaussian sigma for im in range(nimg): ## Add gaussian noise image_blur[:, :] = add_gaussian_blurring(imagein, sigma_arr[im]) ## Check noisy image if args.plot is True: dis.plot(image_blur, 'Blurred image -- sigma: ' + str(sigma_arr[im])) ## Write noisy image to file write_output_file(pathout, filein, image_blur, sigma_arr[im])
def super_filt(sino, factor=2): nang, npix = sino.shape tracer = np.min(sino) - 100 factor = np.int(factor) if factor <= 1: factor = 2 npix_new = npix * factor ig = np.arange(0, npix_new, factor) ib = np.setdiff1d(np.arange(npix_new), ig) sino_new = np.zeros((nang, npix_new), dtype=myfloat) sino_new[:, ig] = sino sino_new[:, ib] = tracer dis.plot(sino_new, 'Starting') sino_new[:] = super_lhsf(sino_new, tracer) dis.plot(sino_new, 'Ending') sino_new[:, ig] = sino return sino_new
def main(): print('') print('######################################') print('######################################') print('#### ####') print('#### CALCULATE IMAGE COMPLEXITY ####') print('#### ####') print('######################################') print('######################################') ## Get input arguments args = getArgs() ## Read input image filein = args.pathin + args.filein image = io.readImage( filein ) nx , ny = image.shape print('\nReading input image:\n', filein) print('Image size: ', nx, ' X ', ny) if args.jpeg_compr <= 0 and args.jpeg_compr >= 100: args.jpeg_compr = 75 if args.plot is True: dis.plot( image , 'Input image' ) ## Calculate image complexity index based on JPEG compression complexity_jpeg( image , args ) ## Calculate image complexity index based on spatial information (SI) complexity_struct_info( image )
def admm(b, a, param): ## Get number of pixels and angles m, n, nz = param.nang, param.npix_op, param.nz b = np.array(b).astype(myfloat) rd = param.radon_degree ## Init forward and back-projector if param.projector == 'grid-pswf': tp = cpj1.projectors(n, a, kernel='pswf', oversampl=2.0, radon_degree=rd) elif param.projector == 'grid-kb': tp = cpj1.projectors(n, a, kernel='kb', oversampl=1.5, W=6.6, errs=6.0e-6, interp='lin', radon_degree=rd) elif param.projector == 'bspline': tp = cpj2.projectors(n, a, param, bspline_degree=3, proj_support_y=4, radon_degree=rd) elif param.projector == 'radon': tp = cpj2.projectors(n, a, param, bspline_degree=1, proj_support_y=2, radon_degree=rd) elif param.projector == 'pix-driv': tp = cpj3.projectors(n, a, oper='pd') elif param.projector == 'ray-driv': tp = cpj3.projectors(n, a, oper='rd') elif param.projector == 'dist-driv': tp = cpj3.projectors(n, a, oper='dd') elif param.projector == 'slant': tp = cpj3.projectors(n, a, oper='ss') ## Initialize x x = np.ones((nz, n, n), dtype=myfloat) if param.init_object is True: i1 = param.index_start i2 = param.index_end x_new = [] b_new = [] for i in range(nz): x[i, :, :] = tp.fbp(b[i, :, :]) if param.plot is True: dis.plot(x[i, :, :], 'Initialization') ## Reconstruction with CG if param.reg == 'cg': x[:], info = conj_grad(x, b, tp, param) ## Reconstruction with Lasso-L1 elif param.reg == 'lasso': x[:], info = lasso_l1(x, b, tp, param) ## Reconstruction with Lasso-TV elif param.reg == 'lasso-tv': x[:], info = lasso_tv(x, b, tp, param) ## Reconstruction with Plug-and-Play else: x[:], info = plug_and_play(x, b, tp, param) ## Conversion for bspline reconstruction and rotate if param.projector == 'bspline': for i in range(nz): x[i, :, :] = bfun.convert_from_bspline_to_pixel_basis( x[i, :, :], 3) x[:, :, :] = x[:, ::-1, ::-1] return x, info
def main(): ## Initial print print('\n') print('##########################################################') print('##########################################################') print('##### #####') print('##### ADMM Iterative Reconstruction #####') print('##### #####') print('##########################################################') print('##########################################################') print('\n') ## Get input arguments args = getArgs() ## Get input and output paths pathin, pathout = utils.get_io_path(args) print('\nInput path:\n', pathin) print('\nOutput path:\n', pathout) ## Get input sinogram sino_list = [] filein = [] if args.filein is not None: sinoname = pathin + args.filein sino = io.readImage(sinoname).astype(myfloat) if args.angle_pi is True: sino = sino[:sino.shape[0] - 1, :] nang, npix = sino.shape nz = 1 sino_list.append(sino) filein.append(args.filein) print('\nSinogram to reconstruct:\n', sinoname) else: print('\nReading stack of images\n') curr_dir = os.getcwd() os.chdir(pathin) for f in os.listdir('./'): if f.endswith('.DMP') is True: ext = '.DMP' break elif f.endswith('.tif') is True: ext = '.tif' break else: sys.exit('\nERROR: no .DMP or .tif file found in:\n' + pathin) filein.append(sorted(glob.glob('*' + ext))) nz = len(filein[0]) os.chdir(curr_dir) print('Stack extension: ', ext) print('Number of slices: ', nz) print('\nLoading images .... ') for i in range(nz): if i == 0: sino = io.readImage(pathin + filein[0][i]).astype(myfloat) nang, npix = sino.shape sino_list.append(sino) else: sino_list.append( io.readImage(pathin + filein[0][i]).astype(myfloat)) print(' done! ') print('\nNumber of projection angles: ', nang) print('Number of pixels: ', npix) ## Check plot if args.plot is True: if nz == 1: dis.plot(sino_list[0], 'Input sinogram') else: nzz = np.int(nz * 0.5) dis.plot(sino_list[nzz], 'Input sinogram') ## Center of rotation axis if args.ctr == -1: ctr = npix * 0.5 elif args.ctr != -1: ctr = args.ctr ## Enable edge padding if args.lt is True: edf = 0.87 elif args.lt is False and args.edge_padding != 0: edf = args.edge_padding else: edf = 0.0 if edf: npix_old = npix for i in range(nz): sino_list[i] = proc.sino_edge_padding(sino_list[i], edf) npix = sino_list[0].shape[1] i1 = myint((npix - npix_old) * 0.5) i2 = i1 + npix_old ctr += i1 print('\nEdge padding: ', edf) print('Number of edge-padded pixels: ', npix) print('Index start: ', i1, ' Index end: ', i2) print('Center of rotation axis new position: ', ctr) if args.plot is True: if nz == 1: dis.plot(sino_list[0], 'Sinogram with edge-padding') else: nzz = np.int(nz * 0.5) dis.plot(sino_list[nzz], 'Input sinogram') else: npix_old = npix i1 = 0 i2 = npix ## Compute differential sinogram if DBP option enabled if args.dbp is True: print('\nComputing differential sinogram ....') for i in range(nz): sino_list[i] = proc.diff_sino_savitzky_golay(sino_list[i], window_size=args.sg) if args.plot is True: dis.plot(sino_list[0], 'Differential sinogram') ## Correct for the center of rotation axis if args.ctr != -1: for i in range(nz): sino_list[i] = proc.sino_correct_rot_axis(sino_list[i], ctr) print('\nCenter of rotation axis position: ', ctr) print('Center of rotation corrected') ## Get geometry if args.geometry == '0': angles = utils.create_projection_angles(nang) else: angles = utils.create_projection_angles(textfile=pathin + args.geometry) ## Getting stopping criterion print('\nSetup of the iterative procedure:') if nz == 0: labelout = pathout + filein[0][:len(filein[0]) - 4] else: labelout = pathout + filein[0][0][:len(filein[0]) - 4] param = cap.admm_param(npix_old, nang, nz, ctr, labelout, args) print('Projectors enabled: ', args.projector) if args.dbp is True: print('DBP reconstruction enabled') if args.dpc is True: print('DPC reconstruction enabled') if args.n_iter is not None: print('Number of iterations: ', param.n_iter) if args.eps is not None: print('Stopping epsilon: ', param.eps) if args.n_iter_pcg is not None: print('Number of PCG iterations: ', param.n_iter_pcg) if args.plot is True: print('Interactive plot:', param.plot) if args.logfile is True: print('Interactive plot:', param.logfile) if param.reg is not None: if param.reg == 'cg': print('Conjugate gradient') if param.reg == 'lasso': print('Regularization type: Lasso L1') elif param.reg == 'lasso-tv': print('Regularization type: Lasso TV') elif param.reg == 'pp-breg': print('Regularization type: Plug and Play -- TV Bregman') elif param.reg == 'pp-chamb': print('Regularization type: Plug and Play -- TV Chambolle') elif param.reg == 'pp-nlmeans': print('Regularization type: Plug and Play -- Non Local Means') elif param.reg == 'pp-tgv': print( 'Regularization type: Plug and Play -- Total generalized variation' ) elif param.reg == 'pp-nltv': print( 'Regularization type: Plug and Play -- Non-local total variation' ) if param.reg != 'cg': print('\nLambda 1: ', param.lambd1) print('Lambda 2: ', param.lambd2) print('Mu: ', param.mu) if args.init_object is True: print('\nInitialization with FBP reconstruction:', param.init_object) if param.mask is not None: print('\nObject support enabled') if param.plot is True: dis.plot(param.mask, 'Object support') if param.mask_add is not None: print('\nAdditional supports provided') if param.plot is True: if param.mask_add_n == 1: dis.plot(param.mask_add[0]) else: dis.plot_multi(param.mask_add) if param.lt is True: print('\nLocal tomography mode enabled') ## Iterative reconstruction print('\n\nReconstructing with ADMM ....') time1 = time.time() reco_list, info = admm(sino_list, angles, param) time2 = time.time() print('.... reconstruction done!') for i in range(nz): ## Crop reconstruction if edge-padding enabled if edf != 0.0: reco = reco_list[i, i1:i2, i1:i2] else: reco = reco_list[i, :, :] ## Show reconstruction if args.plot is True and nz == 1 and args.reg != 'cg': dis.plot(reco, 'Reconstruction') plot_convergence_curves(info) elif args.plot is True and i == nzz and args.reg != 'cg': nzz = np.int(nz * 0.5) dis.plot(reco_list[nzz, :, :], 'Reconstruction of slice ' + str(nzz)) ## Save reconstruction if nz == 1: save_reco(pathout, filein[0], args, param, reco) else: save_reco(pathout, filein[0][i], args, param, reco) ## Time elapsed for the reconstruction time_tot = (time2 - time1) / 60.0 print('\nTime elapsed for the reconstruction: ', time_tot) ## Write log file if args.logfile is True: write_logfile(pathin, pathout, args, angles, ctr, param, time_tot, info) write_info(pathout, filein[0], info, param, args) ## Final print print('\n') print('\n') print('##########################################################') print('##########################################################') print('##### #####') print('##### ADMM Reconstruction done! #####') print('##### #####') print('##########################################################') print('##########################################################') print('\n')
def main(): ## Initial print print('\n') print('##########################################################') print('##########################################################') print('##### #####') print('##### STATISTICAL ITERATIVE RECONSTRUCTION #####') print('##### #####') print('##########################################################') print('##########################################################') print('\n') ## Getting arguments args = getArgs() ## Get input & output paths pathin, pathout = utils.get_io_path(args) print('\nInput path: \n', pathin) print('\nOutput path:\n', pathout) ## Get input sinogram sino_list = [] filein = [] if args.filein is not None: sinoname = pathin + args.filein sino = io.readImage(sinoname).astype(myfloat) nang, npix = sino.shape nz = 1 sino_list.append(sino) filein.append(args.filein) print('\nSinogram to reconstruct:\n', sinoname) else: print('\nReading stack of images\n') curr_dir = os.getcwd() os.chdir(pathin) for f in os.listdir('./'): if f.endswith('.DMP') is True: ext = '.DMP' break elif f.endswith('.tif') is True: ext = '.tif' break else: sys.exit('\nERROR: no .DMP or .tif file found in:\n' + pathin) filein.append(sorted(glob.glob('*' + ext))) nz = len(filein[0]) os.chdir(curr_dir) print('Stack extension: ', ext) print('Number of slices: ', nz) print('\nLoading images .... ') for i in range(nz): if i == 0: sino = io.readImage(pathin + filein[0][i]).astype(myfloat) nang, npix = sino.shape sino_list.append(sino) else: sino_list.append( io.readImage(pathin + filein[0][i]).astype(myfloat)) print(' done! ') print('\nNumber of projection angles: ', nang) print('Number of pixels: ', npix) ## Check plot if args.plot is True: if nz == 1: dis.plot(sino_list[0], 'Input sinogram') else: nzz = np.int(0.5 * nz) dis.plot(sino_list[nzz], 'Input sinogram') ## Center of rotation axis if args.ctr == -1: ctr = npix * 0.5 elif args.ctr != -1: ctr = args.ctr ## Enable edge padding if args.lt is True: edf = 0.87 elif args.lt is False and args.edge_padding != 0: edf = args.edge_padding else: edf = 0.0 if edf: npix_old = npix for i in range(nz): sino_list[i] = proc.sino_edge_padding(sino_list[i], edf) npix = sino_list[0].shape[1] i1 = myint((npix - npix_old) * 0.5) i2 = i1 + npix_old ctr += i1 print('\nEdge padding: ', edf) print('Number of edge-padded pixels: ', npix) print('Index start: ', i1, ' Index end: ', i2) print('Center of rotation axis new position: ', ctr) if args.plot is True: dis.plot(sino_list[0], 'Sinogram with edge-padding') else: npix_old = npix i1 = 0 i2 = npix ## Correct for the center of rotation axis if args.ctr != -1: for i in range(nz): sino_list[i] = proc.sino_correct_rot_axis(sino_list[i], ctr) print('\nCenter of rotation axis position: ', ctr) print('Center of rotation corrected') ## Get geometry if args.geometry == '0': angles = utils.create_projection_angles(nang) else: angles = utils.create_projection_angles(textfile=pathin + args.geometry) ## Setup iterative procedure print('\nSetup of the iterative procedure:') if nz == 0: labelout = pathout + filein[0][:len(filein[0]) - 4] else: labelout = pathout + filein[0][0][:len(filein[0]) - 4] param = csp.sir_param(nang, npix_old, nz, ctr, labelout, args) print('Selected projector: ', args.projector) if args.eps is not None: print('Stopping threshold: ', param.eps) if args.n_iter is not None: print('Number of iterations: ', param.n_iter) if args.plot is True: print('Interactive plot:', param.plot) if args.logfile is True: print('Interactive plot:', param.logfile) if param.reg is not None: if param.reg == 'huber': print('Regularization type: Huber penalty') print('Huber constant ---> delta: ') elif param.reg == 'tikhonov': print('Regularization type: l2 penalty') elif param.reg == 'haar': print('Regularization type: l1 penalty') print('Regularization constant (beta): ', param.reg_cost) if args.init_object is True: print('Initialization with FBP reconstruction:', param.init_object) ## Reconstruction print('\n\nPerforming STASTICAL ITERATIVE RECONSTRUCTION ....') time1 = time.time() reco_list, info = sir(sino_list, angles, param) time2 = time.time() print('.... reconstruction done!') for i in range(nz): ## Crop reconstruction if edge-padding enabled if edf != 0.0: reco = reco_list[i, i1:i2, i1:i2] else: reco = reco_list[i, :, :] ## Show reconstruction if args.plot is True and nz == 1: dis.plot(reco, 'Reconstruction') elif args.plot is True and i == nzz: dis.plot(reco, 'Reconstruction') ## Save reconstruction if nz == 1: save_reco(pathout, filein[0], args, param, reco) else: save_reco(pathout, filein[0][i], args, param, reco) ## Time elapsed for the reconstruction time_tot = (time2 - time1) / 60.0 print('\nTime elapsed for the reconstruction: ', time_tot) ## Write log file if args.logfile is True: write_logfile(pathin, pathout, args, angles, ctr, param, time_tot, info) write_info(pathout, filein[0], info, param, args) ## Final print print('\n') print('\n') print('##########################################################') print('##########################################################') print('##### #####') print('##### STATISTICAL ITERATIVE RECONSTRUCTION DONE! #####') print('##### #####') print('##########################################################') print('##########################################################') print('\n')
def sir(b, a, param): ## Get number of pixels and angles m, n, nz = param.nang, param.npix_op, param.nz b = np.array(b).astype(myfloat) ## Init forward and back-projector if param.projector == 'grid-pswf': tp = cpj1.projectors(n, a, kernel='pswf', oversampl=2.0) elif param.projector == 'grid-kb': tp = cpj1.projectors(n, a, kernel='kb', oversampl=1.5, W=6.6, errs=6.0e-6, interp='lin') elif param.projector == 'bspline': tp = cpj2.projectors(n, a, param, bspline_degree=3, proj_support_y=4) elif param.projector == 'radon': tp = cpj2.projectors(n, a, param, bspline_degree=1, proj_support_y=2) elif param.projector == 'pix-driv': tp = cpj3.projectors(n, a, oper='pd') elif param.projector == 'ray-driv': tp = cpj3.projectors(n, a, oper='rd') elif param.projector == 'dist-driv': tp = cpj3.projectors(n, a, oper='dd') elif param.projector == 'slant': tp = cpj3.projectors(n, a, oper='ss') ## Initialize x x = np.ones((nz, n, n), dtype=myfloat) if param.init_object is True: i1 = param.index_start i2 = param.index_end x_new = [] b_new = [] for i in range(nz): x[i, :, :] = tp.fbp(b[i, :, :]) if param.plot is True: dis.plot(x[i, :, :], 'Initialization') ## Reconstruction with CG if param.algorithm == 'em': print('\n\nUsing Maximum-Likelihood Expectation-Maximization') x[:], info = em(x, b, tp, param) ## Reconstruction with Lasso-L1 elif param.algorithm == 'sps': print('\n\nUsing Separable Paraboloidal Surrogate') x[:], info = sps(x, b, tp, param) ## Conversion for bspline reconstruction and rotate if param.projector == 'bspline': for i in range(nz): x[i, :, :] = bfun.convert_from_bspline_to_pixel_basis( x[i, :, :], 3) x[:, :, :] = x[:, ::-1, ::-1] return x, info
def main(): ## Initial print print( """\nThe program will execute in order 4 tests for the gridding implementation of the forward and backprojector""" ) print( """\nEvery time an image is displayed the code is temporarily halted. To the successive tests close the image""" ) ############################################################# ## Test n.1 ############################################################# inp = raw_input("\n\nProceed with test n.1? (y/n) ") if inp == "n": exit() print("###################################################") print("### ###") print("### TEST 1: Test adjoint operator ###") print("### ###") print("###################################################") test1() ############################################################# ## Test n.2 ############################################################# inp = raw_input("\n\nProceed with test n.2? (y/n) ") if inp == "n": exit() print("###################################################") print("### ###") print("### TEST 2: Test forward operator ###") print("### ###") print("###################################################") sino = test2() dis.plot(sino, "Forward projection 402 views X 256 pixels") ############################################################# ## Test n.3 ############################################################# inp = raw_input("\n\nProceed with test n.3? (y/n) ") if inp == "n": exit() print("###################################################") print("### ###") print("### TEST 3: Test Backprojector ###") print("### ###") print("###################################################") reco = test3(sino) dis.plot(reco, "Non-filtered backprojection") ############################################################# ## Test n.4 ############################################################# inp = raw_input("\n\nProceed with test n.4? (y/n) ") if inp == "n": exit() print("###################################################") print("### ###") print("### TEST 4: Test FBP ###") print("### ###") print("###################################################") reco = test4(sino) dis.plot(reco, "Reconstruction with Hanning filter")
def main(): ## Initial print print('\n') print('###########################################################') print('############# FORWARD REGRIDDING PROJECTOR #############') print('###########################################################') print('\n') ## Get the startimg time of the reconstruction time1 = time.time() ## Get input arguments args = getArgs() ## Get input/output directory pathin, pathout = utils.get_io_path(args) print('\nInput path:\n', pathin) print('\nOutput path:\n', pathout) ## Get input files file_list, file1, nimg, ext = utils.get_input(args, pathin) print('\nNumber of input files: ', nimg) print('Extension of the files: ', ext) ## Read first image image = io.readImage(pathin + file1).astype(myfloat) npix = image.shape[0] print('\nFirst image to forward project: ', file1) print('Number of pixels: ', npix) if args.plot is True: dis.plot(image, 'Input image') ## Get projection angles if args.geometry == '0' or args.geometry == '1': nang = args.nang angle_type = myint(args.geometry) if args.angle_range.find(':') == -1 or args.geometry == -1: angle_start = myfloat(args.angle_range) angle_end = angle_start + 180.0 else: angle_aux = args.angle_range.find(':') angle_start = myfloat(angle_aux[0]) angle_end = myfloat(angle_aux[1]) angles = utils.create_projection_angles(nang, angle_start, angle_end) else: angles = utils.create_projection_angles(pathin + args.geometry) nang = len(angles) print('\nNumber of views: ', nang) print('Selected angle range: [ ', angle_start, ' , ', angle_end, ' )') print('Angles:\n', angles) ## Initialize projectior class tp = cpj.projectors(npix, angles, args=args) ## Apply forward projection operator time_rec1 = time.time() sino = tp.A(image) time_rec2 = time.time() ## Display sinogram if args.plot is True: dis.plot(sino, 'Sinogram') ## Save sinogram save_sinogram(pathout, file1, angles, args, sino) ## Create sinograms from all the other images in the stack if args.filein is None: pool = mproc.Pool() for i in range(1, nimg): pool.apply_async(multi_thread, (pathin, pathout, file_list[0][i], angles, args)) pool.close() pool.join() time2 = time.time() print('\nTime elapsed to run the 1st forward gridrec: ', time_rec2 - time_rec1) print('Total time elapsed for the run of the program: ', time2 - time1) print('\n') print('#######################################') print('#### FORWARD PROJECTION DONE ! ####') print('#######################################') print('\n')
def main(): print('\nRESCALE IMAGE\n') ## Get input arguments args = getArgs() ## Get input and output path pathin = args.pathin if pathin[len(pathin) - 1] != '/': pathin += '/' if args.pathout is None: pathout = pathin else: pathout = args.pathout if pathout[len(pathout) - 1] != '/': pathout += '/' print('\nInput path:\n', pathin) print('\nOutput path:\n', pathout) ## Get single image if args.image is not None: ## Reading image filein = args.image imagein = io.readImage(pathin + filein) nrows, ncols = imagein.shape[0], imagein.shape[1] print('\nReading image:', filein) print('Image size: ', nrows, ' X ', ncols) ## Check plot if args.plot is True: dis.plot(imagein, 'Input image') ## Make image square if args.square is True: if nrows < ncols: imagein = imagein[:, :nrows] else: imagein = imagein[:ncols, :] ## Rescaled image if args.rescale is not None: rescale = args.rescale nrows_new = int(nrows * rescale) ncols_new = int(ncols * rescale) else: nrows_new = ncols_new = args.npix rescale = nrows_new / myfloat(nrows) image_rescale = rescale_image(imagein, rescale) print('\nRescaled factor: ', rescale) print('Rescaled-image size: ', image_rescale.shape) ## Check plot if args.plot is True: dis.plot(image_rescale, 'Rescaled image -- factor = ' + str(rescale)) ## Write noisy image to file fileout = filein[:len(filein) - 4] + '_pix' if nrows_new < 100: fileout += '00' + str(nrows_new) + '.DMP' elif nrows_new < 1000: fileout += '0' + str(nrows_new) + '.DMP' else: fileout += str(nrows_new) + '.DMP' io.writeImage(pathout + fileout, image_rescale) print('\nWriting rescaled image:', fileout) ## Get bunch of input images elif args.label is not None: curr_dir = os.getcwd() ## Reading images os.chdir(pathin) files = sorted(glob.glob('*' + args.label + '*')) os.chdir(curr_dir) num_im_input = len(files) for i in range(num_im_input): imagein = io.readImage(pathin + files[i]) nrows, ncols = imagein.shape[0], imagein.shape[1] print('\nReading image:\n', files[i]) print('\nImage size: ', nrows, ' X ', ncols) ## Make image square if args.square is True: if nrows < ncols: imagein = imagein[:, :nrows] else: imagein = imagein[:ncols, :] ## Rescaled image if args.rescale is not None: rescale = args.rescale nrows_new = int(nrows * rescale) ncols_new = int(ncols * rescale) else: nrows_new = ncols_new = args.npix rescale = nrows_new / myfloat(nrows) image_rescale = rescale_image(imagein, rescale) print('\nRescaled factor: ', rescale) print('Rescaled-image size: ', image_rescale.shape) ## Write noisy image to file fileout = files[i][:len(files[i]) - 4] + '_pix' if nrows_new < 100: fileout += '00' + str(nrows_new) + '.DMP' elif nrows_new < 1000: fileout += '0' + str(nrows_new) + '.DMP' else: fileout += str(nrows_new) + '.DMP' io.writeImage(pathout + fileout, image_rescale) print('\nWriting rescaled image:', fileout) print('\n\n')
def anti_alias_filt(sino, op='cubic', factor=2, bd=0.7, radius=2, reassign=True, plot=False): nang, npix = sino.shape tracer = np.min(sino) - 100 factor = np.int(factor) if factor <= 1: factor = 2 nang_new = nang * factor ig = np.arange(0, nang_new, factor) ib = np.setdiff1d(np.arange(nang_new), ig) sino_new = np.zeros((nang_new, npix), dtype=myfloat) sino_new[ig, :] = sino sino_new[ib, :] = tracer if plot is True: dis.plot(sino_new, 'Sinogram to inpaint') if op == 'pg1d': for i in range(npix): proj = sino_new[:, i] sino_new[:, i] = papoulis_gerchberg_1d(proj, tracer, bd=bd, niter=50, eps=1e-10) elif op == 'pg2d': sino_new[:] = papoulis_gerchberg_2d(sino_new, tracer, bd=bd, niter=50, eps=1e-10) elif op == 'zp1d': for i in range(npix): proj = sino[:, i] sino_new[:, i] = zero_padding(proj, mode='c') elif op == 'zp2d': sino_new[:] = zero_padding(sino, mode='a')[:, ::2] elif op == 'cubic': for i in range(npix): proj = sino_new[:, i] sino_new[:, i] = interp(proj, tracer, side=0, itype='cubic') elif op == 'navier': sino_new[:] = inpainting_navier_stokes(sino_new, tracer, radius=radius) elif op == 'telea': sino_new[:] = inpainting_telea(sino_new, tracer, radius=radius) if reassign is True: sino_new[ig, :] = sino return sino_new
def main(): print('\n') print('#######################################') print('#######################################') print('### ###') print('### STRUCTURAL SIMILARITY INDEX ###') print('### ###') print('#######################################') print('#######################################') print('\n') ## Get input arguments args = getArgs() ## Get oracle image currDir = os.getcwd() image1 = io.readImage(args.image1) image1 = image1.astype(myfloat) print('\nReading reference image:\n', args.image1) print('Image shape: ', image1.shape) image_list = [] results = [] ## CASE OF SINGLE IMAGE TO ANALYZE if args.image2 is not None: if args.image2.find(':') == -1: image_list.append(args.image2) image2 = io.readImage(args.image2) # image2 --> image to analyze image2 = image2.astype(myfloat) num_img = 1 print('\nReading image to analyze:\n', args.image2) print('Image shape: ', image2.shape) ## Get time in which the prgram starts to run time1 = time.time() ## Scale image to analyze with respect to the reference one if args.scaling is True: print('\nPerforming linear regression ....') image2 = proc.linear_regression(image1, image2) ## Register images if args.register is True: print('\nPerforming registration of the image to analize ....') image2 = proc.image_registration(image2, image1, 'ssd') ## Crop resolution circle of the images if args.resol_circle is True: print('\nSelecting the resolution circle') image1 = proc.select_resol_square(image1) image2 = proc.select_resol_square(image2) ## Crop images if enabled if args.roi is not None: roi = args.roi if roi.find(':') != -1: roi = roi.split(',') p0 = [int(roi[0].split(':')[1]), int(roi[0].split(':')[0])] p1 = [int(roi[1].split(':')[1]), int(roi[1].split(':')[0])] print('Cropping rectangular ROI with vertices: ( ', \ p0[0],' , ', p0[1], ') ( ', p1[0],' , ',p1[1], ')') image1 = proc.crop_image(image1, p0, p1) image2 = proc.crop_image(image2, p0, p1) else: print('\nUsing pixels specified in file:\n', roi) pixels = np.loadtxt(roi) pixels = pixels.astype(int) p0 = np.array([pixels[0, 0], pixels[0, 1]]) p1 = np.array([ pixels[len(pixels) - 1, 0], pixels[len(pixels) - 1, 1] ]) print('Cropping rectangular ROI with vertices: ( ', \ p0[0],' , ', p0[1], ') ( ', p1[0],' , ',p1[1], ')') image1 = proc.crop_image(image1, p0, p1) image2 = proc.crop_image(image2, p0, p1) ## Compute the gradient of the images, if enabled if args.gradient is True: image1 = compute_gradient_image(image1) image2 = compute_gradient_image(image2) ## Check whether the 2 images have the same shape if image1.shape != image2.shape: sys.error('\nERROR: The input images have different shapes!\n') ## Plot to check whether the images have the same orientation if args.plot is True: print('\nPlotting images to check orientation ....') img_list = [image1, image2] title_list = ['Oracle image', 'Image to analyze'] dis.plot_multi(img_list, title_list, 'Check plot') ## Get window size window_size = args.window print('\nSize of the computation window: ', window_size) if window_size % 2 != 0: window_size += 1 print('Window size is even: window size changed to ', window_size) ## Get sigma of the gaussian kernel sigma = SIGMA print('Sigma of the gaussian kernel: ', sigma) ## Calculate map of SSIM values map_ssim, MSSIM = compute_map_ssim(image1, image2, window_size, sigma) results.append(MSSIM) if args.plot is True: print('\nPlotting images + map of ssim ....') img_list = [image1, image2, map_ssim] title_list = [ 'Oracle image', 'Image to analyze', 'Map of SSIM' ] dis.plot_multi(img_list, title_list, 'Images and map of SSIM') ## Save SSIM map filename = args.image2[:len(args.image2) - 4] + '_ssim_map.png' io.writeImage(filename, map_ssim) ## CASE OF MULTIPLE SPECIFIC IMAGES else: image_list = args.image2.split(':') img_list = [] title_list = [] num_img = len(image_list) for im in range(num_img): img_file = image_list[im] image1 = io.readImage(args.image1) image2 = io.readImage(img_file) # image2 --> image to analyze image2 = image2.astype(myfloat) print('\nReading image to analyze:\n', args.image2) print('Image shape: ', image2.shape) ## Get time in which the prgram starts to run time1 = time.time() ## Scale image to analyze with respect to the reference one if args.scaling is True: print('\nPerforming linear regression ....') image2 = proc.linearRegression(image1, image2) ## Register images if args.register is True: print( '\nPerforming registration of the image to analize ....' ) image2 = proc.image_registration(image2, image1, 'ssd') ## Crop resolution circle of the images if args.resol_circle is True: print('\nSelecting the resolution circle') image1 = proc.selectResolutionSquare(image1) image2 = proc.selectResolutionSquare(image2) ## Crop images if enabled if args.roi is not None: roi = args.roi if args.roi.find(',') != -1: roi = roi.split(',') p0 = [ int(roi[0].split(':')[1]), int(roi[0].split(':')[0]) ] p1 = [ int(roi[1].split(':')[1]), int(roi[1].split(':')[0]) ] print('Cropping rectangular ROI with vertices: ( ', \ p0[0],' , ', p0[1], ') ( ', p1[0],' , ',p1[1], ')') image1 = proc.crop_image(image1, p0, p1) image2 = proc.crop_image(image2, p0, p1) else: print('\nUsing pixels specified in file:\n', roi) pixels = np.loadtxt(roi) pixels = pixels.astype(int) p0 = np.array([pixels[0, 0], pixels[0, 1]]) p1 = np.array([ pixels[len(pixels) - 1, 0], pixels[len(pixels) - 1, 1] ]) print('Cropping rectangular ROI with vertices: ( ', \ p0[0],' , ', p0[1], ') ( ', p1[0],' , ',p1[1], ')') image1 = proc.crop_image(image1, p0, p1) image2 = proc.crop_image(image2, p0, p1) ## Compute the gradient of the images, if enabled if args.gradient is True: image1 = compute_gradient_image(image1) image2 = compute_gradient_image(image2) ## Check whether the 2 images have the same shape if image1.shape != image2.shape: sys.exit( '\nERROR: The input images have different shapes!\n') ## Plot to check whether the images have the same orientation if args.plot is True: print('\nPlotting images to check orientation ....') img_list2 = [image1, image2] title_list2 = ['Oracle image', 'Image to analyze'] dis.plot_multi(img_list2, title_list2, 'Check plot') ## Get window size window_size = args.window print('\nSize of the computation window: ', window_size) if window_size % 2 != 0: window_size += 1 print('Window size is even: window size changed to ', window_size) ## Get sigma of the gaussian kernel sigma = SIGMA print('Sigma of the gaussian kernel: ', sigma) ## Calculate map of SSIM values map_ssim, MSSIM = compute_map_ssim(image1, image2, window_size, sigma) results.append(MSSIM) map_ssim[map_ssim < 0] = 0.0 if args.plot is True: img_list.append(map_ssim) title_list.append('SSIM map n.' + str(im + 1)) ## Save SSIM map filename = img_file[:len(img_file) - 4] + '_ssim_map.png' io.writeImage(filename, map_ssim) if args.plot is True: print('\nPlotting images + map of ssim ....') dis.plot(img_list[0]) dis.plot(img_list[1]) dis.plot_multi_colorbar(img_list, title_list, 'Maps of SSIM') ## CASE OF BUNCH OF IMAGES TO ANALYZE else: os.chdir(args.path) image_list = sorted(glob.glob('*')) num_images = len(image_list) img_list.append(image1) title_list.append('Oracle image') ## Get time in which the prgram starts to run time1 = time.time() ## Loop on all the images to analyze for i in range(num_img): image1 = io.readImage(args.image1) image2 = io.readImage(image_list[i]) image2 = image2.astype(myfloat) print('\n\n\nIMAGE TO ANALYZE NUMBER: ', i) print('\nReading image to analyze:\n', fileIn[i]) print('Image shape: ', image2.shape) ## Scale image to analyze with respect to the reference one if args.scaling is True: print('\nPerforming linear regression ....') image2 = proc.linearRegression(image1, image2) ## Register images if args.register is True: print('\nPerforming registration of the image to analize ....') image2 = proc.image_registration(image2, image1, 'ssd') ## Crop resolution circle of the images if args.resol_circle is True: print('\nSelecting the resolution circle') image1 = proc.selectResolutionSquare(image1) image2 = proc.selectResolutionSquare(image2) ## Crop images if enabled if args.roi is not None: roi = args.roi if args.roi.find(',') != -1: roi = roi.split(',') p0 = [int(roi[0].split(':')[1]), int(roi[0].split(':')[0])] p1 = [int(roi[1].split(':')[1]), int(roi[1].split(':')[0])] print('Cropping rectangular ROI with vertices: ( ', \ p0[0],' , ', p0[1], ') ( ', p1[0],' , ',p1[1], ')') image1 = proc.crop_image(image1, p0, p1) image2 = proc.crop_image(image2, p0, p1) else: print('\nUsing pixels specified in file:\n', roi) pixels = np.loadtxt(roi) pixels = pixels.astype(int) p0 = np.array([pixels[0, 0], pixels[0, 1]]) p1 = np.array([ pixels[len(pixels) - 1, 0], pixels[len(pixels) - 1, 1] ]) print('Cropping rectangular ROI with vertices: ( ', \ p0[0],' , ', p0[1], ') ( ', p1[0],' , ',p1[1], ')') image1 = proc.crop_image(image1, p0, p1) image2 = proc.crop_image(image2, p0, p1) ## Compute the gradient of the images, if enabled if args.gradient is True: image1 = compute_gradient_image(image1) image2 = compute_gradient_image(image2) ## Check whether the 2 images have the same shape if image1.shape != image2.shape and args.roi is None: sys.error('\nERROR: The input images have different shapes!\n') ## Plot to check whether the images have the same orientation if args.plot is True: print('\nPlotting images to check orientation ....') img_list = [image1, image2] title_list = ['Oracle image', 'Image to analyze'] dis.plot_multi(img_list, title_list, 'Check plot') ## Get window size window_size = args.window print('\nSize of the computation window: ', window_size) if window_size % 2 != 0: window_size += 1 print('Window size is even: window size changed to ', window_size) ## Get sigma of the gaussian kernel sigma = SIGMA print('Sigma of the gaussian kernel: ', sigma) ## Calculate map of SSIM values map_ssim, MSSIM = compute_map_ssim(image1, image2, window_size, sigma) results.append(MSSIM) ## Diplay map of SSIM if args.plot is True: fig = plt.figure() plt.title('Map of SSIM indeces') plt.imshow(map_ssim, cmap=cm.Greys_r) #plt.colorbar() plt.show() ## Save SSIM map filename = image_list[i][:len(image_list[i]) - 4] + '_ssim_map.png' io.writeImage(filename, map_ssim) os.chdir(currDir) ## Summary print of the results print('\n\nSUMMARY OF THE RESULTS:\n') print('\nReference image:\n', args.image1) for i in range(num_img): print('\n\nTest image number ', i, '\n', image_list[i], '\n') print('SSIM = ', results[i]) ## Get time elapsed for the run of the program time2 = time.time() - time1 print('\n\nTime elapsed for the calculation: ', time2) ## Write log file write_log_file(args, image_list, results) print('\n\n')
def lhem(x0, tracer): ## Extend sinogram to [0,2pi) m0, n0 = x0.shape s_2pi = extend_full_period(x0) ig = np.argwhere(s_2pi != tracer)[:, 0] ib = np.argwhere(s_2pi == tracer)[:, 0] ## Resample each projection at cosinusoidal nodes sc = resampling_cosine_nodes(s_2pi) sc[ib, :] = tracer m1, n1 = sc.shape mh1 = int(m1 * 0.5) nh1 = int(n1 * 0.5) ## Get matrix representation of each operator print('Creating Fy and Fya ....') Fy = ftmy(m1, n1) Fya = Fy.getH() print('Creating Sx ....') Sx = fsmx(m1, n1) print('Creating M ....') M = fbmask(m1, n1) #I = ss.eye( m1 * n1 , m1 * n1 ) I = np.eye(m1 * n1, m1 * n1) ## Matrix representation of D, that keeps only the ## extrapolated values print('Creating D ....') sx = np.mat(sc.copy().reshape(m1 * n1, 1)) ib2 = np.argwhere(sx == tracer) sx[ib2] = 0.0 D = np.zeros((m1 * n1, m1 * n1), dtype=myint) D[ib2, ib2] = 1.0 D = ss.coo_matrix(D) aux = D.dot(sx) dis.plot(aux.reshape(m1, n1), 'Aux') ## Complete operator print('Creating H ....') H = D.dot(Fya.dot(Sx.dot(M.dot(Sx.dot(Fy))))) ## Compute limit operator print('Creating Hl ....') eps = 1e-5 H = H.todense() Hl = np.linalg.pinv(I - H) #Hl = np.eye( m1 * n1 , dtype=mycomplex ) #for i in range( 1 , 50 ): # print( 'i = ' , i ) # Hl += np.linalg.matrix_power( H , i ) #for i in range( 1 , 30 ): # print( 'i = ' , i ) # sx[:] = np.mat( np.dot( H , sx ) ) # sx[ig] = sc[ig] #sx = sx.reshape( m1 , n1 ) eva, eve = np.linalg.eig(H) print('Max-eigen: ', np.max(np.abs(eva))) H2 = np.dot(np.transpose(np.conjugate(H)), H) eva, eve = np.linalg.eig(H2) print('Max-eigen: ', np.max(np.abs(eva))) ## Filtered sinogram print('Creating filt. sinogram ....') #sx = np.real( Hl.dot( sx ) ).reshape( m1 , n1 ) sx = np.real(np.dot(Hl, sx)).reshape(m1, n1) ## Resample on equispaced nodes print('Resample on equispaced nodes ....') x = resampling_equisp_nodes(sx, n0) ## Halve the nuber of projections x = x[:m0, :] return x
def debug_lhem(x0, tracer): ## Extend sinogram to [0,2pi) m0, n0 = x0.shape s_2pi = extend_full_period(x0) ig = np.argwhere(s_2pi != tracer)[:, 0] ib = np.argwhere(s_2pi == tracer)[:, 0] #dis.plot( s_2pi , 'S-2pi' ) ## Resample each projection at cosinusoidal nodes sc = resampling_cosine_nodes(s_2pi) sc[ib, :] = tracer m1, n1 = sc.shape mh1 = int(m1 * 0.5) nh1 = int(n1 * 0.5) dis.plot(sc, 'SC') ## Get matrix representation of each operator print('Creating Fy and Fya ....') Fy = ftmy(m1, n1) Fya = Fy.getH() print('Creating Sx ....') Sx = fsmx(m1, n1) print('Creating M ....') M = fbmask(m1, n1) I = ss.eye(m1 * n1, m1 * n1) ## Matrix representation of D, that keeps only the ## extrapolated values print('Creating D ....') sx = np.mat(sc.copy().reshape(m1 * n1, 1)) ib2 = np.argwhere(sx == tracer) D = np.zeros((m1 * n1, m1 * n1), dtype=myint) D[ib2, ib2] = 1.0 D = ss.coo_matrix(D) ## Get traced and non-traced elements sx = sc.copy() sx[ib, :] = 0.0 ## Loop it = 0 err = 1000 nc = n1 niter = 50 eps = 1e-10 while it < niter and err > eps: sx = sx.reshape(m1 * n1, 1) ## Fourier-Chebyshev decomposition if it == 0: c = Sx.dot(sx) #fp.dst( sx , type=1 , axis=1 ) b = Fy.dot( c) #np.fft.fftshift( np.fft.fft( c , axis=0 ) , axes=0 ) sp = sx.copy().reshape(m1, n1) else: c[:] = Sx.dot(sx) #fp.dst( sx , type=1 , axis=1 ) b[:] = Fy.dot( c) #np.fft.fftshift( np.fft.fft( c , axis=0 ) , axes=0 ) sp[:] = sx.reshape(m1, n1) ## Zero-out inconsistent coefficients #dis.plot( np.real( b ).reshape( m1 , n1 ) , 'B before' ) b[:] = M.dot(b) #b[ic[:,0],ic[:,1]] = 0.0 #dis.plot( np.real( b ).reshape( m1 , n1 ) , 'B after' ) ## Reproject to real space c = Fya.dot( b ) #c[:] = np.real( np.fft.ifft( np.fft.ifftshift( b , axes=0 ) , axis=0 ) ) #dis.plot( np.real( c ).reshape( m1 , n1 ) , 'C' ) # sx_r[:] = 1.0 / ( 2.0 * ( nc + 1 ) ) * fp.dst( c , type=1 , axis=1 ) # sx_i[:] = 1.0 / ( 2.0 * ( nc + 1 ) ) * fp.dst( ci , type=1 , axis=1 ) sx[:] = Sx.dot(c) # sx[:] = np.sqrt( sx_r**2 + sx_i**2 ) #dis.plot( np.real( sx ).reshape( m1 , n1 ) , 'Sx before reassign' ) ## Re-assign original values sx = sx.reshape(m1, n1) sx[ig, :] = sc[ig, :] #dis.plot( sx , 'Sx after reassign' ) ## Compute error & PSNR err = np.linalg.norm(sx - sp) it += 1 print('\n Iteration n. ', it, ' ---> || x_{k+1} - x{k}|| = ', err, end='') ## Crop original sinogram interval [0,pi) and first channel half (transl. of 1) sx = sx[:mh1, :] ## Interpolate back on equispaced nodes x = resampling_equisp_nodes(sx, n0) print('\n') return x
def main(): ## Initial print print('\n') print('##################################################################') print('############# TOMOGRAPHIC GRIDDING RECONSTRUCTION #############') print('##################################################################') print('\n') ## Get the startimg time of the reconstruction time1 = time.time() ## Get input arguments args = getArgs() ## Get input/output directory pathin, pathout = utils.get_io_path(args) print('\nInput path:\n', pathin) print('\nOutput path:\n', pathout) ## Get input files file_list, file1, nimg, ext = utils.get_input(args, pathin) print('\nNumber of input files: ', nimg) print('Extension of the files: ', ext) ## Read first sinogram sino = io.readImage(pathin + file1).astype(myfloat) nang, npix = sino.shape print('\nSinogram to reconstruct:\n', file1) print('Number of projection angles: ', nang) print('Number of pixels: ', npix) if args.plot is True: dis.plot(sino, 'Input sinogram') ## Enable edge padding if args.edge_pad is True: sino = proc.sino_edge_padding(sino, 0.5).astype(myfloat) i1 = int((sino.shape[1] - npix) * 0.5) i2 = i1 + npix npix = sino.shape[1] ctr = args.ctr if ctr != 0.0: ctr += i1 if args.plot is True: dis.plot(sino, 'Edge padded sinogram') else: i1 = 0 i2 = npix ctr = args.ctr ## Getting projection geometry if args.geometry == '0': print( '\nDealing with equiangular projections distributed between 0 and' + ' 180 degrees ---> [0,180)') angles = utils.create_projection_angles(nang) else: print('\nReading list of projection angles:\n', pathin + args.geometry) angles = utils.create_projection_angles(textfile=pathin + args.geometry) if args.plot is True: print('\nProjection angles:') pp.printArray(angles) ## Enable object support calculation if args.object_support is True: print('\nObject support calculation enabled') mask = ob.object_support(sino) if args.plot is True: dis.plot(mask, 'Object support mask') ## Differential sinogram fo DBP if args.dbp is True: print('\nDifferential backprojection enabled') print( 'Computing differential sinogram by means of Savitzky-Golay method' ) sino[:, :] = proc.diff_sino_savitzky_golay(sino, window_size=11) if args.plot is True: dis.plot(sino, 'Differential sinogram') ## Initialize projectior class tp = cpj.projectors(npix, angles, ctr=ctr, args=args) ## Apply forward projection operator time_rec1 = time.time() reco = tp.fbp(sino) time_rec2 = time.time() ## Crop reconstruction if args.edge_pad: reco = reco[i1:i2, i1:i2] ## Apply object support mask if args.object_support is True: reco[mask == 0] = 0.0 ## Display reconstruction if args.plot is True: dis.plot(reco, 'Reconstruction') ## Save reconstruction save_reconstruction(pathout, file1, args, reco) ## Reconstruct sinograms from all the other images in the stack if args.filein is None: pool = mproc.Pool() for i in range(1, nimg): pool.apply_async( multi_thread, (pathin, pathout, file_list[0][i], args, [i1, i2])) pool.close() pool.join() time2 = time.time() print('\nTime elapsed to run the 1st backward gridrec: ', time_rec2 - time_rec1) print('Total time elapsed for the run of the program: ', time2 - time1) print('\n') print('##############################################') print('#### GRIDDING RECONSTRUCTION DONE ! ####') print('##############################################') print('\n')
def main(): print('\n') print('#########################################################') print('#########################################################') print('### ###') print('### CREATE SHEPP-LOGAN AND ITS ANALYTICAL SINOGRAM ###') print('### ###') print('#########################################################') print('#########################################################') print('\n') ## Get arguments args = getArgs() ## Get number of pixels npix = args.npix nang = args.nang print('\nNumber of pixels: ', npix) print('Number of views: ', nang) ## Create look-up-table of Shepp-Logan ellipses or read specifics from file if args.filein is None: LUT = lut_shepp_logan( npix , nang ) print('\nCreated LUT for Shepp-Logan phantom') else: lut_file = np.loadtxt( args.filein ) LUT = lut_generic_phantom( lut_file , npix , nang ) if args.filein.find( '/' ) == -1: name = args.filein.split( '.' )[0] else: tokens = args.filein.split( '/' ) name = tokens[len(tokens)-1].split('.')[0] print('\nReading LUT for phantom from file:\n', args.filein) print('Label selected for the putput files: ', name) ## Create Shepp-Logan phantom phantom = create_phantom( LUT , npix ) ## Write phantom path = args.path if path[len(path)-1] != '/': path += '/' if args.filein is None: filename = path + 'shepp_logan_pix' else: filename = path + name + '_pix' if npix < 10: common = '000' + str( npix ) elif npix < 100: common = '00' + str( npix ) elif npix < 1000: common = '0' + str( npix ) else: common = str( npix ) filename += common + args.file_format io.writeImage( filename , phantom ) print('\nWriting sinogram in:\n', filename) ## Plot phantom if args.plot is True: dis.plot( phantom , 'Shepp-Logan ' + str( npix ) + ' X ' + str( npix ) + ' pixels' ) ## Compute analitically radon transform of the phantom if args.nang is not None: print('\nCalculating analytical radon transform of the phantom ....') sinogram = radon_transform_analytical( phantom , LUT , npix , nang ) sinogram[:,:] = sinogram[:,::-1] sinogram[:,:] = np.roll( sinogram , 1 , axis=1 ) ## Plot Shepp-Logan phantom if args.plot is True: dis.plot( sinogram , 'Sinogram ' + str( nang ) + ' views X ' + str( npix ) + ' pixels' ) ## Write sinogram if args.filein is None: filename = path + 'shepp_logan_pix' + common + '_ang' else: filename = path + name + '_pix' + common + '_ang' if nang < 10: filename += '000' + str( nang ) + '_rt_anal_sino' + args.file_format elif nang < 100: filename += '00' + str( nang ) + '_rt_anal_sino' + args.file_format elif nang < 1000: filename += '0' + str( nang ) + '_rt_anal_sino' + args.file_format else: filename += str( nang ) + '_rt_anal_sino' + args.file_format io.writeImage( filename , sinogram ) print('\nWriting sinogram in:\n', filename) print('\n\n')
def main(): ## Initial print print('\n') print('########################################################') print('#### CREATE VIRTUAL SINOGRAM ####') print('########################################################') print('\n') ## Get arguments args = getArgs() ## Get input/output directory pathin , pathout = utils.get_io_path( args ) print('\nInput path:\n', pathin) print('\nOutput path:\n', pathout) ## Get input files file_list , file1 , nimg , ext = utils.get_input( args , pathin ) print('\nNumber of input files: ' , nimg) print('Extension of the files: ', ext) ## Read first sinogram sino = io.readImage( pathin + file1 ).astype( myfloat ) nang , npix = sino.shape print('\nSinogram to reconstruct:\n', file1) print('Number of projection angles: ', nang) print('Number of pixels: ', npix) if args.plot is True: dis.plot( sino , 'Input sinogram' ) ## Set center of rotation axis if args.ctr == None: ctr = 0.0 print('Center of rotation axis placed at pixel: ', npix * 0.5) else: ctr = args.ctr print('Center of rotation axis placed at pixel: ', ctr) ## Enable edge-padding if args.edge_pad is True: sino = proc.sino_edge_padding( sino , 0.5 ).astype( myfloat ) i1 = int( ( sino.shape[1] - npix ) * 0.5 ) i2 = i1 + npix npix = sino.shape[1] if ctr != 0.0: ctr += i1 if args.plot is True: dis.plot( sino , 'Edge padded sinogram' ) else: i1 = 0 i2 = npix ## Prepare projectors ang = np.arange( nang ) * 180.0 / myfloat( nang ) tp = cpj.projectors( npix , ang , kernel='kb' , oversampl=2.32 , W=6.6 , errs=6.0e-6 , interp='lin' , radon_degree=0 , filt=args.filt , ctr=ctr ) ## Reconstruct reco = tp.fbp( sino ) if args.plot is True: dis.plot( reco , 'Reconstruction' ) #reco = reco[i1:i2,i1:i2] ## Zero-out pixels outside resolution circle reco_new = reco.copy(); reco_new[:] = 0.0 io.writeImage( 'reco.DMP' , reco[i1:i2,i1:i2] ) reco_new[i1:i2,i1:i2] = utils.resol_circle_constr( reco[i1:i2,i1:i2] ) reco[:] = reco_new[:] if args.plot is True: dis.plot( reco , 'Constrained reconstruction' ) io.writeImage( 'reco_circle.DMP' , reco ) ## Background equalization reco[:] = background_equalization( reco ) if args.plot is True: dis.plot( reco , 'Equalized reconstruction' ) io.writeImage( 'reco_equaliz.DMP' , reco ) ## Forward projection nang_new = np.int( npix * np.pi / 2.0 ) ang_new = np.arange( nang_new ) * 180.0 / np.float32( nang_new ) tp = cpj.projectors( npix , ang_new , kernel='kb' , oversampl=2.32 , W=6.6 , errs=6.0e-6 , interp='lin' , radon_degree=0 ) sino = tp.A( reco ) #sino = sino[:,i1:i2] if args.plot is True: dis.plot( sino , 'Forward projection' ) io.writeImage( 'sino_circle.DMP' , sino ) ## Save output file if args.fileout is None: filein = args.filein extension = filein[len(filein)-4:] fileout = filein[:len(filein)-4] + '_virt.tif' else: fileout = args.fileout io.writeImage( pathout + fileout , sino ) print( '\nWritten output file:\n' , pathout + fileout )
def main(): ## Initial print print('\n') print('########################################################') print('############# REGRIDDING BACKPROJECTION #############') print('########################################################') print('\n') ## Get the startimg time of the reconstruction time1 = time.time() ## Get input arguments args = getArgs() ## Get input/output directory pathin, pathout = utils.get_io_path(args) print('\nInput path:\n', pathin) print('\nOutput path:\n', pathout) ## Get input files file_list, file1, nimg, ext = utils.get_input(args, pathin) print('\nNumber of input files: ', nimg) print('Extension of the files: ', ext) ## Read first sinogram sino = io.readImage(pathin + file1).astype(myfloat) nang, npix = sino.shape print('\nSinogram to reconstruct:\n', file1) print('Number of projection angles: ', nang) print('Number of pixels: ', npix) if args.plot is True: dis.plot(sino, 'Input sinogram') ## Getting projection geometry if args.geometry == '0': print( '\nDealing with equiangular projections distributed between 0 and' + ' 180 degrees ---> [0,180)') angles = utils.create_projection_angles(nang) else: print('\nReading list of projection angles:\n', pathin + args.geometry) angles = utils.create_projection_angles(textfile=pathin + args.geometry) ## Set center of rotation axis if args.ctr == None: ctr = 0.0 print('Center of rotation axis placed at pixel: ', npix * 0.5) else: if args.ctr == -1: ctr = proc.search_rot_ctr(sino, None, 'a') print('Center of rotation axis placed at pixel: ', ctr) else: ctr = args.ctr print('Center of rotation axis placed at pixel: ', ctr) if args.dbp is True: sino[:, :] = proc.sino_correct_rot_axis(sino, ctr) print('Center of rotation corrected') ctr = 0.0 ## Enable edge padding if args.edge_pad is True: sino = proc.sino_edge_padding(sino, 0.5).astype(myfloat) i1 = int((sino.shape[1] - npix) * 0.5) i2 = i1 + npix npix = sino.shape[1] if ctr != 0.0: ctr += i1 if args.plot is True: dis.plot(sino, 'Edge padded sinogram') else: i1 = 0 i2 = npix ## External sinogram filtering if args.filt == 'ramp-ext' or args.filt == 'conv-ext': if filt == 'ramp-ext': sino = fil.filter_fft(sino, 'ramp') elif filt == 'conv-ext': sino = fil.filter_convolve(sino) sino *= 4.0 / myfloat(npix) args.filt = 0 ## Differential sinogram fo DBP if args.dbp is True: print('\nDifferential backprojection enabled') print( 'Computing differential sinogram by means of Savitzky-Golay method' ) print('Savizky-Golay window length: ', args.sg) sino[:, :] = proc.diff_sino_savitzky_golay(sino, window_size=args.sg) if args.plot is True: dis.plot(sino, 'Differential sinogram') ## Initialize projectior class tp = cpj.projectors(npix, angles, ctr=ctr, args=args) ## Apply forward projection operator time_rec1 = time.time() reco = tp.fbp(sino) time_rec2 = time.time() ## Crop reconstruction if args.edge_pad: reco = reco[i1:i2, i1:i2] ## Display reconstruction if args.plot is True: dis.plot(reco, 'Reconstruction') ## Save reconstruction save_reconstruction(pathout, file1, args, reco) ## Reconstruct sinograms from all the other images in the stack if args.filein is None: pool = mproc.Pool() for i in range(1, nimg): pool.apply_async( multi_thread, (pathin, pathout, file_list[0][i], args, [i1, i2])) pool.close() pool.join() time2 = time.time() print('\nTime elapsed to run the 1st backward gridrec: ', time_rec2 - time_rec1) print('Total time elapsed for the run of the program: ', time2 - time1) print('\n') print('##############################################') print('#### REGRIDDING BACKPROJECTION DONE ! ####') print('##############################################') print('\n')
def main(): ## Initial print print('\n') print('########################################################') print('############# REGRIDDING BACKPROJECTION #############') print('########################################################') print('\n') ## Get the startimg time of the reconstruction time1 = time.time() ## Get input arguments args = getArgs() ## Get input and output directory pathin = args.pathin if pathin[len(pathin)-1] != '/': pathin += '/' if os.path.exists( pathin ) is False: sys.exit('\nERROR: input directory ', pathin,' does not exist!') if args.pathout is None: pathout = pathin else: pathout = args.pathout if pathout[len(pathout)-1] != '/': pathout += '/' if os.path.exists( pathin ) is False: sys.exit('\nERROR: input directory ', pathin,' does not exist!') print('\nInput directory:\n', pathin) ## Get input sinogram sinofile = pathin + args.sino sino = io.readImage( sinofile ) nang, npix = sino.shape print('\nSinogram to reconstruct:\n', sinofile) print('Number of projection angles: ', nang) print('Number of pixels: ', npix) ## Display sinogram if args.plot is True: dis.plot( sino , 'Input sinogram' ) ## Getting projection geometry ## Case of equiangular projections distributed in [0,180) if args.geometry == '0': print('\nDealing with equiangular projections distributed between 0 and' +' 180 degrees ---> [0,180)') angles = np.arange( nang ).astype( myfloat ) angles[:] = ( angles * 180.0 )/myfloat( nang ) ## Case of list of projection angles in degrees else: geometryfile = pathin + args.geometry print('\nReading list of projection angles: ', geometryfile) angles = np.fromfile( geometryfile , sep="\t" ) if args.plot is True: print('\nProjection angles:\n', angles) ## Choose filtering function filt_list = [ 'none' , 'ramp' , 'shlo' , 'hann' , 'hamm' , 'parz' , 'lanc' ] filt = args.filt if filt not in filt_list: sys.exit("\nERROR: filter named: ', filt,' does not exist!\n \ Use one of the following available filters:\n \ 'none' , 'ramp' , 'shlo' , 'hann' , 'hamm' , 'parz' , 'lancz'") print('\nSelected filter: ', filt) param = np.zeros( 3 ) if filt == 'none': param[1] = 0 elif filt == 'ramp': param[1] = 1 elif filt == 'shlo': param[1] = 2 elif filt == 'hann': param[1] = 3 elif filt == 'hamm': param[1] = 4 elif filt == 'lanc': param[1] = 5 elif filt == 'parz': param[1] = 6 ## Set center of rotation axis if args.ctr == None: ctr = npix * 0.5 elif args.ctr == -1: ctr = proc.searchCtrRot( sino , None , 'a' ) else: ctr = args.ctr ## Enable edge padding if args.edge_pad is True: sino = proc.edgePadding( sino , 0.5 ) i1 = int( ( sino.shape[1] - npix ) * 0.5 ) i2 = i1 + npix npix = sino.shape[1] ctr += i1 if args.plot is True: dis.plot( sino , 'Edge padded sinogram' ) param[0] = ctr print('Center of rotation axis placed at pixel: ', ctr) ## Reconstruction with regridding method time_rec1 = time.time() reco = grid.backproj( sino.astype( myfloat ) , angles.astype( myfloat ) , param.astype( myfloat ) ) time_rec2 = time.time() ## Crop reconstruction if args.edge_pad: reco = reco[i1:i2,i1:i2] ## Display reconstruction if args.plot is True: dis.plot( reco , 'Reconstruction' ) ## Save reconstruction saveReco( reco , pathin , pathout , args ) ## Time elapsed for the reconstruction time2 = time.time() print('\nTime elapsed for the back-projection: ', time_rec2-time_rec1 ) print('Total time elapsed: ', time2-time1 ) print('\n') print('##############################################') print('#### REGRIDDING BACKPROJECTION DONE ! ####') print('##############################################') print('\n')
def main(): ## Initial print print('\n') print('########################################################') print('############# EQUALLY SLOPED TOMOGRAPHY #############') print('########################################################') print('\n') ## Get the startimg time of the reconstruction time1 = time.time() ## Get input arguments args = getArgs() ## Get input directory pathin = args.pathin if pathin[len(pathin)-1] != '/': pathin += '/' if os.path.exists( pathin ) is False: sys.exit('\nERROR: input directory ', pathin,' does not exist!') print('\nInput directory:\n', pathin) ## Get input sinogram sinofile = pathin + args.sino sino = io.readImage( sinofile ) nang, npix = sino.shape print('\nSinogram to reconstruct:\n', sinofile) print('Number of projection angles: ', nang) print('Number of pixels: ', npix) ## Display sinogram if args.plot is True: dis.plot( sino , 'Input sinogram' ) ## Getting projection geometry ## Case of equiangular projections distributed in [0,180) if args.geometry == '0': print('\nDealing with equiangular views distributed in [0,180)') angles = np.arange( nang ).astype( myfloat ) angles[:] = ( angles * 180.0 )/myfloat( nang ) ## Case of pseudo polar views elif args.geometry == '1': print('\nDealing with equally sloped views in [0,180)') angles , dump1 , dum2 = pyest.create_est_views( nang ) angles *= 180.0 / np.pi ## Case of list of projection angles in degrees else: geometryfile = pathin + args.geometry print('\nReading list of projection angles: ', geometryfile) angles = np.fromfile( geometryfile , sep="\t" ) print('\nProjection angles:\n', angles) ## Set center of rotation axis if args.ctr == None: ctr = 0.0 print('\nCenter of rotation axis placed at pixel: ', npix * 0.5) elif args.ctr == -1: ctr = proc.searchCtrRot( sino , None , 'a' ) print('\nCenter of rotation axis placed at pixel: ', ctr) sino = proc.sinoRotAxisCorrect( sino , ctr ) else: ctr = args.ctr print('\nCenter of rotation axis placed at pixel: ', ctr) sino = proc.sinoRotAxisCorrect( sino , ctr ) ## Get inverse procedure if args.reco_proc == 1: proc = args.reco_proc print('\nSelected inverse procedure: PCG-IPPFT') elif args.reco_proc == 2: proc = args.reco_proc print('\nSelected inverse procedure: iterative procedure with constraints') ## Reconstruction with EQUALLY SLOPED TOMOGRAPHY print('\nPerforming EST reconstruction ....') time_rec1 = time.time() reco = pyest.est_tomo( sino , angles , proc ) time_rec2 = time.time() print('\n.... reconstruction done!') ## Display reconstruction dis.plot( reco , 'Reconstruction' ) ## Save reconstruction saveReco( reco , pathin , args ) ## Time elapsed for the reconstruction time2 = time.time() print('\nTime elapsed for the back-projection: ', time_rec2-time_rec1 ) print('Total time elapsed: ', time2-time1 ) print('\n') print('##############################################') print('#### EQUALLY SLOPED TOMOGRAPHY DONE ! ####') print('##############################################') print('\n')
def main(): print('\nADD NOISE TO IMAGES\n') ## Get input arguments args = getArgs() ## Get input and output path pathin = args.pathin if pathin[len(pathin) - 1] != '/': pathin += '/' if args.pathout is None: pathout = pathin else: pathout = args.pathout if pathout[len(pathout) - 1] != '/': pathout += '/' print('\nInput path:\n', pathin) print('\nOutput path:\n', pathout) ## Get single image if args.image is not None: ## Reading image filein = args.image imagein = io.readImage(pathin + filein).astype(myfloat) shape = np.array(imagein.shape) print('\nReading image:\n', filein, '\n') if len(shape) == 2: dim = 2 nrows, ncols = shape print('Image size: ', nrows, ' X ', ncols) if args.plot is True: dis.plot(imagein, 'Input image') else: dim = 3 nz, nrows, ncols = shape print('Image size: ', nz, ' X ', nrows, ' X ', ncols) if args.plot is True: dis.plot(imagein[0, :, :], 'Input image') ## Compute standard deviation of the image ## and, subsequently, the gaussian sigmas if args.noise == 'gaussian': sigma = 0.5 * np.max(imagein) sigma_list = args.sigma_list sigma_list = np.array(sigma_list.split(':'), dtype=myfloat) nimg = len(sigma_list) sigma_arr = sigma * sigma_list / 100.0 print('\nSigma of the input image: ', sigma) print('Sigma percentages: ', sigma_list) elif args.noise == 'poisson': nimg = 1 else: sys.exit('\nERROR: Noise type "' + args.noise + '" is not an option available with this routine!\n') ## Loop on each gaussian sigma for im in range(nimg): ## Add noise if args.noise == 'gaussian': image_noisy = add_gaussian_noise(imagein, sigma_arr[im]) label = 'gauss' write_output_image(pathout, filein, image_noisy, label, sigma=sigma_list[im]) elif args.noise == 'poisson': image_noisy = add_poisson_noise(imagein) label = 'poiss' write_output_image(pathout, filein, image_noisy, label) ## Check noisy image if args.plot is True: if dim == 2: if args.noise == 'gaussian': dis.plot( image_noisy, 'Gaussian noisy image -- sigma: ' + str(sigma_list[im])) elif args.noise == 'poisson': dis.plot(image_noisy, 'Poisson noisy image') else: if args.noise == 'gaussian': dis.plot( image_noisy[0, :, :], 'Gaussian noisy image -- sigma: ' + str(sigma_list[im])) elif args.noise == 'poisson': dis.plot(image_noisy[0, :, :], 'Poisson noisy image') ## Get bunch of input images elif args.label is not None: curr_dir = os.getcwd() ## Reading images os.chdir(pathin) files = sorted(glob.glob('*' + args.label + '*')) os.chdir(curr_dir) num_im_input = len(files) for i in range(num_im_input): imagein = io.readImage(pathin + files[i]).astype(myfloat) nrows, ncols = imagein.shape print('\nReading image:\n', files[i]) print('Image size: ', nrows, ' X ', ncols) ## Compute standard deviation of the image ## and, subsequently, the gaussian sigmas sigma = np.mean(imagein) if sigma == 0: sigma = 1.0 sigma_list = args.sigma_list sigma_list = np.array(sigma_list.split(':'), dtype=myfloat) nimg = len(sigma_list) sigma_arr = sigma * sigma_list / 100.0 print('\nSigma of the input image: ', sigma) print('Sigma percentages: ', sigma_list) print('Gaussian sigma values: ', sigma_arr) ## Add noise ## Loop on each gaussian sigma if args.noise == 'gaussian': for im in range(nimg): ## Loop on each gaussian sigma image_noisy = add_gaussian_noise(imagein, sigma_arr[im]) label = 'gauss' write_output_file(pathout, files[i], image_noisy, label, sigma=sigma_arr[im]) elif args.noise == 'poisson': image_noisy = add_poisson_noise(imagein) label = 'poiss' write_output_file(pathout, files[i], image_noisy, label) print('\n\n')