Как применить простые ядра к изображениям с помощью Python и OpenCV
Я пытался изучить компьютерное зрение с помощью Python и OpenCV, и я всегда натыкался на термины ядро и свертка.
Сначала я попытался полагаться на эти гифки и некоторые краткие объяснения, но я часто путаюсь с их использованием, поэтому решил взглянуть на них получше.
В этой статье я поделюсь кое-чем из того, что я узнал о ядрах и свертках, исследуя некоторые из их основных приложений, таких как размытие, повышение резкости, дистилляция и эрозия.
Ядра и свертки
Как и я, вы можете подумать, что это как-то связано с кукурузой, но это не так.
Ядра в компьютерном зрении - это матрицы, используемые для свертки наших данных. Давай попробуем сломать это.
Свертки - это математические операции между двумя функциями, которые создают третью функцию. При обработке изображений это происходит путем прохождения каждого пикселя для выполнения вычисления с пикселем и его соседями.
Ядра будут определять размер свертки, применяемые к ней веса и точку привязки, обычно расположенную в центре.
Таким образом, в матрице 3x3 на каждый пиксель влияют только пиксели вокруг него, тогда как более дальние пиксели 7x7 изменили бы его.
Хорошо, поэтому, чтобы применить его к изображению, мы должны: расположить его над заданным пикселем, используя его точку привязки, выполнить некоторую операцию между значениями в ядрах и значениями пикселей, определить новое значение для этого пикселя и переместить к следующему.
Резюмируя:
- Мы можем фильтровать и изменять изображения, взаимодействуя с их пикселями;
- Это взаимодействие может происходить с извилинами;
- Эти свертки используют ядра для описания того, как будут затронуты пиксели;
- Ядра представляют собой область для каждой операции, значения / веса и точку привязки;
Руки вверх
Хватит разговоров, давайте посмотрим, как мы можем использовать эти ядра.
Мы будем использовать OpenCV, Numpy и Matplotlib.
import cv2 import numpy as np import matplotlib.pyplot as plt
После импорта библиотек мы можем построить исходное изображение, чтобы знать, что меняется.
image = cv2.imread('Images/6.jpg') image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) fig, ax = plt.subplots(1, figsize=(12,8)) plt.imshow(image)
Круто, теперь давайте сделаем ядро для размытия изображения. Мы будем использовать Numpy, чтобы построить матрицу единиц 3x3 и разделить ее на 9.
>>> kernel = np.ones((3, 3), np.float32) / 9 >>> kernel ... array([[0.11111111, 0.11111111, 0.11111111], [0.11111111, 0.11111111, 0.11111111], [0.11111111, 0.11111111, 0.11111111]], dtype=float32)
Мы можем применить его к изображению с помощью .filter2D.
img = cv2.filter2D(image, -1, kernel) fig, ax = plt.subplots(1, figsize=(12,8)) plt.imshow(img)
Давайте попробуем это с ядром Sharpen.
kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]])
Используя .filter2D, мы можем применять линейные фильтры к любому ядру, которое захотим. Но есть и более удобные способы достижения этих результатов.
Легкий путь
OpenCV имеет несколько удобных функций для фильтрации изображений, и во многих случаях вам даже не нужно определять ядро.
Мы можем использовать .blur, чтобы применить размытие рамки, и нам просто нужно передать изображение и размер ядра.
image = cv2.imread('Images/6.jpg') image = cv2.blur(img, (5,5)) image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) fig, ax = plt.subplots(1, figsize=(12,8)) plt.imshow(image)
Гауссово и медианное размытие:
image = cv2.imread('Images/6.jpg') image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) fig, ax = plt.subplots(1, figsize=(12,16)) ax = plt.subplot(211) g = cv2.GaussianBlur(image, (3,3), 0) plt.imshow(g) ax = plt.subplot(212) m = cv2.medianBlur(image, 3) plt.imshow(m)
Расширения и эрозии
Ядра также могут помочь расширять и размывать изображения - кажется, это полезно при работе с изображениями с текстом.
image = cv2.imread('Images/9.png') # convert to black and white image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) r ,image = cv2.threshold(image, 150, 255, cv2.THRESH_BINARY) # create kernel kernel = np.ones((5,5), np.uint8) fig, ax = plt.subplots(1, figsize=(16,12)) # original ax = plt.subplot(232) plt.imshow(image, cmap='Greys') plt.title('original') # erosion e = cv2.erode(image, kernel) ax = plt.subplot(234) plt.imshow(e, cmap='Greys') plt.title('erosion') # dilation d = cv2.dilate(image, kernel) ax = plt.subplot(235) plt.imshow(d, cmap='Greys') plt.title('dilation') # morphological gradient (dilation - erosion) m = cv2.morphologyEx(image, cv2.MORPH_GRADIENT, kernel) ax = plt.subplot(236) plt.imshow(m, cmap='Greys') plt.title('dilation - erosion')
В этом приложении ядра являются структурирующим элементом, определяющим форму и распространение применяемого эффекта. Несмотря на то, что вам нужно создать матрицу, OpenCV имеет некоторые функции для облегчения этого процесса.
Ядра и свертки намного проще, чем я ожидал, и легче понять, почему они так широко используются при обработке изображений и как они могут усложняться для поддержки таких задач, как классификация изображений, обнаружение объектов и многое другое.
Спасибо, что прочитали мою статью. Надеюсь, вы сможете лучше понять, как свертки используют ядра для выполнения операций.
Ресурсы:
2D-фильтр OpenCV;
Сглаживание OpenCV;
Фильтрация OpenCV;
Морфологические преобразования OpenCV;