def fast_radon(img): """ Compute projection through projection-slice theorem """ # Execute polar polar 2D-FFT: fsino = Forward(img) fsino = np.fft.ifftshift(fsino) # Inverse FFT: Kino = pr.image(fsino, top_left=sino.top_left, bottom_right=sino.bottom_right) pp.imshow(Kino, cmap='Greys', interpolation='nearest', extent=(Kino.top_left[0], Kino.bottom_right[0], Kino.bottom_right[1], Kino.top_left[1])) result = np.fft.ifft(fsino, axis=0) # Shift result: result = np.fft.fftshift(result) # Get real part: result = np.real(result) # Normalize: result = result[PAD - 1:-PAD - 1, :] result /= (0.5 * (sino.shape[0] - 1)) return pr.image(result, top_left=sino.top_left, bottom_right=sino.bottom_right)
def nonuimportSino(data_case): if data_case ==0: sl = pr.image_read( 'TomoData/PhantomData/sl.mat') flat = pr.image_read( 'TomoData/PhantomData/slflat.mat', dtype=np.float32 ) dark = pr.image_read( 'TomoData/PhantomData/sldark.mat', dtype=np.float32 ) counts = pr.image_read( 'TomoData/PhantomData/slcount.mat', dtype=np.float32 ) elif data_case ==1: sl = pr.image_read( 'TomoData/PhantomData/sl.mat') counts = pr.image_read( 'TomoData/noisyphantom/nslcounts.mat', dtype=np.float32 ) flat = pr.image_read( 'TomoData/noisyphantom/nslflat.mat', dtype=np.float32 ) dark = pr.image_read( 'TomoData/noisyphantom/nsldark.mat', dtype=np.float32 ) elif data_case ==2: sl = pr.image(np.ones((2048,2048)), top_left =(-1,1), bottom_right = (1,-1)) flat = pr.image_read( 'TomoData/SeedData/flati.mat', dtype=np.float32 ) dark = pr.image_read( 'TomoData/SeedData/darki.mat', dtype=np.float32 ) counts = pr.image_read( 'TomoData/SeedData/countsi.mat', dtype=np.float32 ) else: print('not a valid data_case, you can insert custom data here') quit() sino = pr.image(np.log(flat/counts), top_left = (0,1),bottom_right=(np.pi,-1)) function = fs.make_fourier_slice_radon_transp fast_radon, fast_transp = function( sino ) return sl, sino, counts, dark, flat, fast_radon, fast_transp, function
def pseudoimportSino(data_case): #You can custom import data by loading into directory and changing string #Sinogram must by NxN wher N is doubly even. It may be useful to develop #interpolation function in feature domain to create artificial oversampling #this way any data can be made NxN with N divisible by 4. if data_case ==0: sl = pr.image_read( 'TomoData/PhantomData/sl2.mat', dtype=np.float32) flat = pr.image_read( 'TomoData/PhantomData/slflat.mat', dtype=np.float32 ) dark = pr.image_read( 'TomoData/PhantomData/sldark.mat', dtype=np.float32 ) counts = pr.image_read( 'TomoData/PhantomData/slcount.mat', dtype=np.float32 ) elif data_case == 1: sl = pr.image_read( 'TomoData/PhantomData/sl2.mat', dtype=np.float32) flat = pr.image_read( 'TomoData/noisyphantom/nslflat.mat', dtype=np.float32 ) dark = pr.image_read( 'TomoData/noisyphantom/nsldark.mat', dtype=np.float32 ) counts = pr.image_read( 'TomoData/noisyphantom/nslcounts.mat', dtype=np.float32 ) elif data_case ==2: sl = pr.image(np.ones((1024,1024)), top_left =(-1,1), bottom_right = (1,-1)) flat = pr.image_read( 'TomoData/SeedData/flati.mat', dtype=np.float32 ) dark = pr.image_read( 'TomoData/SeedData/darki.mat', dtype=np.float32 ) counts = pr.image_read( 'TomoData/SeedData/countsi.mat', dtype=np.float32 ) else: print('not a valid data_case, you can insert custom data here') quit() #the lines below must always be performed regardless of data n,k = sl.shape #Form sino for interpolation step sino = np.log(flat/counts) #Pad Sino to eliminate need for extrapolation, oversample sino = PIPP.Pad2x(sino) print(np.max(sino)) #Convert to frequency domain fsino = np.fft.fftshift(sino, axes = 0) fsino = np.fft.fft( fsino, axis = 0 ) fsino = np.fft.fftshift(fsino) #Interpolate via 2 stage interpolation (reverse of averbuch et. al) fsino = PIPP.P_INTERP_PP(fsino) #Convert back to feature domain fsino = np.fft.fftshift(fsino ) fsino = np.fft.ifft( fsino, axis = 0 ) sino= (np.real(np.fft.ifftshift(fsino, axes=0))) sino= pr.image(np.concatenate((np.fliplr(np.flipud(sino[:,0:n])),np.fliplr(sino[:,n::])),1), top_left = (0,1), bottom_right = (np.pi,-1) ) print(np.min(counts)) #Reparse into counts,flat,dark counts = pr.image(flat/np.exp(sino), top_left = (0,1), bottom_right = (np.pi,-1) ) function = ppfs.make_fourier_slice_radon_transp fast_radon, fast_transp = function( sino ) return sl, sino, counts, dark, flat, fast_radon, fast_transp, function
def fast_radon(img): """ Compute projection through projection-slice theorem """ # Execute plan: plan.f_hat = img fsino = pfft.fft(img, plan.M) # Assemble sinogram: fsino = np.reshape(fsino, (sino_padded_size, sino.shape[1])) # Inverse FFT: result = np.fft.ifft(fsino, axis=0) # Shift result: result = np.fft.ifftshift(result, axes=(0, )) # Remove padding: result = result[delta + odd_sino:result.shape[0] - delta - extra + odd_sino] # Get real part: result = np.real(result) # Normalize: result /= (0.5 * (sino.shape[0] - 1)) # Return image with appropriate bounding box: return pr.image(result, top_left=sino.top_left, bottom_right=sino.bottom_right)
def fast_radon(img): """ Compute projection through projection-slice theorem """ # Execute pseudo polar 2D-FFT: fsino = Forward(img) fsino = np.fft.fftshift(fsino) # Inverse FFT: result = np.fft.ifft(fsino, axis=0) # Shift result: result = np.fft.ifftshift(result, axes=(0, )) # Get real part: result = np.real(result) # Normalize: result /= (0.5 * (sino.shape[0] - 1)) # Kino = pr.image(result, top_left = sino.top_left, bottom_right = sino.bottom_right ) # # pp.imshow(Kino,cmap = 'plasma', interpolation = 'nearest', # extent = ( Kino.top_left[ 0 ], Kino.bottom_right[ 0 ], Kino.bottom_right[ 1 ], Kino.top_left[ 1 ] )) # pp.show # Return image with appropriate bounding box: if Toggle == 1: result = np.fft.fftshift(result, 1) return pr.image(result, top_left=sino.top_left, bottom_right=sino.bottom_right)
def fast_radon_transpose(sino): """ Compute backprojection through projection-slice theorem """ # Zero-pad sinogram: fsino = np.zeros((sino_padded_size, sino.shape[1])) fsino[delta + odd_sino:fsino.shape[0] - delta - extra + odd_sino] = sino # Shift sinogram columns: fsino = np.fft.fftshift(fsino, axes=(0, )) # Fourier transform of projections: fsino = np.fft.fft(fsino, axis=0) # Dissasemble transformed sinogram: plan.f = np.reshape(fsino, (fsino.shape[0] * fsino.shape[1], 1)) # Compute adjoint of nouniform Fourier transform: result = plan.adjoint() # Get real part: result = np.real(result) # Normalize: result /= (0.5 * (sino_padded_size - 1) * (img.shape[1] - 1)) return pr.image(result, top_left=img.top_left, bottom_right=img.bottom_right)
def fast_radon(img): """ Compute projection through projection-slice theorem """ # Execute plan: plan.f_hat = img fsino = plan.trafo() #print(fsino.shape) # Assemble sinogram: fsino = np.reshape(fsino, (sino_padded_size, sino.shape[1])) #print(fsino.shape) # Inverse FFT: result = np.fft.ifft(fsino, axis=0) #print(result.shape) # Shift result: result = np.fft.ifftshift(result, axes=(0, )) #print(result.shape) # Remove padding: result = result[delta + odd_sino:result.shape[0] - delta - extra + odd_sino] #print(result.shape) # Get real part: result = np.real(result) # Normalize: result /= (0.5 * (sino.shape[0] - 1)) Kino = pr.image(fsino, top_left=(0, 1), bottom_right=(math.pi, -1)) pp.imshow(Kino, cmap='gray_r', interpolation='nearest', extent=(Kino.top_left[0], Kino.bottom_right[0], Kino.bottom_right[1], Kino.top_left[1])) pp.show # Return image with appropriate bounding box: return pr.image(result, top_left=sino.top_left, bottom_right=sino.bottom_right)
def fast_radon_transpose(sino): """ Compute backprojection through projection-slice theorem """ # Zero-pad sinogram: #fsino = np.zeros( ( sino_padded_size, sino.shape[ 1 ] ) ) #fsino[ delta + odd_sino : fsino.shape[ 0 ] - delta - extra + odd_sino ] = sino fsino = sino # Shift sinogram columns: fsino = np.fft.fftshift(fsino) # Fourier transform of projections: fsino = np.fft.fft(fsino, axis=0) fsino = np.fft.fftshift(fsino) # Compute adjoint of 2D polar Polar Fourier transform: Kino = pr.image(fsino, top_left=img.top_left, bottom_right=img.bottom_right) pp.imshow(Kino, cmap='Greys', interpolation='nearest', extent=(Kino.top_left[0], Kino.bottom_right[0], Kino.bottom_right[1], Kino.top_left[1])) pp.show result = Adjoint(np.transpose(fsino)) # Get real part: result = np.real(result) result /= (0.5 * (sino.shape[0] - 1) * (img.shape[1] - 1)) return pr.image(result, top_left=img.top_left, bottom_right=img.bottom_right)
def importPhoto(): sl = pr.image_read('sl.mat') #pp.imshow( sl, cmap = 'gray_r', interpolation = 'nearest', #extent = ( sl.top_left[ 0 ], sl.bottom_right[ 0 ], sl.bottom_right[ 1 ], sl.top_left[ 1 ] )) #pp.show() sino = pr.image(np.zeros((1024, 1024)), top_left=(0, 1), bottom_right=(math.pi, -1)) fast_radon, fast_transp = fs.make_fourier_slice_radon_transp(sino) sino = fast_radon(sl) #pp.imshow( sino, cmap = 'gray_r', interpolation = 'nearest', #extent = ( sino.top_left[ 0 ], sino.bottom_right[ 0 ], sino.bottom_right[ 1 ], sino.top_left[ 1 ] )) #pp.show() return sino, fast_radon, fast_transp
if __name__ == "__main__": Kino = fft(1) #flip the rows of the 2-D fft before shifting L = range(0, r) L = L[::-1] print(L) Kino = Kino[L, :] #fftshift to center around 0 frequency Kino = np.fft.fftshift(Kino, axes=(0, )) print(Kino.shape) # perform ifft along each radial line to get radon transform (Fourier Slice Theorem) result = np.fft.ifft(Kino, axis=0) Kino = pr.image(Kino, top_left=(0, 1), bottom_right=(math.pi, -1)) # Shift result: result = np.fft.ifftshift(result, axes=(0, )) #adjust for padding result = result[PAD + 1:-PAD + 1, :] print(result.shape) result = np.real(result) # Normalize: result /= (0.5 * (r - 1)) #print result = pr.image(result, top_left=(0, 1), bottom_right=(math.pi, -1)) pp.imshow(result,
import numpy import pyraft dens = numpy.transpose(pyraft.image(numpy.loadtxt('new.dat'))) trans = numpy.transpose(pyraft.image(numpy.loadtxt('ein.dat'))) fluor = numpy.transpose(pyraft.image(numpy.loadtxt('hilb.dat'))) pyraft.imagesc(dens, trans, fluor) d = pyraft.xfct.radon(dens, trans, fluor, [dens.shape[0], 180]) b = pyraft.xfct.backprojection360(d) b2 = pyraft.xfct.backprojection(d, trans, fluor, dens.shape) rec = pyraft.xfct.akt(d, trans, fluor, dens.shape, 10, 0) #rec = pyraft.xfct.em(d, trans, fluor, dens.shape, 50, 0) #pyraft.imagesc(dens, rec) y = pyraft.xfct.fbp360(d) pyraft.imagesc(b, b2, y, rec)
def make_fourier_slice_radon_transp(sino, shape=None): """ make_fourier_slice_radon_transp( shape, sino, sino_zp_factor = 1.5, nfft_zp_factor = 1.2, nfft_m = 2 ) Creates routines for computing the discrete Radon Transform and its conjugate. Parameters: sino : Sinogram. Data is unimportant, but size and ranges are not. shape : Shape of the backprojection result (same of projection argument) You can provide an image instead, in which case its FOV must be the unit square. Returns: return fast_radon, fast_radon_transpose functions for computing the Radon transform and its numerical transpose. Usage: """ if shape is None: shape = (np.max(sino.shape) / 2, np.max(sino.shape[0]) / 2) img = pr.image(shape) #consider dividing by 2 if ( sino.top_left[ 1 ] != 1.0 ) or \ ( sino.bottom_right[ 1 ] != -1.0 ): raise ValueError('Invalid sinogram t range. Must be ( -1.0, 1.0 )') if ( img.top_left != ( -1.0, 1.0 ) ) or \ ( img.bottom_right != ( 1.0, -1.0 ) ): print img.top_left, img.bottom_right raise ValueError( 'Invalid image range. Must be ( -1.0, 1.0 ) x ( -1.0, 1.0 ).') if ( img.shape[ 0 ] != sino.shape[ 0 ] ) or \ ( img.shape[ 1 ] != sino.shape[ 0 ] ): warnings.warn( 'Attention: img and sino should preferably have matching dimensions.' ) # Padded sinogram size (make it even): #sino_padded_size = int( math.ceil( sino_zp_factor * sino.shape[ 0 ] ) ) #sino_padding_size = sino_padded_size - sino.shape[ 0 ] if (sino.top_left[0] == 0 and sino.bottom_right[0] > np.pi / 2): Forward = pseudo.PPFFT Adjoint = pseudo.APPFFT Toggle = 0 elif sino.bottom_right[0] < np.pi: Forward = pseudo.PPFFTBV Adjoint = pseudo.APPFFTBV Toggle = 1 else: Forward = pseudo.PPFFTBH Adjoint = pseudo.APPFFTBH Toggle = 1 def fast_radon(img): """ Compute projection through projection-slice theorem """ # Execute pseudo polar 2D-FFT: fsino = Forward(img) fsino = np.fft.fftshift(fsino) # Inverse FFT: result = np.fft.ifft(fsino, axis=0) # Shift result: result = np.fft.ifftshift(result, axes=(0, )) # Get real part: result = np.real(result) # Normalize: result /= (0.5 * (sino.shape[0] - 1)) # Kino = pr.image(result, top_left = sino.top_left, bottom_right = sino.bottom_right ) # # pp.imshow(Kino,cmap = 'plasma', interpolation = 'nearest', # extent = ( Kino.top_left[ 0 ], Kino.bottom_right[ 0 ], Kino.bottom_right[ 1 ], Kino.top_left[ 1 ] )) # pp.show # Return image with appropriate bounding box: if Toggle == 1: result = np.fft.fftshift(result, 1) return pr.image(result, top_left=sino.top_left, bottom_right=sino.bottom_right) def fast_radon_transpose(sino): """ Compute backprojection through projection-slice theorem """ # Zero-pad sinogram: #fsino = np.zeros( ( sino_padded_size, sino.shape[ 1 ] ) ) #fsino[ delta + odd_sino : fsino.shape[ 0 ] - delta - extra + odd_sino ] = sino fsino = sino # Shift sinogram columns: fsino = np.fft.fftshift(fsino, axes=(0, )) # Fourier transform of projections: fsino = np.fft.fft(fsino, axis=0) fsino = np.fft.fftshift(fsino) pp.show # Compute adjoint of 2D Pseudo Polar Fourier transform: if Toggle == 1: fsino = np.fft.fftshift(fsino, 1) # Kino = pr.image( fsino, top_left = img.top_left, bottom_right = img.bottom_right ) # pp.imshow(Kino,cmap = 'plasma', interpolation = 'nearest', # extent = ( Kino.top_left[ 0 ], Kino.bottom_right[ 0 ], Kino.bottom_right[ 1 ], Kino.top_left[ 1 ] )) result = Adjoint(np.transpose(fsino)) # Get real part: result = np.real(result) # Kino = pr.image( result, top_left = img.top_left, bottom_right = img.bottom_right ) # pp.imshow(Kino,cmap = 'plasma', interpolation = 'nearest', # extent = ( Kino.top_left[ 0 ], Kino.bottom_right[ 0 ], Kino.bottom_right[ 1 ], Kino.top_left[ 1 ] )) # pp.show # Normalize:( sino_padded_size - 1 ) result /= (0.5 * (sino.shape[0] - 1) * (img.shape[1] - 1)) return pr.image(result, top_left=img.top_left, bottom_right=img.bottom_right) return fast_radon, fast_radon_transpose
if c > 5: break x0 = x t0 = t x = y - gamma * grad(x0) x[x < 0] = 0 t = (1 + np.sqrt(1 + 4 * t0**2)) / 2 y = x + (t0 - 1) / t * (x - x0) c += 1 print(c) ## Print Recovered Image print(x) sino_x = fast_radon(x) image_sino = pr.image(sino_x, top_left=(0, 1), bottom_right=(math.pi, -1)) pp.imshow(image_sino, cmap='gray_r', interpolation='nearest', extent=(image_sino.top_left[0], image_sino.bottom_right[0], image_sino.bottom_right[1], image_sino.top_left[1])) pp.show() image = pr.image(x, top_left=(-1, 1), bottom_right=(1, -1)) pp.imshow(image, cmap='gray_r', interpolation='nearest', extent=(image.top_left[0], image.bottom_right[0], image.bottom_right[1], image.top_left[1])) pp.show()
def make_fourier_slice_radon_transp(sino, shape=None, sino_zp_factor=1.5, nfft_zp_factor=1.2, nfft_m=2): """ make_fourier_slice_radon_transp( shape, sino, sino_zp_factor = 1.5, nfft_zp_factor = 1.2, nfft_m = 2 ) Creates routines for computing the discrete Radon Transform and its conjugate. Parameters: sino : Sinogram. Data is unimportant, but size and ranges are not. shape : Shape of the backprojection result (same of projection argument) You can provide an image instead, in which case its FOV must be the unit square. sino_zp_factor : Zero-padding factor for Fourier transform of projection nfft_zp_factor : Zero-padding factor for Fourier transform of image nfft_m : Number of summation terms in nfft series. Returns: return fast_radon, fast_radon_transpose functions for computing the Radon transform and its numerical transpose. Usage: import pyraft as pr import matplotlib.pyplot as pp import h5py import time f = h5py.File( '/home/elias/curimatã/CM-Day3/tomoTesteH2O.h5', 'r' ) v = f[ 'images' ] sino = pr.image( np.transpose( v[ :, 450, : ] ).astype( np.float64 ), x_extent = ( 0.0, math.pi ) ) fast_radon, fast_transp = make_fourier_slice_radon_transp( sino ) st = time.time() bp = fast_transp( sino ) print 'Done!', time.time() - st st = time.time() bp2 = pr.radon_transpose( sino, np.zeros( bp.shape ) ) print 'Done!', time.time() - st pp.imshow( bp, interpolation = 'nearest' ); pp.colorbar(); pp.show() pp.imshow( bp2, interpolation = 'nearest' ); pp.colorbar(); pp.show() st = time.time() rbp = fast_radon( bp ) print 'Done!', time.time() - st st = time.time() rbp2 = pr.radon( bp, pr.image( np.zeros( sino.shape ), x_extent = ( 0.0, math.pi ) ) ) print 'Done!', time.time() - st pp.imshow( rbp, interpolation = 'nearest' ); pp.colorbar(); pp.show() pp.imshow( rbp2, interpolation = 'nearest' ); pp.colorbar(); pp.show() """ if shape is None: shape = (sino.shape[0], sino.shape[0]) img = pr.image(shape) if ( sino.top_left[ 1 ] != 1.0 ) or \ ( sino.bottom_right[ 1 ] != -1.0 ): raise ValueError('Invalid sinogram t range. Must be ( -1.0, 1.0 )') if ( img.top_left != ( -1.0, 1.0 ) ) or \ ( img.bottom_right != ( 1.0, -1.0 ) ): print img.top_left, img.bottom_right raise ValueError( 'Invalid image range. Must be ( -1.0, 1.0 ) x ( -1.0, 1.0 ).') if ( img.shape[ 0 ] != sino.shape[ 0 ] ) or \ ( img.shape[ 1 ] != sino.shape[ 0 ] ): warning.warn( 'Attention: img and sino should preferably have matching dimensions.' ) # Padded sinogram size (make it even): sino_padded_size = int(math.ceil(sino_zp_factor * sino.shape[0])) sino_padding_size = sino_padded_size - sino.shape[0] # Fourier radii of FFT irregular samples: rhos = np.reshape(np.fft.fftfreq(sino_padded_size), (sino_padded_size, 1)) # Angular positions of irregular samples: thetas = np.linspace(sino.top_left[0], sino.bottom_right[0], sino.shape[1]) # Trigonometric values: trig_vals = np.reshape( np.transpose(np.array([np.sin(thetas), -np.cos(thetas)])), (1, thetas.shape[0] * 2)) # Finally, desired irregular samples: sample_positions = np.reshape(rhos * trig_vals, (thetas.shape[0] * rhos.shape[0], 2)) # Computations later required to remove padding. delta = sino_padding_size / 2 extra = sino_padding_size % 2 odd_sino = sino.shape[0] % 2 # Plan nonuniform FFT: plan = nf.NFFT(d=2, N=img.shape, M=sample_positions.shape[0], flags=('PRE_PHI_HUT', 'PRE_PSI'), n=[i * nfft_zp_factor for i in img.shape], m=nfft_m) plan.x = sample_positions plan.precompute() def fast_radon(img): """ Compute projection through projection-slice theorem """ # Execute plan: plan.f_hat = img fsino = plan.trafo() #print(fsino.shape) # Assemble sinogram: fsino = np.reshape(fsino, (sino_padded_size, sino.shape[1])) #print(fsino.shape) # Inverse FFT: result = np.fft.ifft(fsino, axis=0) #print(result.shape) # Shift result: result = np.fft.ifftshift(result, axes=(0, )) #print(result.shape) # Remove padding: result = result[delta + odd_sino:result.shape[0] - delta - extra + odd_sino] #print(result.shape) # Get real part: result = np.real(result) # Normalize: result /= (0.5 * (sino.shape[0] - 1)) Kino = pr.image(fsino, top_left=(0, 1), bottom_right=(math.pi, -1)) pp.imshow(Kino, cmap='gray_r', interpolation='nearest', extent=(Kino.top_left[0], Kino.bottom_right[0], Kino.bottom_right[1], Kino.top_left[1])) pp.show # Return image with appropriate bounding box: return pr.image(result, top_left=sino.top_left, bottom_right=sino.bottom_right) def fast_radon_transpose(sino): """ Compute backprojection through projection-slice theorem """ # Zero-pad sinogram: fsino = np.zeros((sino_padded_size, sino.shape[1])) fsino[delta + odd_sino:fsino.shape[0] - delta - extra + odd_sino] = sino # Shift sinogram columns: fsino = np.fft.fftshift(fsino, axes=(0, )) # Fourier transform of projections: fsino = np.fft.fft(fsino, axis=0) # Dissasemble transformed sinogram: plan.f = np.reshape(fsino, (fsino.shape[0] * fsino.shape[1], 1)) # Compute adjoint of nouniform Fourier transform: result = plan.adjoint() # Get real part: result = np.real(result) # Normalize: result /= (0.5 * (sino_padded_size - 1) * (img.shape[1] - 1)) return pr.image(result, top_left=img.top_left, bottom_right=img.bottom_right) return fast_radon, fast_radon_transpose
#sino2 = fast_radon2( img ) #print np.max( sino2 ) ##pp.imshow( sino2, interpolation = 'nearest', extent = sino2.extent() ); pp.colorbar(); pp.show() #sino3 = pr.radon( pr.shepp_logan_desc(), pr.image( ( N, M ), x_extent = ( 0.0, math.pi ) ) ) ##pp.imshow( sino3, interpolation = 'nearest', extent = sino2.extent() ); pp.colorbar(); pp.show() #pp.imshow( np.absolute( ( sino2 - sino3 ) ), extent = sino2.extent(), interpolation = 'nearest' ); pp.colorbar(); pp.show() #t = np.arange( sino2.shape[ 0 ] ) #pp.plot( t, np.absolute( sino2[ :, 0 ] ), t + 1, np.flipud( sino2[ :, sino2.shape[ 1 ] - 1 ] ), 'r' ); pp.show() import pyraft as pr import matplotlib.pyplot as pp import h5py import time f = h5py.File('/home/elias/curimatã/CM-Day3/tomoTesteH2O.h5', 'r') v = f['images'] sino = pr.image(np.transpose(v[:, 450, :]).astype(np.float64), x_extent=(0.0, math.pi)) fast_radon, fast_transp = make_fourier_slice_radon_transp(sino) st = time.time() bp = fast_transp(sino) print 'Done!', time.time() - st #st = time.time() #bp2 = pr.radon_transpose( sino, np.zeros( bp.shape ) ) #print 'Done!', time.time() - st pp.imshow(bp, interpolation='nearest') pp.colorbar() pp.show() #pp.imshow( bp2, interpolation = 'nearest' ); pp.colorbar(); pp.show()
def make_fourier_slice_radon_transp(sino, shape=None): """ make_fourier_slice_radon_transp( shape, sino, sino_zp_factor = 1.5, nfft_zp_factor = 1.2, nfft_m = 2 ) Creates routines for computing the discrete Radon Transform and its conjugate. Parameters: sino : Sinogram. Data is unimportant, but size and ranges are not. shape : Shape of the backprojection result (same of projection argument) You can provide an image instead, in which case its FOV must be the unit square. Returns: return fast_radon, fast_radon_transpose functions for computing the Radon transform and its numerical transpose. Usage: """ if shape is None: shape = (np.min(sino.shape) + 1, np.min(sino.shape) + 1) img = pr.image(shape) #consider dividing by 2 if ( sino.top_left[ 1 ] != 1.0 ) or \ ( sino.bottom_right[ 1 ] != -1.0 ): raise ValueError('Invalid sinogram t range. Must be ( -1.0, 1.0 )') if ( img.top_left != ( -1.0, 1.0 ) ) or \ ( img.bottom_right != ( 1.0, -1.0 ) ): print img.top_left, img.bottom_right raise ValueError( 'Invalid image range. Must be ( -1.0, 1.0 ) x ( -1.0, 1.0 ).') if ( img.shape[ 0 ] != sino.shape[ 0 ] ) or \ ( img.shape[ 1 ] != sino.shape[ 0 ] ): warnings.warn( 'Attention: img and sino should preferably have matching dimensions.' ) r1 = img.shape[0] PAD = int(np.ceil((r1 * 1.2 - r1) / 2)) # Padded sinogram size (make it even): #sino_padded_size = int( math.ceil( sino_zp_factor * sino.shape[ 0 ] ) ) #sino_padding_size = sino_padded_size - sino.shape[ 0 ] Forward = polar.pfft Adjoint = polar.apfft def fast_radon(img): """ Compute projection through projection-slice theorem """ # Execute polar polar 2D-FFT: fsino = Forward(img) fsino = np.fft.ifftshift(fsino) # Inverse FFT: Kino = pr.image(fsino, top_left=sino.top_left, bottom_right=sino.bottom_right) pp.imshow(Kino, cmap='Greys', interpolation='nearest', extent=(Kino.top_left[0], Kino.bottom_right[0], Kino.bottom_right[1], Kino.top_left[1])) result = np.fft.ifft(fsino, axis=0) # Shift result: result = np.fft.fftshift(result) # Get real part: result = np.real(result) # Normalize: result = result[PAD - 1:-PAD - 1, :] result /= (0.5 * (sino.shape[0] - 1)) return pr.image(result, top_left=sino.top_left, bottom_right=sino.bottom_right) def fast_radon_transpose(sino): """ Compute backprojection through projection-slice theorem """ # Zero-pad sinogram: #fsino = np.zeros( ( sino_padded_size, sino.shape[ 1 ] ) ) #fsino[ delta + odd_sino : fsino.shape[ 0 ] - delta - extra + odd_sino ] = sino fsino = sino # Shift sinogram columns: fsino = np.fft.fftshift(fsino) # Fourier transform of projections: fsino = np.fft.fft(fsino, axis=0) fsino = np.fft.fftshift(fsino) # Compute adjoint of 2D polar Polar Fourier transform: Kino = pr.image(fsino, top_left=img.top_left, bottom_right=img.bottom_right) pp.imshow(Kino, cmap='Greys', interpolation='nearest', extent=(Kino.top_left[0], Kino.bottom_right[0], Kino.bottom_right[1], Kino.top_left[1])) pp.show result = Adjoint(np.transpose(fsino)) # Get real part: result = np.real(result) result /= (0.5 * (sino.shape[0] - 1) * (img.shape[1] - 1)) return pr.image(result, top_left=img.top_left, bottom_right=img.bottom_right) return fast_radon, fast_radon_transpose
def fft(img): nfft_zp_factor = 1.2 A = np.ones((11,11)) # PAD = ([i * nfft_zp_factor for i in A.shape]) # # PAD[0] = int(PAD[0]) # PAD[1] = int(PAD[1]) # print(PAD) # A = np.pad(A, PAD, 'minimum') r,c = A.shape Z = np.zeros((r,c))+0j Z2 = np.zeros((r,c))+0j N = r-1 M = 10 m = M dtheta = np.pi/M F = np.zeros((M,r))+0j if np.mod(M,4) == 0: L = M/4 elif np.mod(M,2) == 0: L = (M-2)/4 fx = np.zeros((r,c))+0j fy = np.zeros((r,c))+0j C = (N+1)/2 C2 = M/2 B = np.zeros((r,1))+0j CK = np.zeros((r,1))+0j for l in range(1,L+1): alpha = np.cos(l*dtheta) for j in range (0,c) : B[j,0] = np.exp(1j*np.pi*alpha*N*(j-N/2)/(N+1)) CK[j,0] = np.exp(1j*np.pi*alpha*N*(j)/(N+1)) for i in range(0,c): Z[i,:] = A[i,:]*B[:,0] Z2[:,i] = A[:,i]*B[:,0] fx[i,:] = np.fft.fft(Z[i,:]) fy[:,i] = np.fft.fft(Z2[:,i]) fx[i,:] *= CK[:,0] fy[:,i] *= CK[:,0] beta = np.sin(l*dtheta) Fx1 = np.zeros((1,r))+0j Fx2 = np.zeros((1,r))+0j Fy1 = np.zeros((1,r))+0j Fy2 = np.zeros((1,r))+0j Fzero = np.zeros((1,r))+0j Fninety = np.zeros((1,r))+0j for k in range(0,r): p = l if k == C: p = 0 ps = 0 for n in range(0,r): Fx1[0,-k-1] = Fx1[0,-k-1] + fx[n,-k-1]*np.exp(-1*1j*2*np.pi*abs((c-k-1)-N/2)*((c+p)-N/2)*beta*(n-N/2)/(l*(N+1))) Fx2[0,k] = Fx2[0,k] + fx[n,k]*np.exp(-1*1j*2*np.pi*abs(k-N/2)*((c-p)-N/2)*beta*(n-N/2)/(l*(N+1))) Fy1[0,k] = Fy1[0,k] + fy[k,n]*np.exp(-1*1j*2*np.pi*abs(k-N/2)*((c+p)-N/2)*beta*(n-N/2)/(l*(N+1))) Fy2[0,k] = Fy2[0,k] + fy[k,n]*np.exp(-1*1j*2*np.pi*abs(k-N/2)*((c-p)-N/2)*beta*(n-N/2)/(l*(N+1))) if l ==1: Fzero[0,-k-1] = Fzero[0,-k-1] + fx[n,-k-1]*np.exp(-1*1j*2*np.pi*abs((c-k-1)-N/2)*((c+ps)-N/2)*beta*(n-N/2)/(l*(N+1))) Fninety[0,k] = Fninety[0,k] + fy[k,n]*np.exp(-1*1j*2*np.pi*abs(k-N/2)*((c+ps)-N/2)*beta*(n-N/2)/(l*(N+1))) F[l,:] = Fx1 F[m-l,:] = Fx2 F[C2+l,:]= Fy1 F[C2-l,:]= Fy2 if l ==1 : F[0,:] = Fzero F[C2,:] = Fninety return pr.image(F, top_left = (0,1), bottom_right = (math.pi,-1))
# extent = ( image_sino.top_left[ 0 ], image_sino.bottom_right[ 0 ], image_sino.bottom_right[ 1 ], image_sino.top_left[ 1 ] )) # pp.show() # Plot the objective function vs time pp.figure(1) pp.plot(T, obj) pp.ylabel('objective function') pp.xlabel('Time (in seconds)') pp.show() # Plot the objective function decrease vs time pp.figure(2) pp.plot(T, obj2) pp.ylabel('objective function decrease') pp.xlabel('Time (in seconds)') pp.show() # Display reconstructed image pp.figure(4) image = pr.image(x, top_left=(-1, 1), bottom_right=(1, -1)) pp.imshow(image, cmap='gray', interpolation='nearest', extent=(image.top_left[0], image.bottom_right[0], image.bottom_right[1], image.top_left[1])) pp.title('SAEM ' + str(M) + ' Subsets - ' + str(N) + 'Iterations (Moderate Noise)') pp.savefig('Visuals/Images/OSTR_noisy_reconstruct_' + str(N) + '_Iter_' + str(M) + '_Subsets.png') pp.show()
row)) * (np.sum(tmp_counts) / np.sum(ffast_radon(np.ones( (row, row))))) # Create M subsets of sinogram col_M = list(split(range(col), M)) fast_radon = [None] * M fast_transp = [None] * M counts = [None] * M dark = [None] * M flat = [None] * M # Create fast radon/transp functions and subdivide data for subsets for i in range(0, M): len_col_m = len(col_M[i]) sino = pr.image(np.zeros((row, len_col_m)), top_left=(col_M[i][0] * math.pi / (col - 1), 1), bottom_right=(col_M[i][-1] * math.pi / (col - 1), -1)) tmp_radon, tmp_transp = fs.make_fourier_slice_radon_transp(sino) fast_radon[i] = tmp_radon fast_transp[i] = tmp_transp counts[i] = tmp_counts[:, col_M[i]] dark[i] = tmp_dark[:, col_M[i]] flat[i] = tmp_flat[:, col_M[i]] # dj = fast_radon(gamma*c(l)) T = np.zeros((N, 1)) obj = np.zeros((N, 1)) SSIM = np.zeros((N, 1)) subseth = np.zeros((M, 1)) itr = 0 subiter_time = np.zeros((M, 1))