Задача C. Canny

Входной файл:input.jpg   Ограничение времени:2 сек
Выходной файл:output.txt   Ограничение памяти:512 Мб

Условие

Требуется реализовать на языке Python набор функций, выполняющие этапы применения оператора Кэнни:


import numpy as np

from typing import Tuple


def gaussian_blur(img: np.ndarray, kernel: Tuple[int, int], sigma: float) -> np.ndarray:
    '''Blurs an image using Gaussian filter.

    Arguments:
        img: input image, a 2d np.ndarray.
        kernel: gaussian kernel size.
        sigma: gaussian kernel standard deviation.

    Returns:
        Blurred image, a 2d np.ndarray of the same size and dtype as `img`.
    '''
    pass


def magnitude_and_direction(img: np.ndarray, kernel: np.ndarray) -> Tuple[np.ndarray, np.ndarray]:
    '''Applies a filter to the image and computes magnitude and direction of the gradient.
    The filter is applied using 'reflect' mode for border pixels.
    
    Arguments:
        img: input image, a 2d np.ndarray.
        kernel: the filter kernel, a 2d np.ndarray with odd dimension sizes.
            The kernel is applied over x dimension, kernel.T is applied over y

    Returns:
        Magnitude and direction of the gradient, two 2d np.ndarray objects of the same size and dtype as `img`.
        The direction values lie in range [0, 2 * pi].
    '''
    pass


def edge_thinning(magnitude: np.ndarray, direction: np.ndarray) -> np.ndarray:
    '''Performs edge thinning step of Canny algorithm using 0°, 45°, 90°, 135°, 180° (=0°) gradient direction 
    as described here https://en.wikipedia.org/wiki/Canny_edge_detector#Gradient_magnitude_thresholding_or_lower_bound_cut-off_suppression.
    If the angle is equally close to two groups, the group with lower angle value is selected.

    Arguments:
        magnitude: magnitude of image gradient, a 2d np.ndarray.
        direction: direction of image gradient, a 2d np.ndarray.

    Returns:
        Boolean mask of suppressed pixels (False if a pixel is suppresed, True if preserved), a 2d np.ndarray of the same size as `magnitude` and dtype bool.
    '''
    pass


def edge_tracking(magnitude: np.ndarray, mask: np.ndarray, low_threshold: float, high_threshold: float) -> np.ndarray:
    '''Performs edge tracking step of Canny algorithm. The thresholds are inclusive.

    Arguments:
        magnitude: magnitude of image gradient, a 2d np.ndarray.
        mask: pixel suppression mask, obtained by edge_thinning function.
        low_threshold: weak pixel threshold.
        high_threshold: strong pixel threshold.

    Returns:
        A 2d np.ndarray of the same size as `magnitude` and dtype bool, representing detected edges.
    '''
    pass

В результате выполнения кода примера для следующего изображения должны получиться такие границы.

Формат выходного файла

Код решения должен содержать только импортируемые модули, определение и реализацию функций.

Примеры тестов

Входной файл (input.jpg) Выходной файл (output.txt)
1
img = cv.imread('input.jpg')
img = cv.cvtColor(img, cv.COLOR_BGR2GRAY).astype(float)
blur = gaussian_blur(img, (5, 5), 1)
magnitude, direction = magnitude_and_direction(blur, np.array([[1, 0, -1], [2, 0, -2], [1, 0, -1]]))
mask = edge_thinning(magnitude, direction)
edges = edge_tracking(magnitude, mask, 0.1 * np.max(magnitude), 0.2 * np.max(magnitude))
cv.imwrite('sample.png', edges.astype(int) * 255)
            
sample.png

0.151s 0.017s 19