def dct_cut_downsampled(data, cutoff, spacing=0.4): ''' like dctCut but also lowers the sampling rate, creating a compact representation from which the whole downsampled data could be recovered ''' h, w = np.shape(data)[:2] f1 = fft.fftfreq(h * 2, spacing) f2 = fft.fftfreq(w * 2, spacing) wl = 1. / np.abs(reshape(f1, (2 * h, 1)) + 1j * f2.reshape(1, 2 * w)) mask = np.int32(wl >= cutoff) mirror = reflect2D(data) ff = fft.fft2(mirror, axes=(0, 1)) cut = (ff.T * mask.T).T # weird shape broadcasting constraints empty_cols = find(np.all(mask == 0, 0)) empty_rows = find(np.all(mask == 0, 1)) delete_col = len(empty_cols) / 2 #idiv important here delete_row = len(empty_rows) / 2 #idiv important here keep_cols = w - delete_col keep_rows = h - delete_row col_mask = np.zeros(w * 2) col_mask[:keep_cols] = 1 col_mask[-keep_cols:] = 1 col_mask = col_mask == 1 row_mask = np.zeros(h * 2) row_mask[:keep_rows] = 1 row_mask[-keep_rows:] = 1 row_mask = row_mask == 1 cut = cut[row_mask, ...][:, col_mask, ...] w, h = keep_cols, keep_rows result = fft.ifft2(cut, axes=(0, 1))[:h, :w, ...] return result
def dct_upsample_notrim(data, factor=2): ''' Uses the DCT to supsample array data. Nice for visualization. Uses a discrete cosine transform to smoothly supsample image data. Boundary conditions are handeled as reflected. Data is made symmetric, fourier transformed, then inserted into the low-frequency components of a larger array, which is then inverse transformed. Parameters: data (ndarray): frist two dimensions should be height and width. data may contain aribtrary number of additional dimensions factor (int): supsampling factor. ''' print('ALIGNMENT BUG DO NOT USE YET') assert 0 h, w = np.shape(data)[:2] mirrored = reflect2D_1(data) ff = fft.fft2(mirrored, axes=(0, 1)) h2, w2 = np.shape(mirrored)[:2] newshape = (h2 * factor, w2 * factor) + np.shape(data)[2:] result = np.zeros(newshape, dtype=ff.dtype) H = h + 1 #have to add one more on the left to grab the nyqist term W = w + 1 result[:H, :W, ...] = ff[:H, :W, ...] result[-h:, :W, ...] = ff[-h:, :W, ...] result[:H, -w:, ...] = ff[:H, -w:, ...] result[-h:, -w:, ...] = ff[-h:, -w:, ...] result = fft.ifft2(result, axes=(0, 1)) result = result[0:h * factor + factor, 0:w * factor + factor, ...] return result * (factor * factor)
def dct_cut_antialias(data, cutoff, spacing=0.4): ''' Uses brute-force supsampling to anti-alias the frequency space sinc function, skirting numerical issues that derives either from attempting to evaulate the radial sinc function on a small 2D domain, or select a constant frequency cutoff in the frequency space. ''' h, w = np.shape(data)[:2] mask = get_mask_antialiased((h, w), 7, spacing, cutoff) mirror = reflect2D(data) ff2 = fft.fft2(mirror, axes=(0, 1)) cut = (ff2.T * mask.T).T # weird shape broadcasting constraints result = fft.ifft2(cut, axes=(0, 1))[:h, :w, ...] return result
def dct_cut(data, cutoff, spacing=0.4): ''' Low-pass filters image data by discarding high frequency Fourier components. Image data is reflected before being processes (i.e.) mirrored boundary conditions. TODO: I think there is some way to compute the mirrored conditions directly without copying the image data. This function has been superseded by dct_cut_antialias, which is more accurate. ''' print('WARNING DEPRICATED USE dct_cut_antialias') h, w = np.shape(data)[:2] mask = get_mask((h, w), spacing, cutoff) mirror = reflect2D(data) ff2 = fft.fft2(mirror, axes=(0, 1)) cut = (ff2.T * mask.T).T # weird shape broadcasting constraints result = fft.ifft2(cut, axes=(0, 1))[:h, :w, ...] return result