def bandpass(image, lshort, llong, threshold=None): """Convolve with a Gaussian to remove short-wavelength noise, and subtract out long-wavelength variations, retaining features of intermediate scale. Parmeters --------- image : ndarray lshort : small-scale cutoff (noise) llong : large-scale cutoff threshold : float or integer By default, 1 for integer images and 1/256. for float images. Returns ------- ndarray, the bandpassed image """ if threshold is None: if np.issubdtype(image.dtype, np.integer): threshold = 1 else: threshold = 1 / 256. if not 2 * lshort < llong: raise ValueError("The smoothing length scale must be more" + "than twice the noise length scale.") settings = dict(mode='nearest', cval=0) boxcar = uniform_filter(image, 2 * llong + 1, **settings) gaussian = ifftn(fourier_gaussian(fftn(image), lshort)) result = gaussian - boxcar return np.where(result > threshold, result.real, 0)
def fft_gaussian_filter(img, sigma): """FFT gaussian convolution Parameters ---------- img : ndarray Image to convolve with a gaussian kernel sigma : int or sequence The sigma(s) of the gaussian kernel in _real space_ Returns ------- filt_img : ndarray The filtered image """ # This doesn't help agreement but it will make things faster # pull the shape s1 = np.array(img.shape) # s2 = np.array([int(s * 4) for s in _normalize_sequence(sigma, img.ndim)]) shape = s1 # + s2 - 1 # calculate a nice shape fshape = [sig.fftpack.helper.next_fast_len(int(d)) for d in shape] # pad out with reflection pad_img = fft_pad(img, fshape, "reflect") # calculate the padding padding = tuple(_calc_pad(o, n) for o, n in zip(img.shape, pad_img.shape)) # so that we can calculate the cropping, maybe this should be integrated # into `fft_pad` ... fslice = tuple( slice(s, -e) if e != 0 else slice(s, None) for s, e in padding) # fourier transfrom and apply the filter kimg = rfftn(pad_img, fshape) filt_kimg = fourier_gaussian(kimg, sigma, pad_img.shape[-1]) # inverse FFT and return. return irfftn(filt_kimg, fshape)[fslice]
def bandpass(image, lshort, llong, threshold=None): """Convolve with a Gaussian to remove short-wavelength noise, and subtract out long-wavelength variations, retaining features of intermediate scale. Parmeters --------- image : ndarray lshort : small-scale cutoff (noise) llong : large-scale cutoff threshold : float or integer By default, 1 for integer images and 1/256. for float images. Returns ------- ndarray, the bandpassed image """ if threshold is None: if np.issubdtype(image.dtype, np.integer): threshold = 1 else: threshold = 1/256. if not 2*lshort < llong: raise ValueError("The smoothing length scale must be more" + "than twice the noise length scale.") settings = dict(mode='nearest', cval=0) boxcar = uniform_filter(image, 2*llong+1, **settings) gaussian = ifftn(fourier_gaussian(fftn(image), lshort)) result = gaussian - boxcar return np.where(result > threshold, result.real, 0)
def _gaussian_blur_filter(grain_size, domain_size): return pipe( grain_size, lambda x: fourier_gaussian(np.ones(x), np.ones(len(x))), fftshift, zero_pad(shape=domain_size, chunks=None), ).compute()
def legacy_bandpass_fftw(image, lshort, llong, threshold=None): """Remove noise and background variation. Convolve with a Gaussian to remove short-wavelength noise and subtract out long-wavelength variations, retaining features of intermediate scale. This implementation performs a Fourier transform using FFTW (Fastest Fourier Transform in the West). Without FFTW and pyfftw, it will raise an ImportError In benchmarks using typical inputs, it was found to be slower than the ``bandpass`` function in this module. Parameters ---------- image : ndarray lshort : small-scale cutoff (noise) llong : large-scale cutoff for both lshort and llong: give a tuple value for different sizes per dimension give int value for same value for all dimensions when 2*lshort >= llong, no noise filtering is applied threshold : float or integer By default, 1 for integer images and 1/256. for float images. Returns ------- result : array the bandpassed image See Also -------- bandpass, legacy_bandpass """ if not FFTW_AVAILABLE: raise ImportError("This implementation requires pyfftw.") lshort = validate_tuple(lshort, image.ndim) llong = validate_tuple(llong, image.ndim) if np.any([x * 2 >= y for (x, y) in zip(lshort, llong)]): raise ValueError("The smoothing length scale must be more" + "than twice the noise length scale.") if threshold is None: if np.issubdtype(image.dtype, np.integer): threshold = 1 else: threshold = 1 / 256. # Perform a rolling average (boxcar) with kernel size = 2*llong + 1 boxcar = np.asarray(image) for (axis, size) in enumerate(llong): boxcar = uniform_filter1d(boxcar, size * 2 + 1, axis, mode='nearest', cval=0) # Perform a gaussian filter gaussian = ifftn(fourier_gaussian(fftn(image), lshort)).real result = gaussian - boxcar return np.where(result > threshold, result, 0)
def legacy_bandpass_fftw(image, lshort, llong, threshold=None): """Remove noise and background variation. Convolve with a Gaussian to remove short-wavelength noise and subtract out long-wavelength variations, retaining features of intermediate scale. This implementation performs a Fourier transform using FFTW (Fastest Fourier Transform in the West). Without FFTW and pyfftw, it will raise an ImportError In benchmarks using typical inputs, it was found to be slower than the ``bandpass`` function in this module. Parameters ---------- image : ndarray lshort : small-scale cutoff (noise) llong : large-scale cutoff for both lshort and llong: give a tuple value for different sizes per dimension give int value for same value for all dimensions when 2*lshort >= llong, no noise filtering is applied threshold : float or integer By default, 1 for integer images and 1/256. for float images. Returns ------- result : array the bandpassed image See Also -------- bandpass, legacy_bandpass """ if not FFTW_AVAILABLE: raise ImportError("This implementation requires pyfftw.") lshort = validate_tuple(lshort, image.ndim) llong = validate_tuple(llong, image.ndim) if np.any([x*2 >= y for (x, y) in zip(lshort, llong)]): raise ValueError("The smoothing length scale must be more" + "than twice the noise length scale.") if threshold is None: if np.issubdtype(image.dtype, np.integer): threshold = 1 else: threshold = 1/256. # Perform a rolling average (boxcar) with kernel size = 2*llong + 1 boxcar = np.asarray(image) for (axis, size) in enumerate(llong): boxcar = uniform_filter1d(boxcar, size*2+1, axis, mode='nearest', cval=0) # Perform a gaussian filter gaussian = ifftn(fourier_gaussian(fftn(image), lshort)).real result = gaussian - boxcar return np.where(result > threshold, result, 0)
def bandpass(image, lshort, llong): """Convolve with a Gaussian to remove short-wavelength noise, and subtract out long-wavelength variations, retaining features of intermediate scale.""" if not 2 * lshort < llong: raise ValueError, ("The smoothing length scale must be more" "than twice the noise length scale.") smoothed_background = filters.uniform_filter(image, 2 * llong + 1) result = np.fft.ifft2(fourier.fourier_gaussian(np.fft.fft2(image), lshort)) result -= smoothed_background # Where result < 0 that pixel is definitely not a feature. Zero to simplify. return result.real.clip(min=0.)
def bandpass(image, lshort, llong, threshold=1): """Convolve with a Gaussian to remove short-wavelength noise, and subtract out long-wavelength variations, retaining features of intermediate scale.""" if not 2*lshort < llong: raise ValueError("The smoothing length scale must be more" + "than twice the noise length scale.") settings = dict(mode='nearest', cval=0) boxcar = uniform_filter(image, 2*llong+1, **settings) gaussian = ifftn(fourier_gaussian(fftn(image), lshort)) result = gaussian - boxcar return np.where(result > threshold, result.real, 0)
def bandpass(image, lshort, llong, threshold=1): """Convolve with a Gaussian to remove short-wavelength noise, and subtract out long-wavelength variations, retaining features of intermediate scale.""" if not 2 * lshort < llong: raise ValueError("The smoothing length scale must be more" + "than twice the noise length scale.") settings = dict(mode='nearest', cval=0) boxcar = uniform_filter(image, 2 * llong + 1, **settings) gaussian = ifftn(fourier_gaussian(fftn(image), lshort)) result = gaussian - boxcar return np.where(result > threshold, result.real, 0)
def bandpass(image, lshort, llong): """Convolve with a Gaussian to remove short-wavelength noise, and subtract out long-wavelength variations, retaining features of intermediate scale.""" if not 2*lshort < llong: raise ValueError, ("The smoothing length scale must be more" "than twice the noise length scale.") smoothed_background = filters.uniform_filter(image, 2*llong+1) result = np.fft.ifft2(fourier.fourier_gaussian(np.fft.fft2(image), lshort)) result -= smoothed_background # Where result < 0 that pixel is definitely not a feature. Zero to simplify. return result.real.clip(min=0.)
def generate(self): """ Generates a microstructure of dimensions of self.size and grains with dimensions self.grain_size. Returns: periodic microstructure """ if len(self.size) != len(self.grain_size): raise RuntimeError("Dimensions of size and grain_size are" " not equal.") X = np.random.random((self.n_samples,) + self.size) gaussian = fourier_gaussian(np.ones(self.grain_size), np.ones(len(self.size))) filter_ = Filter(np.fft.fftn(gaussian)[None, ..., None]) filter_.resize(self.size) X_blur = filter_.convolve(X[..., None]) return self._assign_phases(X_blur).astype(int)
def bandpass(image, lshort, llong, threshold=None): """Convolve with a Gaussian to remove short-wavelength noise, and subtract out long-wavelength variations, retaining features of intermediate scale. Parmeters --------- image : ndarray lshort : small-scale cutoff (noise) llong : large-scale cutoff for both lshort and llong: give a tuple value for different sizes per dimension give int value for same value for all dimensions when 2*lshort >= llong, no noise filtering is applied threshold : float or integer By default, 1 for integer images and 1/256. for float images. Returns ------- ndarray, the bandpassed image """ lshort = validate_tuple(lshort, image.ndim) llong = validate_tuple(llong, image.ndim) if np.any([x*2 >= y for (x, y) in zip(lshort, llong)]): raise ValueError("The smoothing length scale must be more" + "than twice the noise length scale.") if threshold is None: if np.issubdtype(image.dtype, np.integer): threshold = 1 else: threshold = 1/256. settings = dict(mode='nearest', cval=0) axes = range(image.ndim) sizes = [x*2+1 for x in llong] boxcar = np.asarray(image) for (axis, size) in zip(axes, sizes): boxcar = uniform_filter1d(boxcar, size, axis, **settings) gaussian = ifftn(fourier_gaussian(fftn(image), lshort)).real result = gaussian - boxcar return np.where(result > threshold, result, 0)
def bandpass(image, lshort, llong, threshold=None): """Convolve with a Gaussian to remove short-wavelength noise, and subtract out long-wavelength variations, retaining features of intermediate scale. Parmeters --------- image : ndarray lshort : small-scale cutoff (noise) llong : large-scale cutoff for both lshort and llong: give a tuple value for different sizes per dimension give int value for same value for all dimensions when 2*lshort >= llong, no noise filtering is applied threshold : float or integer By default, 1 for integer images and 1/256. for float images. Returns ------- ndarray, the bandpassed image """ lshort = validate_tuple(lshort, image.ndim) llong = validate_tuple(llong, image.ndim) if np.any([x * 2 >= y for (x, y) in zip(lshort, llong)]): raise ValueError("The smoothing length scale must be more" + "than twice the noise length scale.") if threshold is None: if np.issubdtype(image.dtype, np.integer): threshold = 1 else: threshold = 1 / 256. settings = dict(mode='nearest', cval=0) axes = range(image.ndim) sizes = [x * 2 + 1 for x in llong] boxcar = np.asarray(image) for (axis, size) in zip(axes, sizes): boxcar = uniform_filter1d(boxcar, size, axis, **settings) gaussian = ifftn(fourier_gaussian(fftn(image), lshort)).real result = gaussian - boxcar return np.where(result > threshold, result, 0)
def diffract(self, rot, cutout=True): """ 2D FFT to get diffraction pattern from intensity matrix. Parameters ---------- rot : numpy.ndarray (3, 3), rotation matrix cutout : bool, return diffraction pattern with circle cutout (default True) Returns ------- numpy.ndarray (N,N), diffraction pattern """ N = self.N / self.zoom inv_shear = self.calc_proj(rot) xy = np.copy(np.dot(self.orig, rot)[:, 0:2]) xy = np.dot(xy, inv_shear.T) xy = self.pbc_2d(xy, N) im = self.bin(xy, N) dp = np.fft.fft2(im) dp = fourier_gaussian(dp, self.peak_width / self.zoom) dp = np.fft.fftshift(dp) dp = np.absolute(dp) dp *= dp dp = self.scale(dp) dp = self.shear_back(dp, inv_shear) dp /= dp.max() dp[dp < self.bot] = self.bot dp[dp > self.top] = self.top dp = np.log10(dp) if not cutout: return dp idbig = self.circle_cutout(dp) dp[np.unravel_index(idbig, (self.N, self.N))] = np.log10(self.bot) return dp
def fft_gaussian_filter(img, sigma): """FFT gaussian convolution Parameters ---------- img : ndarray Image to convolve with a gaussian kernel sigma : int or sequence The sigma(s) of the gaussian kernel in _real space_ Returns ------- filt_img : ndarray The filtered image """ # This doesn't help agreement but it will make things faster # pull the shape s1 = np.array(img.shape) # if any of the sizes is 32 or smaller, revert to proper filter if any(s1 < 33): warnings.warn(("Input is small along a dimension," " will revert to `gaussian_filter`")) return gaussian_filter(img, sigma) # s2 = np.array([int(s * 4) for s in _normalize_sequence(sigma, img.ndim)]) shape = s1 # + s2 - 1 # calculate a nice shape fshape = [sig.fftpack.helper.next_fast_len(int(d)) for d in shape] # pad out with reflection pad_img = fft_pad(img, fshape, "reflect") # calculate the padding padding = tuple(_calc_pad(o, n) for o, n in zip(img.shape, pad_img.shape)) # so that we can calculate the cropping, maybe this should be integrated # into `fft_pad` ... fslice = tuple(slice(s, -e) if e != 0 else slice(s, None) for s, e in padding) # fourier transfrom and apply the filter kimg = rfftn(pad_img, fshape) filt_kimg = fourier_gaussian(kimg, sigma, pad_img.shape[-1]) # inverse FFT and return. return irfftn(filt_kimg, fshape)[fslice]
def _grab_real(self): sigma = abs((self.motor.position - FOCUS_POSITION).magnitude) return fourier.fourier_gaussian(self._original, sigma)
from scipy.ndimage.fourier import fourier_gaussian import numpy import scipy print('numpy version:', numpy.__version__) print('scipy version:', scipy.__version__) print('fourier_gaussian:', fourier_gaussian(numpy.ones([1, 1]), 1))
def smoothPlot(self): if not self.plotted_ticket is None: try: if self.filter==0 or 2<=self.filter<=5: congruence.checkStrictlyPositiveNumber(self.filter_sigma_h, "Sigma/Size H") congruence.checkStrictlyPositiveNumber(self.filter_sigma_v, "Sigma/Size V") if self.filter == 1: congruence.checkStrictlyPositiveNumber(self.filter_spline_order, "Spline Order") ticket = self.plotted_ticket.copy() mask = numpy.where(self.plotted_ticket["histogram"] <= self.plotted_ticket["histogram"].max()*self.masking_level) histogram = ticket["histogram"] h_coord = ticket["bin_h_center"] v_coord = ticket["bin_v_center"] norm = histogram.sum() pixel_area = (h_coord[1]-h_coord[0])*(v_coord[1]-v_coord[0]) filter_mode = self.cb_filter_mode.currentText() if self.filter == 0: histogram = filters.gaussian_filter(histogram, sigma=(self.filter_sigma_h, self.filter_sigma_v), mode=filter_mode, cval=self.filter_cval) elif self.filter == 1: histogram = interpolation.spline_filter(histogram, order=int(self.filter_spline_order)) elif self.filter == 2: histogram = filters.uniform_filter(histogram, size=(int(self.filter_sigma_h), int(self.filter_sigma_v)), mode=filter_mode, cval=self.filter_cval) elif self.filter == 3: histogram = numpy.real(numpy.fft.ifft2(fourier.fourier_gaussian(numpy.fft.fft2(histogram), sigma=(self.filter_sigma_h, self.filter_sigma_v)))) elif self.filter == 4: histogram = numpy.real(numpy.fft.ifft2(fourier.fourier_ellipsoid(numpy.fft.fft2(histogram), size=(self.filter_sigma_h, self.filter_sigma_v)))) elif self.filter == 5: histogram = numpy.real(numpy.fft.ifft2(fourier.fourier_uniform(numpy.fft.fft2(histogram), size=(self.filter_sigma_h, self.filter_sigma_v)))) elif self.filter == 6: histogram = self.apply_fill_holes(histogram) histogram[mask] = 0.0 norm /= histogram.sum() ticket["histogram"] = histogram*norm if self.plot_canvas is None: self.plot_canvas = PowerPlotXYWidget() self.image_box.layout().addWidget(self.plot_canvas) cumulated_power_plot = numpy.sum(histogram)*pixel_area energy_min=0.0 energy_max=0.0 energy_step=0.0 self.plot_canvas.cumulated_power_plot = cumulated_power_plot self.plot_canvas.plot_power_density_ticket(ticket, ticket["h_label"], ticket["v_label"], cumulated_total_power=0.0, energy_min=energy_min, energy_max=energy_max, energy_step=energy_step) self.plotted_ticket = ticket except Exception as e: QMessageBox.critical(self, "Error", str(e), QMessageBox.Ok) if self.IS_DEVELOP: raise e
def fourier_gaussian(self, size, *args, **kw): '''see scipy.ndimage.fourier.fourier_gaussian''' return Image(_fourier.fourier_gaussian(self, size, *args, **kw))