def __call__(self, image: np.array, brightness: np.array) -> np.array: # calculate laplace cost l_cost = self.get_laplace_cost(image) l_cost = unfold(l_cost) l_cost = np.ceil(self.laplace_w * l_cost) # calculate direction costs d_cost = self.get_direction_cost(brightness) d_cost = np.ceil(self.direction_w * d_cost) # calculate total static cost total_cost = np.squeeze(l_cost + d_cost) return total_cost
def calculate_single_laplace_cost(image: np.array, laplace_kernel_sz: int) -> np.array: laplace_map = laplace(image, ksize=laplace_kernel_sz) laplace_map = laplace_map[None] # create map of neighbouring pixels costs cost_map = unfold(laplace_map) cost_map = flatten_first_dims(np.squeeze(cost_map)) # leave only direct neighbours cost_map = cost_map[[1, 3, 5, 7], :, :] # get max elements with the opposite sign signs = np.sign(laplace_map) opposites = cost_map * (cost_map * signs < 0) opposites = np.max(np.abs(opposites), axis=0) output = np.abs(laplace_map) > opposites return output
def get_shifted_feats(directions): shifts = np.round(directions * k_distance).astype(np.int) grid = np.stack(np.meshgrid(np.arange(h), np.arange(w), indexing='ij')) # calculate coords of inner/outer pixels coords = grid + shifts # clip values coords[coords < 0] = 0 coords[:, :, -k_distance:] = np.clip(coords[:, :, -k_distance:], 0, w - 1) coords[:, -k_distance:, :] = np.clip(coords[:, -k_distance:, :], 0, h - 1) # get required pixels feats = image[coords[0].reshape(-1), coords[1].reshape(-1)].reshape(h, w) feats = feats / (np.max(feats) + eps) feats = np.ceil((n_values - 1) * feats) feats = unfold(feats[None]).astype(np.int) return feats
def get_magnitude_features(image: np.array, n_values: int, std: int) -> np.array: n_channels, *shape = image.shape grads = np.zeros((n_channels,) + tuple(shape)) # process each RGB channel for i, channel in enumerate(image): channel = gaussian(channel, std) grads[i] = sobel(channel) # choose maximum over the channels grads = np.max(grads, axis=0, keepdims=True) grads = grads - np.min(grads) cost = 1 - grads / np.max(grads) cost = np.ceil((n_values - 1) * cost).astype(np.int) cost = unfold(cost).astype(int) return cost
def get_direction_cost(image: np.array, eps=1e-6) -> np.array: # calculate vectors perpendicular to gradients grads = np.stack([sobel_v(image), -sobel_h(image)]) grads /= (np.linalg.norm(grads, axis=0) + eps) unfolded_grads = unfold(grads) grads = grads[:, None, None, ...] # calculate dot products spatial_feats = create_spatial_feats(image.shape) link_feats = np.einsum('i..., i...', spatial_feats, grads) # get d_p features local_feats = np.abs(link_feats) # get d_q features sign_mask = np.sign(link_feats) distant_feats = sign_mask * np.einsum('i..., i...', spatial_feats, unfolded_grads) # calculate total gradient direction cost total_cost = 2 / (3 * np.pi) * (np.arccos(local_feats) + np.arccos(distant_feats)) return total_cost
def get_direct_pixel_feats(image: np.array, n_values: int) -> np.array: local_feats = image / np.max(image) local_feats = np.ceil((n_values - 1) * local_feats).astype(np.int) local_feats = unfold(local_feats[None]).astype(np.int) return local_feats