def align_seq( prj, ang, fdir='.', iters=10, pad=(0, 0), blur=True, center=None, algorithm='sirt', upsample_factor=10, rin=0.5, rout=0.8, save=False, debug=True): """ Aligns the projection image stack using the sequential re-projection algorithm :cite:`Gursoy:17`. Parameters ---------- prj : ndarray 3D stack of projection images. The first dimension is projection axis, second and third dimensions are the x- and y-axes of the projection image, respectively. ang : ndarray Projection angles in radians as an array. iters : scalar, optional Number of iterations of the algorithm. pad : list-like, optional Padding for projection images in x and y-axes. blur : bool, optional Blurs the edge of the image before registration. center: array, optional Location of rotation axis. algorithm : {str, function} One of the following string values. 'art' Algebraic reconstruction technique :cite:`Kak:98`. 'gridrec' Fourier grid reconstruction algorithm :cite:`Dowd:99`, :cite:`Rivers:06`. 'mlem' Maximum-likelihood expectation maximization algorithm :cite:`Dempster:77`. 'sirt' Simultaneous algebraic reconstruction technique. 'tv' Total Variation reconstruction technique :cite:`Chambolle:11`. 'grad' Gradient descent method with a constant step size upsample_factor : integer, optional The upsampling factor. Registration accuracy is inversely propotional to upsample_factor. rin : scalar, optional The inner radius of blur function. Pixels inside rin is set to one. rout : scalar, optional The outer radius of blur function. Pixels outside rout is set to zero. save : bool, optional Saves projections and corresponding reconstruction for each algorithm iteration. debug : book, optional Provides debugging info such as iterations and error. Returns ------- ndarray 3D stack of projection images with jitter. ndarray Error array for each iteration. """ # Needs scaling for skimage float operations. prj, scl = scale(prj) # Shift arrays sx = np.zeros((prj.shape[0])) sy = np.zeros((prj.shape[0])) conv = np.zeros((iters)) # Pad images. npad = ((0, 0), (pad[1], pad[1]), (pad[0], pad[0])) prj = np.pad(prj, npad, mode='constant', constant_values=0) # Register each image frame-by-frame. for n in range(iters): # Reconstruct image. rec = recon(prj, ang, center=center, algorithm=algorithm) # Re-project data and obtain simulated data. sim = project(rec, ang, center=center, pad=False) # Blur edges. if blur: _prj = blur_edges(prj, rin, rout) _sim = blur_edges(sim, rin, rout) else: _prj = prj _sim = sim # Initialize error matrix per iteration. err = np.zeros((prj.shape[0])) # For each projection for m in range(prj.shape[0]): # Register current projection in sub-pixel precision shift, error, diffphase = register_translation( _prj[m], _sim[m], upsample_factor) err[m] = np.sqrt(shift[0]*shift[0] + shift[1]*shift[1]) sx[m] += shift[0] sy[m] += shift[1] # Register current image with the simulated one tform = tf.SimilarityTransform(translation=(shift[1], shift[0])) prj[m] = tf.warp(prj[m], tform, order=5) if debug: print('iter=' + str(n) + ', err=' + str(np.linalg.norm(err))) conv[n] = np.linalg.norm(err) if save: dxchange.write_tiff(prj, fdir + '/tmp/iters/prj/prj') dxchange.write_tiff(sim, fdir + '/tmp/iters/sim/sim') dxchange.write_tiff(rec, fdir + '/tmp/iters/rec/rec') # Re-normalize data prj *= scl return prj, sx, sy, conv
def align_seq(prj, ang, fdir='.', iters=10, pad=(0, 0), blur=True, save=False, debug=True): """Aligns the projection image stack using the sequential re-projection algorithm :cite:`Gursoy:17`. Parameters ---------- prj : ndarray 3D stack of projection images. The first dimension is projection axis, second and third dimensions are the x- and y-axes of the projection image, respectively. ang : ndarray Projection angles in radians as an array. iters : scalar, optional Number of iterations of the algorithm. pad : list-like, optional Padding for projection images in x and y-axes. blur : bool, optional Blurs the edge of the image before registration. save : bool, optional Saves projections and corresponding reconstruction for each algorithm iteration. debug : book, optional Provides debugging info such as iterations and error. Returns ------- ndarray 3D stack of projection images with jitter. ndarray Error array for each iteration. """ # Needs scaling for skimage float operations. prj, scl = scale(prj) # Shift arrays sx = np.zeros((prj.shape[0])) sy = np.zeros((prj.shape[0])) conv = np.zeros((iters)) # Pad images. npad = ((0, 0), (pad[1], pad[1]), (pad[0], pad[0])) prj = np.pad(prj, npad, mode='constant', constant_values=0) #prj = np.pad(prj, npad, mode='edge') # Register each image frame-by-frame. for n in range(iters): # Reconstruct image. rec = recon(prj, ang, algorithm='sirt') # Re-project data and obtain simulated data. sim = project(rec, ang, pad=False) # Blur edges. if blur: _prj = blur_edges(prj, 0.1, 0.5) _sim = blur_edges(sim, 0.1, 0.5) else: _prj = prj _sim = sim # Initialize error matrix per iteration. err = np.zeros((prj.shape[0])) # For each projection for m in range(prj.shape[0]): # Register current projection in sub-pixel precision shift, error, diffphase = register_translation(_prj[m], _sim[m], 2) err[m] = np.sqrt(shift[0] * shift[0] + shift[1] * shift[1]) sx[m] += shift[0] sy[m] += shift[1] # Register current image with the simulated one tform = tf.SimilarityTransform(translation=(shift[1], shift[0])) prj[m] = tf.warp(prj[m], tform, order=5) ##prj[m] = tf.warp(prj[m], tform, order=0, mode='edge') if debug: print('iter=' + str(n) + ', err=' + str(np.linalg.norm(err))) conv[n] = np.linalg.norm(err) if save: dxchange.write_tiff(prj, fdir + '/tmp/iters/prj/prj') dxchange.write_tiff(sim, fdir + '/tmp/iters/sim/sim') dxchange.write_tiff(rec, fdir + '/tmp/iters/rec/rec') # Re-normalize data prj *= scl return prj, sx, sy, conv
def align_seq(prj, ang, fdir='.', iters=10, pad=(0, 0), blur=True, center=None, algorithm='sirt', upsample_factor=10, rin=0.5, rout=0.8, save=False, debug=True): """ Aligns the projection image stack using the sequential re-projection algorithm :cite:`Gursoy:17`. Parameters ---------- prj : ndarray 3D stack of projection images. The first dimension is projection axis, second and third dimensions are the x- and y-axes of the projection image, respectively. ang : ndarray Projection angles in radians as an array. iters : scalar, optional Number of iterations of the algorithm. pad : list-like, optional Padding for projection images in x and y-axes. blur : bool, optional Blurs the edge of the image before registration. center: array, optional Location of rotation axis. algorithm : {str, function} One of the following string values. 'art' Algebraic reconstruction technique :cite:`Kak:98`. 'gridrec' Fourier grid reconstruction algorithm :cite:`Dowd:99`, :cite:`Rivers:06`. 'mlem' Maximum-likelihood expectation maximization algorithm :cite:`Dempster:77`. 'sirt' Simultaneous algebraic reconstruction technique. 'tv' Total Variation reconstruction technique :cite:`Chambolle:11`. 'grad' Gradient descent method with a constant step size upsample_factor : integer, optional The upsampling factor. Registration accuracy is inversely propotional to upsample_factor. rin : scalar, optional The inner radius of blur function. Pixels inside rin is set to one. rout : scalar, optional The outer radius of blur function. Pixels outside rout is set to zero. save : bool, optional Saves projections and corresponding reconstruction for each algorithm iteration. debug : book, optional Provides debugging info such as iterations and error. Returns ------- ndarray 3D stack of projection images with jitter. ndarray Error array for each iteration. """ # Needs scaling for skimage float operations. prj, scl = scale(prj) # Shift arrays sx = np.zeros((prj.shape[0])) sy = np.zeros((prj.shape[0])) conv = np.zeros((iters)) # Pad images. npad = ((0, 0), (pad[1], pad[1]), (pad[0], pad[0])) prj = np.pad(prj, npad, mode='constant', constant_values=0) # Register each image frame-by-frame. for n in range(iters): # Reconstruct image. rec = recon(prj, ang, center=center, algorithm=algorithm) # Re-project data and obtain simulated data. sim = project(rec, ang, center=center, pad=False) # Blur edges. if blur: _prj = blur_edges(prj, rin, rout) _sim = blur_edges(sim, rin, rout) else: _prj = prj _sim = sim # Initialize error matrix per iteration. err = np.zeros((prj.shape[0])) # For each projection for m in range(prj.shape[0]): # Register current projection in sub-pixel precision shift, error, diffphase = register_translation( _prj[m], _sim[m], upsample_factor) err[m] = np.sqrt(shift[0] * shift[0] + shift[1] * shift[1]) sx[m] += shift[0] sy[m] += shift[1] # Register current image with the simulated one tform = tf.SimilarityTransform(translation=(shift[1], shift[0])) prj[m] = tf.warp(prj[m], tform, order=5) if debug: print('iter=' + str(n) + ', err=' + str(np.linalg.norm(err))) conv[n] = np.linalg.norm(err) if save: dxchange.write_tiff(prj, fdir + '/tmp/iters/prj/prj') dxchange.write_tiff(sim, fdir + '/tmp/iters/sim/sim') dxchange.write_tiff(rec, fdir + '/tmp/iters/rec/rec') # Re-normalize data prj *= scl return prj, sx, sy, conv
def align_seq( prj, ang, fdir='.', iters=10, pad=(0, 0), blur=True, save=False, debug=True): """ Aligns the projection image stack using the sequential re-projection algorithm :cite:`Gursoy:17`. Parameters ---------- prj : ndarray 3D stack of projection images. The first dimension is projection axis, second and third dimensions are the x- and y-axes of the projection image, respectively. ang : ndarray Projection angles in radians as an array. iters : scalar, optional Number of iterations of the algorithm. pad : list-like, optional Padding for projection images in x and y-axes. blur : bool, optional Blurs the edge of the image before registration. save : bool, optional Saves projections and corresponding reconstruction for each algorithm iteration. debug : book, optional Provides debugging info such as iterations and error. Returns ------- ndarray 3D stack of projection images with jitter. ndarray Error array for each iteration. """ # Needs scaling for skimage float operations. prj, scl = scale(prj) # Shift arrays sx = np.zeros((prj.shape[0])) sy = np.zeros((prj.shape[0])) conv = np.zeros((iters)) # Pad images. npad = ((0, 0), (pad[1], pad[1]), (pad[0], pad[0])) prj = np.pad(prj, npad, mode='constant', constant_values=0) # Register each image frame-by-frame. for n in range(iters): # Reconstruct image. rec = recon(prj, ang, algorithm='sirt') # Re-project data and obtain simulated data. sim = project(rec, ang, pad=False) # Blur edges. if blur: _prj = blur_edges(prj, 0.1, 0.5) _sim = blur_edges(sim, 0.1, 0.5) else: _prj = prj _sim = sim # Initialize error matrix per iteration. err = np.zeros((prj.shape[0])) # For each projection for m in range(prj.shape[0]): # Register current projection in sub-pixel precision shift, error, diffphase = register_translation(_prj[m], _sim[m], 2) err[m] = np.sqrt(shift[0]*shift[0] + shift[1]*shift[1]) sx[m] += shift[0] sy[m] += shift[1] # Register current image with the simulated one tform = tf.SimilarityTransform(translation=(shift[1], shift[0])) prj[m] = tf.warp(prj[m], tform, order=5) if debug: print('iter=' + str(n) + ', err=' + str(np.linalg.norm(err))) conv[n] = np.linalg.norm(err) if save: dxchange.write_tiff(prj, fdir + '/tmp/iters/prj/prj') dxchange.write_tiff(sim, fdir + '/tmp/iters/sim/sim') dxchange.write_tiff(rec, fdir + '/tmp/iters/rec/rec') # Re-normalize data prj *= scl return prj, sx, sy, conv