Source code for fastimgproto.gridder.kernel_generation

"""
Generation of convolution kernel arrays, with optional sub-pixel origin offset
and and oversampling.
"""

import numpy as np


[docs]class Kernel(object): """ Generates a 2D array representing a sampled kernel function. Args: kernel_func (callable): Callable object, (e.g. :class:`.conv_funcs.Pillbox`,) that returns a convolution co-efficient for a given distance in pixel-widths. support (int): Defines the 'radius' of the bounding box within which convolution takes place. `Box width in pixels = 2*support+1`. (The central pixel is the one nearest to the UV co-ordinates.) For a kernel_func with truncation radius `trunc`, the support should be set to `ceil(trunc+0.5)` to ensure that the kernel function is fully supported for all valid subpixel offsets. offset (tuple): 2-vector subpixel offset from the sampling position of the central pixel to the origin of the kernel function. Ordering is (x_offset,y_offset). Should have values such that `fabs(offset) <= 0.5` otherwise the nearest integer grid-point would be different! oversampling (int): Oversampling ratio, how many kernel pixels to each UV-grid pixel. Defaults to 1 if not given or ``oversampling=None`` is passed. pad (bool): Whether to pad the array by an extra pixel-width. This is used when generating an oversampled kernel that will be used for interpolation. Attributes: array (numpy.ndarray): The sampled kernel function. centre_idx (int): Index of the central pixel kernel_func, support, offset, oversampling : See params. """ def __init__(self, kernel_func, support, offset=(0.0, 0.0), oversampling=None, pad=False, normalize=True): if oversampling is None: oversampling = 1 assert isinstance(oversampling, int) assert isinstance(support, int) assert support >= 1 assert len(offset) == 2 for off_val in offset: assert -0.5 <= off_val <= 0.5 self.oversampling = oversampling self.kernel_func = kernel_func self.offset = offset self.support = support if pad: padding = 1 else: padding = 0 array_size = 2 * (self.support + padding) * self.oversampling + 1 self.centre_idx = (self.support + padding) * self.oversampling # Distance from each pixel's sample position to kernel-centre position: # (units of oversampled pixels) oversampled_xy = np.arange(array_size, dtype=np.float_) - self.centre_idx # Now translate that to distance from sampling origin, in units of # regular pixels: self.x_distance_vec = oversampled_xy / oversampling - offset[0] self.y_distance_vec = oversampled_xy / oversampling - offset[1] # Re-orient y_vec as a column self.y_distance_vec = np.atleast_2d(self.y_distance_vec).T x_kernel_coeffs = self.kernel_func(self.x_distance_vec) y_kernel_coeffs = self.kernel_func(self.y_distance_vec) # Now multiply separable components to get the 2-d kernel: self.array = x_kernel_coeffs * y_kernel_coeffs if normalize: self.array/=self.array.sum()