# normalize part (mathematically) if normalize: gaussian_2D = gaussian_2D / np.sum(gaussian_2D) return gaussian_2D
可以制作不同大小的高斯核,或多或少都是居中或扁平的。显然,kernel越大,输出的图像越容易模糊。
Sobel 滤波
为了检测边缘,必须对图像应用一个滤波器来提取梯度。
defget_sobel_kernel(k=3): # get range range = np.linspace(-(k // 2), k // 2, k) # compute a grid the numerator and the axis-distances x, y = np.meshgrid(range, range) sobel_2D_numerator = x sobel_2D_denominator = (x ** 2 + y ** 2) sobel_2D_denominator[:, k // 2] = 1# avoid division by zero sobel_2D = sobel_2D_numerator / sobel_2D_denominator return sobel_2D
defget_thin_kernels(start=0, end=360, step=45): k_thin = 3# actual size of the directional kernel # increase for a while to avoid interpolation when rotating k_increased = k_thin + 2
# rotate the 0° angle directional kernel to get the other ones thin_kernels = [] for angle in range(start, end, step): (h, w) = thin_kernel_0.shape # get the center to not rotate around the (0, 0) coord point center = (w // 2, h // 2) # apply rotation rotation_matrix = cv2.getRotationMatrix2D(center, angle, 1) kernel_angle_increased = cv2.warpAffine(thin_kernel_0, rotation_matrix, (w, h), cv2.INTER_NEAREST)
# get the k=3 kerne kernel_angle = kernel_angle_increased[1:-1, 1:-1] is_diag = (abs(kernel_angle) == 1) # because of the interpolation kernel_angle = kernel_angle * is_diag # because of the interpolation thin_kernels.append(kernel_angle) return thin_kernels
directional = self.directional_filter(grad_magnitude) # get indices of positive and negative directions positive_idx = (grad_orientation / 45) % 8 negative_idx = ((grad_orientation / 45) + 4) % 8 thin_edges = grad_magnitude.clone() # non maximum suppression direction by direction for pos_i in range(4): neg_i = pos_i + 4 # get the oriented grad for the angle is_oriented_i = (positive_idx == pos_i) * 1 is_oriented_i = is_oriented_i + (positive_idx == neg_i) * 1 pos_directional = directional[:, pos_i] neg_directional = directional[:, neg_i] selected_direction = torch.stack([pos_directional, neg_directional])
# get the local maximum pixels for the angle is_max = selected_direction.min(dim=0)[0] > 0.0 is_max = torch.unsqueeze(is_max, dim=1)
# apply non maximum suppression to_remove = (is_max == 0) * 1 * (is_oriented_i) > 0 thin_edges[to_remove] = 0.0
# thresholds
if low_threshold isnotNone: low = thin_edges > low_threshold
if high_threshold isnotNone: high = thin_edges > high_threshold # get black/gray/white only thin_edges = low * 0.5 + high * 0.5
if hysteresis: # get weaks and check if they are high or not weak = (thin_edges == 0.5) * 1 weak_is_high = (self.hysteresis(thin_edges) > 1) * weak thin_edges = high * 1 + weak_is_high * 1 else: thin_edges = low * 1