def convolve_images(image, kernel, mode='full', method='direct'): """ Convolves image and kernel using square differences sums only 'full' mode is available :param image: gray image where we detect the kernel :param kernel: gray image which we detect in the image :param mode: mode of convolution "valid" or "full" (just for fft) :param method: method of convolution "direct" or "fft" :return: gray image, where black color shows the overlap """ image_vect, kernel_vect = construct_loss_func(image, kernel, method) shape = tuple([ image.shape[i] + kernel.shape[i] - 1 for i in range(len(image.shape)) ]) conv_shape = tuple([ image.shape[i] - kernel.shape[i] + 1 for i in range(len(image.shape)) ]) # print(f"shape: {shape}\nconv_shape: {conv_shape}\n") if method == "direct": if mode == 'valid': convolution = np.zeros(conv_shape) else: assert False, "!!!No such mode available!!!" for y in range(image_vect.shape[2]): if y > image_vect.shape[2] - kernel.shape[1]: break for x in range(image_vect.shape[1]): if x > image_vect.shape[1] - kernel.shape[0]: break curr_image_vect = image_vect[:, x:x + kernel.shape[0], y:y + kernel.shape[1]] convolution[x, y] = (curr_image_vect * kernel_vect).sum() elif method == "fft": full_shape = tuple( [next_fast_len(shape[i], True) for i in range(len(image.shape))]) convolution = np.zeros(full_shape) for idx in range(image_vect.shape[0]): fft_image = rfftn(image_vect[idx, :, :], full_shape) fft_kernel = rfftn(kernel_vect[idx, :, :], full_shape) conv = irfftn(fft_image * fft_kernel, full_shape) convolution += conv conv_slice = tuple([slice(sz) for sz in shape]) # to get back to shape convolution = convolution[conv_slice] # needed full_shape for speed if mode == 'valid': convolution = get_centered_image(convolution, conv_shape) else: assert False, "!!!No such method for convolution!!!" return convolution
def test_rfftn(self): x = random((30, 20, 10)) expect = fft.fftn(x)[:, :, :6] assert_array_almost_equal(expect, fft.rfftn(x)) assert_array_almost_equal(expect, fft.rfftn(x, norm="backward")) assert_array_almost_equal(expect / np.sqrt(30 * 20 * 10), fft.rfftn(x, norm="ortho")) assert_array_almost_equal(expect / (30 * 20 * 10), fft.rfftn(x, norm="forward"))
def fourier_tf(data, fs=128, viz=False, tmp_signal=None, tmp_channel=None): if isinstance(data, pd.DataFrame): tmp = np.absolute( rfftn(data.values.reshape(data.shape[0], 14, 512), axes=2)) else: tmp = np.absolute(rfftn(data.reshape(data.shape[0], 14, 512), axes=2)) fft_freq = rfftfreq(512, 1.0 / fs) if viz == True: plt.plot(fft_freq, t[tmp_signal, tmp_channel, :]) return tmp
def apply_force_pm(self, p, v): rho = self.assign_densities(p) rhobar = (np.sum(rho) / self.n_grid ** 3) delta = (rho - rhobar) / rhobar delta_ft = rfftn(delta, axes=(0, 1, 2)) # / n_grid_cells**(2/3) phi_ft = delta_ft * self.greens_function() phi = irfftn(phi_ft, axes=(0, 1, 2)) g_field = self.get_acceleration_field(phi) g_particle = self.assign_accelerations(p, g_field) g_norm = np.linalg.norm(g_particle, axis=0) cond = g_norm > 50 rhats = g_particle[:, cond] / g_norm[cond] g_particle[:, cond] = (50 - g_norm[cond]) * 0.1 * rhats + 50 * rhats if self.show_ps: # fast k_bin, P = self.power_spectrum_fast(rho, self.k_norm, self.ps_bins) r, xi = self.correlation_function_fast(k_bin, P) P = P * k_bin for rect, h in zip(self.powspec, P): rect.set_height(h) if np.min(P) < 0: self.ax2.set_ylim([np.min(P) * 1.2, np.max(P) * 1.2]) else: self.ax2.set_ylim([0, np.max(P) * 1.2]) for rect, h in zip(self.corrfunc, xi): rect.set_height(h) if np.min(xi) < 0: self.ax3.set_ylim([np.min(xi) * 1.2, np.max(xi) * 1.2]) else: self.ax3.set_ylim([0, np.max(xi) * 1.2]) v += self.f(self.a) * g_particle * self.da return v
def urfftn(inarray, dim=None): """N-dimensional real unitary Fourier transform. This transform considers the Hermitian property of the transform on real-valued input. Parameters ---------- inarray : ndarray, shape (M, N, ..., P) The array to transform. dim : int, optional The last axis along which to compute the transform. All axes by default. Returns ------- outarray : ndarray, shape (M, N, ..., P / 2 + 1) The unitary N-D real Fourier transform of ``inarray``. Notes ----- The ``urfft`` functions assume an input array of real values. Consequently, the output has a Hermitian property and redundant values are not computed or returned. Examples -------- >>> input = np.ones((5, 5, 5)) >>> output = urfftn(input) >>> np.allclose(np.sum(input) / np.sqrt(input.size), output[0, 0, 0]) True >>> output.shape (5, 5, 3) """ if dim is None: dim = inarray.ndim outarray = fft.rfftn(inarray, axes=range(-dim, 0), norm='ortho') return outarray
def power_spectrum_fast(self, rho, k_norm, n_bins): bin_edges = np.linspace(np.min(k_norm), np.max(k_norm), n_bins + 1) bin_width = bin_edges[1] - bin_edges[0] bin_mids = (bin_edges + bin_width)[:-1] G_r = (rho - np.mean(rho)) / np.mean(rho) F_rvec = G_r F_kvec = rfftn(F_rvec, axes=(0, 1, 2)) P_kvec = np.real(F_kvec * np.conj(F_kvec)) P = np.zeros(n_bins) for i in range(n_bins): condition = np.abs(self.half_k_norm - bin_mids[i]) < bin_width / 2 if np.sum(condition) != 0: P[i] = np.sum(P_kvec[condition]) / np.sum(condition) else: P[i] = 0 return bin_mids, P
def compute_FFT_features(x, max_order=-1, channel_axis=0, window_axis=1, sampling_axis=2): ''' inputs: - x (size: (n_signals, window_length, sampling_freq)): the array of 8 PSG signals with sampling frequency 100Hz over 90 seconds for nb_samples samples - max_order (integer): the maximum order of Fourier coefficients considered output: - x_fft (size: (n_signals, windown_length, max_order): the representation of the sequence in the Fourier domain truncated at max_order ''' x_normalized = normalize_apnea_data(x, channel_axis, window_axis, sampling_axis) x_fft = rfftn(x_normalized, axes=[sampling_axis]) if max_order == -1: idxs = range(0, x_fft.shape[sampling_axis]) else: idxs = range(0, max_order) x_fft = np.take(x_fft, indices=idxs, axis=sampling_axis) return x_fft
def test_irfftn(self): x = random((30, 20, 10)) assert_array_almost_equal(x, fft.irfftn(fft.rfftn(x))) assert_array_almost_equal( x, fft.irfftn(fft.rfftn(x, norm="ortho"), norm="ortho"))
def test_rfftn(self): x = random((30, 20, 10)) assert_array_almost_equal(fft.fftn(x)[:, :, :6], fft.rfftn(x)) assert_array_almost_equal(fft.rfftn(x) / np.sqrt(30 * 20 * 10), fft.rfftn(x, norm="ortho"))
def test_irfftn(self): x = random((30, 20, 10)) assert_array_almost_equal(x, fft.irfftn(fft.rfftn(x))) for norm in ["backward", "ortho", "forward"]: assert_array_almost_equal( x, fft.irfftn(fft.rfftn(x, norm=norm), norm=norm))
def correlate_windows(window_a, window_b, correlation_method="fft", nfftx=None, nffty=None, nfftz=None): """Compute correlation function between two interrogation windows. The correlation function can be computed by using the correlation theorem to speed up the computation. Parameters ---------- window_a : 2d np.ndarray a two dimensions array for the first interrogation window, window_b : 2d np.ndarray a two dimensions array for the second interrogation window. correlation_method : string one method is currently implemented: 'fft'. nfftx : int the size of the 2D FFT in x-direction, [default: 2 x windows_a.shape[0] is recommended]. nffty : int the size of the 2D FFT in y-direction, [default: 2 x windows_a.shape[1] is recommended]. nfftz : int the size of the 2D FFT in z-direction, [default: 2 x windows_a.shape[2] is recommended]. Returns ------- corr : 3d np.ndarray a three dimensional array of the correlation function. Note that due to the wish to use 2^N windows for faster FFT we use a slightly different convention for the size of the correlation map. The theory says it is M+N-1, and the 'direct' method gets this size out the FFT-based method returns M+N size out, where M is the window_size and N is the search_area_size It leads to inconsistency of the output """ if correlation_method == "fft": window_b = np.conj(window_b[::-1, ::-1, ::-1]) if nfftx is None: nfftx = nextpower2(window_b.shape[0] + window_a.shape[0]) if nffty is None: nffty = nextpower2(window_b.shape[1] + window_a.shape[1]) if nfftz is None: nfftz = nextpower2(window_b.shape[2] + window_a.shape[2]) f2a = rfftn(normalize_intensity(window_a), s=(nfftx, nffty, nfftz)) f2b = rfftn(normalize_intensity(window_b), s=(nfftx, nffty, nfftz)) corr = irfftn(f2a * f2b).real corr = corr[:window_a.shape[0] + window_b.shape[0], :window_b.shape[1] + window_a.shape[1], :window_b.shape[2] + window_a.shape[2], ] return corr # elif correlation_method == 'direct': # return convolve2d(normalize_intensity(window_a), # normalize_intensity(window_b[::-1, ::-1, ::-1]), 'full') else: raise ValueError("method is not implemented")
def butterworth( image, cutoff_frequency_ratio=0.005, high_pass=True, order=2.0, channel_axis=None, ): """Apply a Butterworth filter to enhance high or low frequency features. This filter is defined in the Fourier domain. Parameters ---------- image : (M[, N[, ..., P]][, C]) ndarray Input image. cutoff_frequency_ratio : float, optional Determines the position of the cut-off relative to the shape of the FFT. high_pass : bool, optional Whether to perform a high pass filter. If False, a low pass filter is performed. order : float, optional Order of the filter which affects the slope near the cut-off. Higher order means steeper slope in frequency space. channel_axis : int, optional If there is a channel dimension, provide the index here. If None (default) then all axes are assumed to be spatial dimensions. Returns ------- result : ndarray The Butterworth-filtered image. Notes ----- A band-pass filter can be achieved by combining a high pass and low pass filter. The literature contains multiple conventions for the functional form of the Butterworth filter. Here it is implemented as the n-dimensional form of .. math:: \\frac{1}{1 - \\left(\\frac{f}{c*f_{max}}\\right)^{2*n}} with :math:`f` the absolute value of the spatial frequency, :math:`c` the ``cutoff_frequency_ratio`` and :math:`n` the ``order`` modeled after [2]_ Examples -------- Apply a high pass and low pass Butterworth filter to a grayscale and color image respectively: >>> from skimage.data import camera, astronaut >>> from skimage.filters import butterworth >>> high_pass = butterworth(camera(), 0.07, True, 8) >>> low_pass = butterworth(astronaut(), 0.01, False, 4, channel_axis=-1) References ---------- .. [1] Butterworth, Stephen. "On the theory of filter amplifiers." Wireless Engineer 7.6 (1930): 536-541. .. [2] Russ, John C., et al. "The image processing handbook." Computers in Physics 8.2 (1994): 177-178. """ fft_shape = (image.shape if channel_axis is None else np.delete( image.shape, channel_axis)) is_real = np.isrealobj(image) float_dtype = _supported_float_type(image.dtype, allow_complex=True) wfilt = _get_ND_butterworth_filter(fft_shape, cutoff_frequency_ratio, order, high_pass, is_real, float_dtype) axes = np.arange(image.ndim) if channel_axis is not None: axes = np.delete(axes, channel_axis) abs_channel = channel_axis % image.ndim post = image.ndim - abs_channel - 1 sl = ((slice(None), ) * abs_channel + (np.newaxis, ) + (slice(None), ) * post) wfilt = wfilt[sl] if is_real: butterfilt = fft.irfftn(wfilt * fft.rfftn(image, axes=axes), s=fft_shape, axes=axes) else: butterfilt = fft.ifftn(wfilt * fft.fftn(image, axes=axes), s=fft_shape, axes=axes) return butterfilt
def butterworth( image, cutoff_frequency_ratio=0.005, high_pass=True, order=2.0, channel_axis=None, *, squared_butterworth=True, npad=0, ): """Apply a Butterworth filter to enhance high or low frequency features. This filter is defined in the Fourier domain. Parameters ---------- image : (M[, N[, ..., P]][, C]) ndarray Input image. cutoff_frequency_ratio : float, optional Determines the position of the cut-off relative to the shape of the FFT. Receives a value between [0, 0.5]. high_pass : bool, optional Whether to perform a high pass filter. If False, a low pass filter is performed. order : float, optional Order of the filter which affects the slope near the cut-off. Higher order means steeper slope in frequency space. channel_axis : int, optional If there is a channel dimension, provide the index here. If None (default) then all axes are assumed to be spatial dimensions. squared_butterworth : bool, optional When True, the square of a Butterworth filter is used. See notes below for more details. npad : int, optional Pad each edge of the image by `npad` pixels using `numpy.pad`'s ``mode='edge'`` extension. Returns ------- result : ndarray The Butterworth-filtered image. Notes ----- A band-pass filter can be achieved by combining a high-pass and low-pass filter. The user can increase `npad` if boundary artifacts are apparent. The "Butterworth filter" used in image processing textbooks (e.g. [1]_, [2]_) is often the square of the traditional Butterworth filters as described by [3]_, [4]_. The squared version will be used here if `squared_butterworth` is set to ``True``. The lowpass, squared Butterworth filter is given by the following expression for the lowpass case: .. math:: H_{low}(f) = \\frac{1}{1 + \\left(\\frac{f}{c f_s}\\right)^{2n}} with the highpass case given by .. math:: H_{hi}(f) = 1 - H_{low}(f) where :math:`f=\\sqrt{\\sum_{d=0}^{\\mathrm{ndim}} f_{d}^{2}}` is the absolute value of the spatial frequency, :math:`f_s` is the sampling frequency, :math:`c` the ``cutoff_frequency_ratio``, and :math:`n` is the filter `order` [1]_. When ``squared_butterworth=False``, the square root of the above expressions are used instead. Note that ``cutoff_frequency_ratio`` is defined in terms of the sampling frequency, :math:`f_s`. The FFT spectrum covers the Nyquist range (:math:`[-f_s/2, f_s/2]`) so ``cutoff_frequency_ratio`` should have a value between 0 and 0.5. The frequency response (gain) at the cutoff is 0.5 when ``squared_butterworth`` is true and :math:`1/\\sqrt{2}` when it is false. Examples -------- Apply a high-pass and low-pass Butterworth filter to a grayscale and color image respectively: >>> from skimage.data import camera, astronaut >>> from skimage.filters import butterworth >>> high_pass = butterworth(camera(), 0.07, True, 8) >>> low_pass = butterworth(astronaut(), 0.01, False, 4, channel_axis=-1) References ---------- .. [1] Russ, John C., et al. The Image Processing Handbook, 3rd. Ed. 1999, CRC Press, LLC. .. [2] Birchfield, Stan. Image Processing and Analysis. 2018. Cengage Learning. .. [3] Butterworth, Stephen. "On the theory of filter amplifiers." Wireless Engineer 7.6 (1930): 536-541. .. [4] https://en.wikipedia.org/wiki/Butterworth_filter """ if npad < 0: raise ValueError("npad must be >= 0") elif npad > 0: center_slice = tuple(slice(npad, s + npad) for s in image.shape) image = np.pad(image, npad, mode='edge') fft_shape = (image.shape if channel_axis is None else np.delete( image.shape, channel_axis)) is_real = np.isrealobj(image) float_dtype = _supported_float_type(image.dtype, allow_complex=True) if cutoff_frequency_ratio < 0 or cutoff_frequency_ratio > 0.5: raise ValueError( "cutoff_frequency_ratio should be in the range [0, 0.5]") wfilt = _get_nd_butterworth_filter(fft_shape, cutoff_frequency_ratio, order, high_pass, is_real, float_dtype, squared_butterworth) axes = np.arange(image.ndim) if channel_axis is not None: axes = np.delete(axes, channel_axis) abs_channel = channel_axis % image.ndim post = image.ndim - abs_channel - 1 sl = ((slice(None), ) * abs_channel + (np.newaxis, ) + (slice(None), ) * post) wfilt = wfilt[sl] if is_real: butterfilt = fft.irfftn(wfilt * fft.rfftn(image, axes=axes), s=fft_shape, axes=axes) else: butterfilt = fft.ifftn(wfilt * fft.fftn(image, axes=axes), s=fft_shape, axes=axes) if npad > 0: butterfilt = butterfilt[center_slice] return butterfilt
for i in adam_e: x, yf = drawfft(np.abs(np.array(i['RVx']))) plt.plot(x, yf) plt.xlim([-5, 5]) plt.ylim([-500, 500]) # %% for i in Bonn_e: x, yf = drawfft(np.abs(np.array(i['RVx']))) plt.plot(x, yf) plt.xlim([-5, 5]) plt.ylim([-500, 500]) # %% a = np.array(adam_e[0])[:1000, :6] # %% af = rfftn(a) # %% af.shape # %% ia = irfftn(af) # %% ia # %% np.max(af) # %% import pywt # %% widths = np.arange(1, 100) cwtmatr, freqs = pywt.cwt(np.array(n[0]['RVx']), widths, 'mexh') plt.imshow(cwtmatr,