Морфологические операции: Dilate (дилатация, расширение) и Erode (эрозия, сжатие)
Морфологические операции — это методы обработки изображений, которые применяются к бинарным (черно-белым) или полутоновым изображениям для обработки и анализа форм объектов. Эти операции используют так называемые структурные элементы (ядра) для изменения формы объектов на изображении.
Два основных типа морфологических операций — dilate (расширение) и erode (сжатие). Они играют ключевую роль в анализе и обработке изображений, особенно в задачах, связанных с удалением шума, усилением контуров и корректировкой форм объектов.
Dilate — это морфологическая операция, которая расширяет светлые области на изображении, увеличивая размер объектов. Она делает белые (яркие) пиксели более "жирными", расширяя их в зависимости от размера и формы структурного элемента. Операция "расширение" особенно полезна для соединения разорванных участков и усиления линий или краев объектов.
- Как работает расширение?: При операции dilate структурный элемент перемещается по изображению, и если хотя бы один пиксель из области, соответствующей ядру, совпадает с белым (ярким), то центральный пиксель тоже становится белым. Это приводит к расширению светлых областей.
Erode — это морфологическая операция, которая сужает светлые области на изображении, уменьшая размер объектов. Эрозия делает белые (яркие) пиксели более "тонкими", уменьшая их в зависимости от размера и формы структурного элемента. Эрозия полезна для удаления мелких шумов, отделения соединенных объектов и уменьшения размеров объектов.
- Как работает эрозия?: При эрозии структурный элемент перемещается по изображению, и если хотя бы один пиксель из области, соответствующей ядру, совпадает с черным (темным), то центральный пиксель тоже становится черным. Это приводит к уменьшению светлых областей.
Посмотрим, как это работает. Возьмем зашумленное изображение (точнее уже его бинарную маску), содержащее два интересующих нас объекта.

В реальных условиях, когда меняется уровень освещения, подобрать диапазоны сложно, всегда будут попадаться оттенки, не попадающие в выбранный диапазон, создавая шум, который будет мешать поиску контуров объектов.
import cv2
import numpy as np
image = cv2.imread('example.png')
image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
kernel = np.ones((5, 5), np.uint8)
eroded_image = cv2.erode(image, kernel, iterations=1)
dilated_image = cv2.dilate(image, kernel, iterations=1)
cv2.imwrite('eroded_image.png', eroded_image)
cv2.imwrite('dilated_image.png', dilated_image)
Создание структурного элемента (ядра)
kernel = np.ones((5, 5), np.uint8)
- Структурный элемент (ядро) создается в виде матрицы размера 5x5, заполненной единицами. Ядро определяет форму и размер области, которая используется для применения морфологических операций. Чем больше размер ядра, тем более выражен эффект расширения или сжатия.
Применение эрозии
eroded_image = cv2.erode(image, kernel, iterations=1)
- Функция
cv2.erode()
выполняет операцию эрозии на изображении image
с использованием ядра kernel
.
iterations=1
: Количество раз, которое операция эрозии применяется последовательно. Увеличение этого значения усилит эффект эрозии. На представленных ниже изображениях операция эрозии применена один, два и три раза соответственно.

Как видите, с каждой последующей операцией черные точки увеличиваются.
Важно обратить внимание! Даже после однократного применения erode()
исчез весь шум типа "соль", т.е. мелкие белые пиксели по всему изображению, в чем и есть основная задача данной операции
Применение операции "расширение"
dilated_image = cv2.dilate(image, kernel, iterations=1)
- Функция
cv2.dilate()
выполняет операцию расширения на изображении image
с использованием ядра kernel
.
iterations=1
: Количество раз, которое операция расширения применяется последовательно. Увеличение этого значения усилит эффект. На представленных ниже изображениях операция dilate()
применена один, два и три раза соответственно.

Как видите, с каждой последующей операцией белые точки увеличиваются.
Важно обратить внимание! Даже после однократного применения dilate()
исчез весь шум типа "перец", т.е. мелкие черные пиксели внутри обнаруженных "объектов", в чем и есть основная задача данной операции.
В обоих операциях важно подобрать параметры под конкретную задачу, чтобы не допустить слияния объектов и сильного изменения их размеров.
Но как же убрать оба типа шума?
Для этого можно сочетать эти операции:
-
Открытие (Opening): Последовательное применение erode()
, а затем dilate()
. Используется для удаления мелких объектов или шумов на изображении, сохраняя при этом формы крупных объектов.
eroded_image = cv2.erode(noisy_image, kernel, iterations=1)
opened_image = cv2.dilate(eroded_image, kernel, iterations=1)
Также эта операция может быть выполнена в одну строку:
opened_image = cv2.morphologyEx(noisy_image, cv2.MORPH_OPEN, kernel)
В первом варианте, вы можете более гибко настроить количество повторений каждой из операций. В результате данной операции мы получим объект, близкий по форме к исходному, однако все лишние белые пиксели с изображения будут удалены!
→ 
-
Закрытие (Closing): Последовательное применение dilate(), а затем erode(). Используется для заполнения мелких пробелов внутри объектов или соединения близко расположенных объектов.
dilated_image = cv2.dilate(noisy_image, kernel, iterations=1)
closed_image = cv2.erode(dilated_image, kernel, iterations=1)
Также эта операция может быть выполнена в одну строку:
closed_image = cv2.morphologyEx(image, cv2.MORPH_CLOSE, kernel)
В результате данной операции мы получим объект, близкий по форме к исходному, однако все лишние черные пиксели внутри объектов будут удалены. Также, в зависимости от количества повторений, могут быть соединены мелкие детали объекта в единый контур.
→ 
-
Последовательное применение операций открытия и закрытия, позволяет эффективно справляться с двумя видами шумов:
opened_image = cv2.morphologyEx(noisy_image, cv2.MORPH_OPEN, kernel)
unnoised_image = cv2.morphologyEx(opened_image, cv2.MORPH_CLOSE, kernel)

- Градиент (Morphological Gradient): Разница между расширением и сжатием. Это помогает выявить контуры и края объектов на изображении.
gradient_image = cv2.morphologyEx(image, cv2.MORPH_GRADIENT, kernel)

Конечно же, перед применение операции градиент, стоит очистить изображение от шумов. Иначе результат может выглядеть так:

Дальнейшая работа, с таким изображением будет сильно затруднена!
Преимущества и недостатки морфологических операций
Преимущества:
- Эффективное удаление шумов и улучшение качества изображения: Операции сжатия и расширения могут эффективно удалять мелкие шумы, не влияя на крупные объекты.
- Простота и эффективность: Эти операции легко реализуются и выполняются быстро, что делает их подходящими для задач реального времени.
- Гибкость применения: Комбинируя сжатие и расширение, можно получить разнообразные эффекты, улучшая или изменяя форму объектов.
Недостатки:
- Зависимость от параметров: Эффективность операций зависит от правильного выбора размеров и формы структурного элемента.
- Ограничения на типы изображений: Морфологические операции лучше всего работают на бинарных или полутоновых изображениях. На цветных изображениях они менее эффективны и требуют предварительного преобразования.