def maxAPosteriori_smallKernel(image, psf, iterations=10, clip=True, verbose=False): print('This procedure may be very slow! -> Use it with small psf!!!') xp = pyb.get_array_module(image) xps = cupyx.scipy.get_array_module(image) image = image.astype(xp.float) psf = psf.astype(xp.float) im_deconv = xp.full(image.shape, 0.5) psf_flip = axisflip(psf) for i in range(iterations): if verbose == True: print('Iteration ' + str(i)) relative_blur = xps.ndimage.convolve(im_deconv, psf) relative_blur = image / relative_blur - 1 im_deconv *= xp.exp(xps.ndimage.convolve(relative_blur, psf_flip)) if clip: im_deconv[im_deconv > 1] = 1 im_deconv[im_deconv < -1] = -1 return im_deconv
def anchorUpdate_MAP(signal, kernel, prior=0, iterations=10, measure=True, clip=True, verbose=False): xp = cp.get_array_module(signal) signal_deconv = signal signal = signal / signal.sum() kernel = kernel / kernel.sum() epsilon = 1e-7 # starting guess with a flat image if prior.any() == 0: signal_deconv = xp.full(signal.shape, 0.5) + 0.01 * xp.random.rand(*signal.shape) else: signal_deconv = prior #+ 0.1*prior.max()*xp.random.rand(*signal.shape) # to measure the distance between the guess convolved and the signal error = None if measure == True: error = xp.zeros(iterations) for i in range(iterations): if verbose == True: print('Iteration ' + str(i)) kernel_update = my_convolution(signal_deconv, kernel) kernel_update = my_correlation(kernel_update, kernel) kernel_update = kernel_update / kernel_update.sum() kernel_mirror = axisflip(kernel_update) relative_blur = my_convolution(signal_deconv, kernel_update) if measure == True: error[i] = xp.linalg.norm(signal - relative_blur) relative_blur = signal / relative_blur # avoid errors due to division by zero or inf relative_blur[xp.isinf(relative_blur)] = epsilon relative_blur = xp.nan_to_num(relative_blur) # multiplicative update signal_deconv *= xp.exp( my_convolution(relative_blur - 1, kernel_mirror)) if clip: signal_deconv[signal_deconv > +1] = +1 signal_deconv[signal_deconv < -1] = -1 return signal_deconv, error
def maxAPosteriori(signal, kernel, iterations=10, measure=True, clip=True, verbose=False): xp = cp.get_array_module(signal) signal_deconv = signal # starting guess with a flat image signal_deconv = xp.full(signal.shape, 0.5) epsilon = 1e-7 kernel_mirror = axisflip(kernel) # to measure the distance between the guess convolved and the signal error = None if measure == True: error = xp.zeros(iterations) for i in range(iterations): if verbose == True and (i % 100) == 0: print('Iteration ' + str(i)) relative_blur = my_convolution(signal_deconv, kernel) if measure == True: error[i] = xp.linalg.norm(signal - relative_blur) relative_blur = signal / relative_blur # avoid errors due to division by zero or inf relative_blur[xp.isinf(relative_blur)] = epsilon relative_blur = xp.nan_to_num(relative_blur) # multiplicative update signal_deconv *= xp.exp( my_convolution(relative_blur - 1, kernel_mirror)) if clip: signal_deconv[signal_deconv > +1] = +1 signal_deconv[signal_deconv < -1] = -1 return signal_deconv, error
def randomAmorphousVases_3D(intdimension=512, extdimension=1024, volumeradius=2 * (64 + 16), maskradius1=13, maskradius2=11): # definition of 2 concentric masks, used for amorphous generation mask1 = pf.spherical_mask3D(extdimension, extdimension, extdimension, center=None, radius=maskradius1) mask2 = pf.spherical_mask3D(extdimension, extdimension, extdimension, center=None, radius=maskradius2) mask = (np.float32(mask1) - np.float32(mask2)) # this is the mask that select the size of the phantom mask3 = pf.spherical_mask3D(intdimension, intdimension, intdimension, center=None, radius=volumeradius) # random phase and amplitude to associate to the mask phase = 2 * np.pi * np.random.rand(extdimension, extdimension, extdimension) ampli = 1 - 0.01 * np.random.rand(extdimension, extdimension, extdimension) # generation of the volumetric amorphous pattern, this is symmetric randomrods = np.abs(np.fft.fftn(ampli * np.exp(phase * mask))) # select only the portion up to intdimension within mask3 hyp = (randomrods[:intdimension, :intdimension, :intdimension] * mask3) hyp /= hyp.max() hyp_dots = hyp.copy() hyp = 1 - hyp hyp[hyp == 1] = 0 # creating the outer veins threshold_veins = 0.95 sample = np.float32(hyp > threshold_veins) sample = sample * hyp sample = np.float32(sample) - threshold_veins sample[sample < 0] = 0 sample /= sample.max() # creating the inner veins threshold_veins = 0.93 sample_veins = np.float32(hyp > threshold_veins) sample_veins = sample_veins * hyp sample_veins = np.float32(sample_veins) - threshold_veins sample_veins[sample_veins < 0] = 0 sample_veins /= sample_veins.max() # creating the vases by subtracting the veins sample_vase = np.abs(sample_veins - sample) # smooth and sharpen before returning sample_vase = pf.axisflip(hyp**2) * pf.my_gaussblur(sample_vase**2, 0.5) sample_vase = np.abs(sample_vase) sample_vase /= sample_vase.max() return sample_vase
def anchorUpdateSK(signal, kernel, signal_deconv=np.float32(0), iterations=10, measure=True, clip=False, verbose=True): # for code agnosticity between Numpy/Cupy xp = cp.get_array_module(signal) xps = cupyx.scipy.get_array_module(signal) # for performance evaluation start_time = time.time() if iterations<100: breakcheck = iterations else: breakcheck = 100 # normalization signal /= signal.sum() epsilon = 1e-7 # starting guess with a flat image if signal_deconv.any()==0: # xp.random.seed(0) signal_deconv = xp.full(signal.shape,0.5) + 0.01*xp.random.rand(*signal.shape) # signal_deconv = signal.copy() else: signal_deconv = signal_deconv #+ 0.1*prior.max()*xp.random.rand(*signal.shape) # normalization signal_deconv = signal_deconv/signal_deconv.sum() # to measure the distance between the guess convolved and the signal error = None if measure == True: error = xp.zeros(iterations) for i in range(iterations): # I use this property to make computation faster kernel_update = xps.ndimage.gaussian_filter(signal_deconv, sigma) # kernel_update = xps.ndimage.fourier_gaussian(signal_deconv, sigma) kernel_mirror = (kernel_update) relative_blur = my_correlation(signal_deconv, kernel_update) # compute the measured distance metric if given if measure==True: # error[i] = xp.linalg.norm(signal/signal.sum()-relative_blur/relative_blur.sum()) error[i] = snrIntensity_db(signal/signal.sum(), xp.abs(signal/signal.sum()-relative_blur/relative_blur.sum())) if (error[i] < error[i-breakcheck]) and i > breakcheck: break if verbose==True and (i % 100)==0 and measure==False: print('Iteration ' + str(i)) elif verbose==True and (i % 100)==0 and measure==True: print('Iteration ' + str(i) + ' - noise level: ' + str(error[i])) relative_blur = signal / relative_blur # avoid errors due to division by zero or inf relative_blur[xp.isinf(relative_blur)] = epsilon relative_blur = xp.nan_to_num(relative_blur) # multiplicative update, for the full model signal_deconv *= 0.5 * (my_convolution(relative_blur, kernel_mirror) + my_correlation(axisflip(relative_blur), kernel_mirror)) # signal_deconv *= (my_convolution(relative_blur, kernel_mirror) + my_correlation(relative_blur,kernel_mirror)) # multiplicative update, for the Anchor Update approximation # signal_deconv *= my_convolution(kernel_mirror, relative_blur) # multiplicative update, remaining term. This gives wrong reconstructions # signal_deconv *= my_correlation(axisflip(relative_blur), kernel_mirror) if clip: signal_deconv[signal_deconv > +1] = +1 signal_deconv[signal_deconv < -1] = -1 print("\n\n Algorithm finished. Performance:") print("--- %s seconds ----" % (time.time() - start_time)) print("--- %s sec/step ---" % ((time.time() - start_time)/iterations)) return signal_deconv, error #,kernel_update
def anchorUpdateX(signal, kernel, signal_deconv=np.float32(0), kerneltype='B', iterations=10, measure=True, clip=False, verbose=True): """ Reconstruction of signal_deconv from its auto-correlation signal, via a RichardsonLucy-like multiplicative procedure. At the same time, the kernel psf is deconvolved from the reconstruction so that the iteration converges corr(conv(signal_deconv, kernel), conv(signal_deconv, kernel),) -> signal. Parameters ---------- signal : ndarray, either numpy or cupy. The auto-correlation to be inverted kernel : ndarray, either numpy or cupy. Point spread function that blurred the signal. It must be signal.shape == kernel.shape. signal_deconv : ndarray, either numpy or cupy or 0. It must be signal.shape == signal_deconv.shape. The de-autocorrelated signal deconvolved with kernel at ith iteration. The default is np.float32(0). kerneltype : string. Type of kernel update used for the computation choosing from blurring directly the autocorrelation 'A', blurring the signal that is then autocorrelated 'B' and the window applied in fourier domain 'C'. The default is 'B'. iterations : int, optional Number of iteration to be done. The default is 10. measure : boolean, optional If true computes the euclidean distance between signal and the auto-correlation of signal_deconv. The default is True. clip : boolean, optional Clip the results within the range -1 to 1. Useless for the moment. The default is False. verbose : boolean, optional Print current step value. The default is True. Returns ------- signal_deconv : ndarray, either numpy or cupy. The de-autocorrelated signal deconvolved with kernel at ith iteration.. error : vector. Euclidean distance between signal and the auto-correlation of signal_deconv. Last implementation returns the SNR instead of euclidean distance. """ # for code agnosticity between Numpy/Cupy xp = pyb.get_array_module(signal) # for performance evaluation start_time = time.time() if iterations < 100: breakcheck = iterations else: breakcheck = 100 # normalization signal /= signal.sum() kernel /= kernel.sum() epsilon = 1e-7 # compute the norm of the fourier transform of the kernel associated with the IEEE paper if kerneltype == 'A': kernel = xp.abs(xp.fft.rfftn(kernel)) elif kerneltype == 'B': kernel = xp.square(xp.abs(xp.fft.rfftn(kernel))) elif kerneltype == 'C': kernel = xp.abs(xp.fft.irfftn(kernel)) else: print('Wrong input, I have choosen Anchor Update scheme, B') kernel = xp.square(xp.abs(xp.fft.rfftn(kernel))) # starting guess with a flat image if signal_deconv.any() == 0: # xp.random.seed(0) signal_deconv = xp.full(signal.shape, 0.5) + 0.01 * xp.random.rand(*signal.shape) # signal_deconv = signal.copy() else: signal_deconv = signal_deconv #+ 0.1*prior.max()*xp.random.rand(*signal.shape) # normalization signal_deconv = signal_deconv / signal_deconv.sum() # to measure the distance between the guess convolved and the signal error = None if measure == True: error = xp.zeros(iterations) for i in range(iterations): # I use this property to make computation faster kernel_update = my_convcorr_sqfft(signal_deconv, kernel) kernel_mirror = axisflip(kernel_update) relative_blur = my_convolution(signal_deconv, kernel_update) # relative_blur = pyconv.convolve(signal_deconv, kernel_update, mode='same', method='fft') # compute the measured distance metric if given if measure == True: # error[i] = xp.linalg.norm(signal/signal.sum()-relative_blur/relative_blur.sum()) error[i] = snrIntensity_db( signal / signal.sum(), xp.abs(signal / signal.sum() - relative_blur / relative_blur.sum())) if (error[i] < error[i - breakcheck]) and i > breakcheck: break if verbose == True and (i % 100) == 0 and measure == False: print('Iteration ' + str(i)) elif verbose == True and (i % 100) == 0 and measure == True: print('Iteration ' + str(i) + ' - noise level: ' + str(error[i])) relative_blur = signal / relative_blur # avoid errors due to division by zero or inf relative_blur[xp.isinf(relative_blur)] = epsilon relative_blur = xp.nan_to_num(relative_blur) # multiplicative update, for the full model # signal_deconv *= 0.5 * (my_convolution(relative_blur, kernel_mirror) + my_correlation(axisflip(relative_blur), kernel_mirror)) # signal_deconv *= (my_convolution(relative_blur, kernel_mirror) + my_correlation(relative_blur,kernel_mirror)) # multiplicative update, for the Anchor Update approximation signal_deconv *= my_convolution(relative_blur, kernel_mirror) # multiplicative update, remaining term. This gives wrong reconstructions # signal_deconv *= my_correlation(axisflip(relative_blur), kernel_mirror) if clip: signal_deconv[signal_deconv > +1] = +1 signal_deconv[signal_deconv < -1] = -1 print("\n\n Algorithm finished. Performance:") print("--- %s seconds ----" % (time.time() - start_time)) print("--- %s sec/step ---" % ((time.time() - start_time) / iterations)) return signal_deconv, error #,kernel_update
def maxAPosteriori(signal, kernel, iterations=10, measure=True, clip=True, verbose=False): """ Deconvolution using the Maximum a Posteriori algorithm. Implementation identical to Richardson Lucy algorithm but with a different moltiplicative rule for the update. Parameters ---------- signal : ndarray, either numpy or cupy. The signal to be deblurred. kernel : ndarray, either numpy or cupy. Point spread function that blurred the signal. It must be signal.shape == kernel.shape. prior : ndarray, either numpy or cupy, optional the prior information to start the reconstruction. The default is np.float32(0). iterations : integer, optional Number of iteration to be done. The default is 10. measure : boolean, optional If true computes the euclidean distance between signal and the auto-correlation of signal_deconv. The default is True. clip : boolean, optional Clip the results within the range -1 to 1. The default is False. verbose : boolean, optional Print current step value. The default is True. Returns ------- signal_deconv : ndarray, either numpy or cupy. The deconvolved signal with respect the given kernel at ith iteration. error : one dimensional ndarray. Euclidean distance between signal and the auto-correlation of signal_deconv. """ xp = pyb.get_array_module(signal) start_time = time.time() epsilon = 1e-7 # starting guess with a flat image if prior.any() == 0: signal_deconv = xp.full(signal.shape, 0.5) + 0.01 * xp.random.rand(*signal.shape) else: signal_deconv = prior #+ 0.1*prior.max()*xp.random.rand(*signal.shape) kernel_mirror = axisflip(kernel) error = None if measure == True: error = xp.zeros(iterations) for i in range(iterations): if verbose == True and (i % 100) == 0: print('Iteration ' + str(i)) relative_blur = my_convolution(signal_deconv, kernel) if measure == True: error[i] = xp.linalg.norm(signal / signal.sum() - relative_blur / relative_blur.sum()) relative_blur = signal / relative_blur # avoid errors due to division by zero or inf relative_blur[xp.isinf(relative_blur)] = epsilon relative_blur = xp.nan_to_num(relative_blur) # multiplicative update given by the MAP signal_deconv *= xp.exp( my_convolution(relative_blur - 1, kernel_mirror)) if clip: signal_deconv[signal_deconv > +1] = +1 signal_deconv[signal_deconv < -1] = -1 print("\n\n Algorithm finished. Performance:") print("--- %s seconds ----" % (time.time() - start_time)) print("--- %s sec/step ---" % ((time.time() - start_time) / iterations)) return signal_deconv, error
def anchorUpdate_H(signal, kernel, signal_deconv=np.float32(0), iterations=10, measure=True, clip=False, verbose=True): xp = cp.get_array_module(signal) start_time = time.time() signal = signal / signal.sum() # kernel = kernel / kernel.sum() # compute the norm of the fourier transform of the kernel # kernel = xp.fft.rfftn(kernel) epsilon = 1e-7 # starting guess with a flat image if signal_deconv.any() == 0: signal_deconv = xp.full(signal.shape, 0.5) + 0.01 * xp.random.rand(*signal.shape) else: signal_deconv = signal_deconv #+ 0.1*prior.max()*xp.random.rand(*signal.shape) signal_deconv = signal_deconv / signal_deconv.sum() # to measure the distance between the guess convolved and the signal error = None if measure == True: error = xp.zeros(iterations) for i in range(iterations): if verbose == True and (i % 100) == 0: print('Iteration ' + str(i)) # I use this property to make computation faster # kernel_update = my_correlation_withfft(signal_deconv, kernel) kernel_update = my_correlation(signal_deconv, kernel) # kernel_update = kernel_update / kernel_update.sum() kernel_mirror = axisflip(kernel_update) relative_blur = my_convolution(signal_deconv, kernel_update) if measure == True: error[i] = xp.linalg.norm(signal / signal.max() - relative_blur / relative_blur.max()) relative_blur = signal / relative_blur # avoid errors due to division by zero or inf relative_blur[xp.isinf(relative_blur)] = epsilon relative_blur = xp.nan_to_num(relative_blur) # multiplicative update signal_deconv *= my_convolution(relative_blur, kernel_mirror) if clip: signal_deconv[signal_deconv > +1] = +1 signal_deconv[signal_deconv < -1] = -1 print("\n\n Algorithm finished. Performance:") print("--- %s seconds ----" % (time.time() - start_time)) print("--- %s sec/step ---" % ((time.time() - start_time) / iterations)) return signal_deconv, error
def anchorUpdate(signal, kernel, signal_deconv=np.float32(0), iterations=10, measure=True, clip=False, verbose=True): """ Reconstruction of signal_deconv from its auto-correlation signal, via a RichardsonLucy-like multiplicative procedure. At the same time, the kernel psf is deconvolved from the reconstruction so that the iteration converges corr(conv(signal_deconv, kernel), conv(signal_deconv, kernel),) -> signal. Parameters ---------- signal : ndarray, either numpy or cupy. The auto-correlation to be inverted kernel : ndarray, either numpy or cupy. It must be signal.shape == kernel.shape. DESCRIPTION. signal_deconv : ndarray, either numpy or cupy or 0. It must be signal.shape == signal_deconv.shape. The de-autocorrelated signal deconvolved with kernel at ith iteration. The default is np.float32(0). iterations : int, optional Number of iteration to be done. The default is 10. measure : boolean, optional If true computes the euclidean distance between signal and the auto-correlation of signal_deconv. The default is True. clip : boolean, optional Clip the results within the range -1 to 1. Useless for the moment. The default is False. verbose : boolean, optional Print current step value. The default is True. Returns ------- signal_deconv : ndarray, either numpy or cupy. The de-autocorrelated signal deconvolved with kernel at ith iteration.. error : vector. Euclidean distance between signal and the auto-correlation of signal_deconv. """ xp = cp.get_array_module(signal) start_time = time.time() signal = signal / signal.sum() kernel = kernel / kernel.sum() epsilon = 1e-7 # starting guess with a flat image if signal_deconv.any() == 0: signal_deconv = xp.full(signal.shape, 0.5) + 0.01 * xp.random.rand(*signal.shape) else: signal_deconv = signal_deconv # to measure the distance between the guess convolved and the signal error = None if measure == True: error = xp.zeros(iterations) for i in range(iterations): if verbose == True and (i % 100) == 0: print('Iteration ' + str(i)) # kernel update rule kernel_update = my_convolution(signal_deconv, kernel) kernel_update = my_correlation(kernel_update, kernel) kernel_update = kernel_update / kernel_update.sum() kernel_mirror = axisflip(kernel_update) relative_blur = my_convolution(signal_deconv, kernel_update) if measure == True: error[i] = xp.linalg.norm(signal - relative_blur) relative_blur = signal / relative_blur # avoid errors due to division by zero or inf relative_blur[xp.isinf(relative_blur)] = epsilon relative_blur = xp.nan_to_num(relative_blur) # multiplicative update signal_deconv *= my_convolution((relative_blur), kernel_mirror) if clip: signal_deconv[signal_deconv > +1] = +1 signal_deconv[signal_deconv < -1] = -1 print("\n\n Algorithm finished. Performance:") print("--- %s seconds ----" % (time.time() - start_time)) print("--- %s sec/step ---" % ((time.time() - start_time) / iterations)) return signal_deconv, error