Нахождение матриц ребер для соответствующих ребер в изображениях - PullRequest
1 голос
/ 02 мая 2020

Я слежу за этим видео по компьютерному зрению Эндрю Нга и пытаюсь выяснить, как он находит матрицы, которые соответствуют определенной c линии.
Он говорит, что матрица определения вертикальной кромки:

[1 0 -1
1 0 -1
1 0 -1]

Как узнать, какую линию угла даст мне матрица? Например, если я ищу горизонтальную линию или линии 45/30 градусов, как мне найти матрицы?

Обновление:
Я проверил функцию aminrd на следующее изображение с использованием 3 различных углов: 45, 90 и 180.

#Convolve function for convolving a filter on an image
# import the necessary packages
from skimage.exposure import rescale_intensity
import numpy as np
import argparse
import cv2
def convolve(image, kernel):
    # grab the spatial dimensions of the image, along with
    # the spatial dimensions of the kernel
    (iH, iW) = image.shape[:2]
    (kH, kW) = kernel.shape[:2]
    # allocate memory for the output image, taking care to
    # "pad" the borders of the input image so the spatial
    # size (i.e., width and height) are not reduced
    pad = (kW - 1) // 2
    image = cv2.copyMakeBorder(image, pad, pad, pad, pad,
        cv2.BORDER_REPLICATE)
    output = np.zeros((iH, iW), dtype="float32")
    # loop over the input image, "sliding" the kernel across
    # each (x, y)-coordinate from left-to-right and top to
    # bottom
    for y in np.arange(pad, iH + pad):
        for x in np.arange(pad, iW + pad):
            # extract the ROI of the image by extracting the
            # *center* region of the current (x, y)-coordinates
            # dimensions
            roi = image[y - pad:y + pad + 1, x - pad:x + pad + 1]
            # perform the actual convolution by taking the
            # element-wise multiplicate between the ROI and
            # the kernel, then summing the matrix
            k = (roi * kernel).sum()
            # store the convolved value in the output (x,y)-
            # coordinate of the output image
            output[y - pad, x - pad] = k
    # rescale the output image to be in the range [0, 255]
    output = rescale_intensity(output, in_range=(0, 255))
    output = (output * 255).astype("uint8")
    # return the output image
    return output


import matplotlib.pyplot as plt
#original image
image = cv2.imread('circle.jpg')

plt.figure(figsize=(10,10))
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
# as opencv loads in BGR format by default, we want to show it in RGB.
plt.show()

180 градусов на выходе: here

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

new_img= convolve(gray, create_filter(1, 180))

plt.figure(figsize=(10,10))
plt.imshow(new_img, cmap='Greys_r')

plt.show()

90 градусов на выходе: here

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

new_img= convolve(gray, create_filter(1, 90))
plt.figure(figsize=(10,10))
plt.imshow(new_img, cmap='Greys_r')
plt.show()

Выходные изображения выглядят одинаково для угла 45 градусов. Я попробовал это с несколькими фотографиями, и это, кажется, то же самое. Поэтому я не уверен, что что-то упустил, но, похоже, функция выдает похожие результаты для углов 45, 90 и 180 градусов.

1 Ответ

0 голосов
/ 02 мая 2020

Рассмотрим черно-белое изображение. Что такое линия? при масштабировании по вертикальной линии наблюдается контраст слева направо (или справа налево).

Таким образом, в solid областях изображения (где нет ребер), этот фильтр свертки генерирует 0 (потому что 1 и -1 отменяют друг друга). Но когда фильтр достигает линий, Свертка генерирует большое положительное или отрицательное значение.

Может применяться для обнаружения горизонтальных линий с использованием одного из этих фильтров (при условии, что размер фильтра равен 3x3):

 [1  1  1
  0  0  0
 -1 -1 -1]

#OR

 [-1 -1 -1
  0  0  0
  1  1  1] 

Чтобы обобщить идею, a 3x3 окно не достаточно велико для других градусов. Лучше увеличить размер этого сверточного фильтра на другие градусы. Например, для фильтра свертки 45 градусов размера 5 вы можете использовать:

  0  0  0  1  0 
  0  0  1  0 -1
  0  1  0 -1  0
  1  0 -1  0  0
  0  -1 0  0  0

Чтобы создать фильтр со случайными значениями степени, вы можете использовать следующую функцию:

import numpy as np
def create_filter(filter_size, degree):
    filter = np.zeros((2*filter_size+1, 2*filter_size+1))
    tetha = (degree / 180) * np.pi

    for x in range(-filter_size, filter_size+1):
        y = int(x * np.tan(tetha))
        if np.abs(y) + 1 <= filter_size and np.abs(y) - 1 <= filter_size:
            filter[x + filter_size][y + filter_size + 1] = 1
            filter[x + filter_size][y + filter_size - 1] = -1

    return filter

create_filter(6, 30)

# Output:
# array([[ 0.,  0., -1.,  0.,  1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
#        [ 0.,  0.,  0., -1.,  0.,  1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
#        [ 0.,  0.,  0., -1.,  0.,  1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
#        [ 0.,  0.,  0.,  0., -1.,  0.,  1.,  0.,  0.,  0.,  0.,  0.,  0.],
#        [ 0.,  0.,  0.,  0., -1.,  0.,  1.,  0.,  0.,  0.,  0.,  0.,  0.],
#        [ 0.,  0.,  0.,  0.,  0., -1.,  0.,  1.,  0.,  0.,  0.,  0.,  0.],
#        [ 0.,  0.,  0.,  0.,  0., -1.,  0.,  1.,  0.,  0.,  0.,  0.,  0.],
#        [ 0.,  0.,  0.,  0.,  0., -1.,  0.,  1.,  0.,  0.,  0.,  0.,  0.],
#        [ 0.,  0.,  0.,  0.,  0.,  0., -1.,  0.,  1.,  0.,  0.,  0.,  0.],
#        [ 0.,  0.,  0.,  0.,  0.,  0., -1.,  0.,  1.,  0.,  0.,  0.,  0.],
#        [ 0.,  0.,  0.,  0.,  0.,  0.,  0., -1.,  0.,  1.,  0.,  0.,  0.],
#        [ 0.,  0.,  0.,  0.,  0.,  0.,  0., -1.,  0.,  1.,  0.,  0.,  0.],
#        [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0., -1.,  0.,  1.,  0.,  0.]])

...