Морфология: эрозия и дилатация
Морфология — это «лепка» формы на чёрно-белых масках: то сжать объект, то нарастить.
Морфологические операции — преобразования формы объектов на бинарном (чёрно-белом) изображении с помощью маленького шаблона — структурного элемента.
Где это нужно
После бинаризации (порога) маска редко идеальна: на объекте бывают дыры, вокруг — мелкий «мусор» из отдельных белых пикселей, края рваные. Морфология чистит такие маски. Две базовые операции — эрозия и дилатация — смотрят на окрестность каждого пикселя и решают, оставить его или нет.
- Эрозия: пиксель остаётся объектом (1), только если все его соседи тоже объект. Иначе становится фоном. Эффект — объект «худеет», мелкие точки шума исчезают.
- Дилатация: пиксель становится объектом, если хоть один сосед — объект. Эффект — объект «толстеет», дырки и разрывы заполняются.
Реализуем руками
img = [
[0,0,0,0,0,0,0],
[0,0,0,0,0,0,0],
[0,0,1,1,1,0,0],
[0,0,1,1,1,0,0],
[0,0,1,1,1,0,0],
[0,0,0,0,0,0,0],
[0,0,0,0,0,0,0],
]
def show(m):
for r in m:
print("".join("#" if v else "." for v in r))
def neighbors(m, y, x):
return [m[y + dy][x + dx] for dy in (-1, 0, 1) for dx in (-1, 0, 1)]
def erode(m):
H, W = len(m), len(m[0])
out = [[0] * W for _ in range(H)]
for y in range(1, H - 1):
for x in range(1, W - 1):
out[y][x] = 1 if all(neighbors(m, y, x)) else 0
return out
def dilate(m):
H, W = len(m), len(m[0])
out = [[0] * W for _ in range(H)]
for y in range(1, H - 1):
for x in range(1, W - 1):
out[y][x] = 1 if any(neighbors(m, y, x)) else 0
return out
print("Исходник (квадрат 3x3):")
show(img)
print("Эрозия (сжался до 1x1):")
show(erode(img))
print("Дилатация (разбух до 5x5):")
show(dilate(img))
Вывод:
Исходник (квадрат 3x3): ....... ....... ..###.. ..###.. ..###.. ....... ....... Эрозия (сжался до 1x1): ....... ....... ....... ...#... ....... ....... ....... Дилатация (разбух до 5x5): ....... .#####. .#####. .#####. .#####. .#####. .......
Эрозия «съела» внешний слой пикселей — квадрат 3×3 ужался до точки. Дилатация, наоборот, нарастила слой — стал 5×5. Эффекты противоположны.
Открытие и закрытие
Сила морфологии — в комбинациях. Применяя эрозию, потом дилатацию (или наоборот), получают:
| Операция | Порядок | Зачем |
| Открытие (opening) | эрозия → дилатация | убрать мелкий шум, не меняя размер объекта |
| Закрытие (closing) | дилатация → эрозия | заполнить дырки и разрывы внутри объекта |
Открытие сначала «съедает» мелкие точки шума эрозией, а потом дилатация возвращает крупный объект к прежнему размеру. Закрытие работает зеркально — латает дыры. Эти операции — рабочая лошадка очистки масок перед поиском контуров и подсчётом объектов.
Итог
- Эрозия сжимает объект (нужны все соседи) — убирает мелкий шум.
- Дилатация наращивает (достаточно одного соседа) — заполняет дыры.
- Открытие = эрозия+дилатация (чистит шум), закрытие = дилатация+эрозия (латает дыры).
- Работают на бинарных масках, чистят результат пороговой бинаризации.