дискретный домен
Свертка делится на свертку с непрерывной функцией и свертку с дискретной функцией, Поскольку большая часть нашей фактической работы — это цифровая сцена, нам нужна операция свертки в дискретной области. Для двух дискретных функций f и g операция свертки преобразует интегральную операцию непрерывной функции в эквивалентную сумму:
ядро свертки
Для изображения оно принадлежит двумерным данным, поэтому оно соответствует 2D-функции Мы можем фильтровать изображение через фильтр, который является ядром свертки. Вообще говоря, каждое измерение фильтра может содержать от 2 до 5 элементов, и разные фильтры имеют разные эффекты обработки.
Для изображений после обработки конкретным ядром свертки будет получено эквивалентное изображение, но оно может выделять определенные элементы на изображении, такие как линии и края, а также может скрывать определенные элементы на изображении.
Свертка изображения
Мы определяем пять фильтров: Identity, Laplacian, Left Sobel, Upper Sobel и Blur`, которые все являются ядрами свертки 3 x 3. Различные ядра свертки будут выделять различные атрибуты признаков исходного изображения.
Фильтр Blur эквивалентен вычислению среднего значения соседей в пределах 3x3. Фильтр Identity просто возвращает значения пикселей как есть. Фильтры Лапласа — это дифференциальные фильтры, используемые для выделения краев. Фильтр Левого Собеля используется для обнаружения горизонтальных краев, а фильтр Верхнего Собеля — для обнаружения вертикальных краев.
kernels = OrderedDict({"Identity": [[0, 0, 0], [0., 1., 0.], [0., 0., 0.]],
"Laplacian": [[1., 2., 1.], [0., 0., 0.], [-1., -2., -1.]],
"Left Sobel": [[1., 0., -1.], [2., 0., -2.], [1., 0., -1.]],
"Upper Sobel": [[1., 2., 1.], [0., 0., 0.], [-1., -2., -1.]],
"Blur": [[1. / 16., 1. / 8., 1. / 16.], [1. / 8., 1. / 4., 1. / 8.],
[1. / 16., 1. / 8., 1. / 16.]]})
def apply3x3kernel(image, kernel):
newimage = np.array(image)
for m in range(1, image.shape[0] - 2):
for n in range(1, image.shape[1] - 2):
newelement = 0
for i in range(0, 3):
for j in range(0, 3):
newelement = newelement + image[m - 1 + i][n - 1 + j] * kernel[i][j]
newimage[m][n] = newelement
return newimage
arr = imageio.imread("data/dog.jpg")[:, :, 0].astype(np.float)
plt.figure(1)
j = 0
positions = [321, 322, 323, 324, 325, 326]
for key, value in kernels.items():
plt.subplot(positions[j])
out = apply3x3kernel(arr, value)
plt.imshow(out, cmap=plt.get_cmap('binary_r'))
j = j + 1
plt.show()
В сгенерированном графике первое подизображение является неизмененным изображением, потому что здесь мы используем фильтр идентификации, за которым следует обнаружение лапласовских краев, обнаружение горизонтальных краев, обнаружение вертикальных краев и, наконец, размытие.
объединение изображений
Операция объединения в основном достигает эффекта уменьшения параметров через ядро.Более известными операциями объединения являются максимальное значение (максимальное объединение), среднее значение (среднее объединение) и минимальное значение (минимальное объединение). Это уменьшает количество информации, поступающей от предыдущих сетевых уровней, тем самым уменьшая сложность при сохранении наиболее важных информационных элементов. Другими словами, они создают компактные представления информации.
def apply2x2pooling(image, stride):
newimage = np.zeros((int(image.shape[0] / 2), int(image.shape[1] / 2)), np.float32)
for m in range(1, image.shape[0] - 2, 2):
for n in range(1, image.shape[1] - 2, 2):
newimage[int(m / 2), int(n / 2)] = np.max(image[m:m + 2, n:n + 2])
return (newimage)
arr = imageio.imread("data/dog.jpg")[:, :, 0].astype(np.float)
plt.figure(1)
plt.subplot(121)
plt.imshow(arr, cmap=plt.get_cmap('binary_r'))
out = apply2x2pooling(arr, 1)
plt.subplot(122)
plt.imshow(out, cmap=plt.get_cmap('binary_r'))
plt.show()
Вы можете увидеть некоторые различия до и после объединения изображений, а результирующее изображение имеет более низкое разрешение, а общее количество пикселей составляет около четверти исходного.
github
------------- Рекомендуем прочитать ------------
Зачем писать «Анализ проектирования ядра Tomcat»
Резюме моей статьи за 2017 год — машинное обучение
Краткое изложение моих статей за 2017 год — Java и промежуточное ПО
Резюме моих статей 2017 года — глубокое обучение
Краткое изложение моих статей за 2017 год — исходный код JDK
Резюме моей статьи за 2017 год — обработка естественного языка
Резюме моих статей 2017 года — Java Concurrency
Поговори со мной, задай мне вопросы:
Добро пожаловать, чтобы следовать: