5.15. Морфологические операции¶
Морфологические операции работают с бинарными изображениями – масками, получаемыми в результате пороговой обработки и обнаружения границ. Каждая операция обходит ту же скользящую окрестность, что используют сглаживающие фильтры, но вопрос, который она задаёт в каждой позиции, является вопросом «да/нет»: включён ли каждый пиксель в окрестности, включён ли хоть один пиксель в окрестности, как выглядит рисунок включённых/выключенных пикселей? Ответы наращивают области, сжимают их и заново перекраивают их границы способами, недоступными усредняющему фильтру.
Морфология – это то, что стоит между исходной бинарной маской (выходом пороговой обработки, обнаружения границ или другого классификатора) и чистой бинарной маской, которую может использовать остальная часть конвейера. Сырой выход порога обычно содержит изолированные пиксели шума, разбросанные по областям истинного переднего плана, небольшие дыры, пробитые в иначе сплошных областях, и зубчатые границы там, где порог прошёл близко к краю объекта. Морфология устраняет эти дефекты.
5.15.1. Четыре классические операции¶
Две примитивные операции и две их композиции составляют морфологический инструментарий:
dilate() наращивает каждую область переднего плана. Правило таково: любой пиксель, у которого есть хотя бы один сосед переднего плана в его окне (2 * size + 1), становится передним планом. Видимый эффект в том, что области переднего плана увеличиваются на size пикселей во всех направлениях, а дыры внутри них сжимаются (или исчезают) на ту же величину.
erode() делает обратное. Любой пиксель, у которого не каждый сосед в его окне относится к переднему плану, становится фоном. Области переднего плана уменьшаются на size пикселей во всех направлениях, изолированные пиксели переднего плана (у которых нет соседей переднего плана) исчезают полностью, а небольшие соединения между более крупными областями обрезаются.
Четыре классические морфологические операции, применённые к зашумлённой бинарной области. Erode сжимает; dilate наращивает; open – это erode, затем dilate (удаляет шум); close – это dilate, затем erode (заполняет дыры).¶
open() – это erode, за которым следует dilate. Из подвергнутого erode изображения удалён каждый изолированный пиксель шума, но оно также уменьшено на size пикселей во всех направлениях. Применение dilate того же размера после erode восстанавливает подлинные области переднего плана примерно до их исходных границ, оставив шум удалённым. Эта композиция и делает open стандартной операцией «удаления шума» в классической морфологии: изолированные пиксели переднего плана исчезают, реальные области возвращаются невредимыми.
close() – зеркальное отражение, dilate, за которым следует erode. Dilate заполняет небольшие дыры внутри областей переднего плана и соединяет области, разделённые небольшими промежутками; erode сжимает результат обратно к его исходной внешней границе, оставив заполненную внутреннюю часть сплошной. close – это стандартная операция «заполнения небольших промежутков».
binary_mask.open(1) # remove single-pixel noise
binary_mask.close(2) # fill small holes and gaps
Параметр size имеет то же значение, что и в яркостных фильтрах: size=1 означает окрестность 3 на 3, size=2 – 5 на 5 и так далее. Большие размеры означают более агрессивную очистку – и более долгие затраты на пиксель.
5.15.2. Top-hat и black-hat¶
Ещё две композиции стоит знать, потому что они извлекают именно те признаки, которые open и close удаляют:
top_hat() возвращает разность между исходным изображением и его версией после open – пиксели переднего плана, которые open удалил бы. Это буквально маска пикселей шума, изолированных небольших областей переднего плана, тонких структур переднего плана, которые операция open не смогла сохранить. Полезно для извлечения небольших признаков переднего плана, когда именно эти признаки важны приложению, а не для их удаления.
black_hat() возвращает разность между версией изображения после close и исходным изображением – пиксели фона, которые close заполнил бы. Это маска небольших дыр внутри областей переднего плана и узких промежутков между областями, которые операция close соединила бы.
К обеим прибегают реже, чем к четырём базовым операциям, но этот приём стоит запомнить – когда приложению нужно извлечь небольшие или тонкие признаки, которые стандартный проход очистки удаляет, top-hat и black-hat являются естественным способом вернуть их.
5.15.3. Режим порога¶
Все четыре базовые морфологические операции принимают целочисленное именованное значение threshold, которое смягчает тест «включён/выключен» в каждой позиции. Без него операции ведут себя так, как описано выше: erode() требует, чтобы каждый сосед был включён, dilate() требует хотя бы одного. С заданным threshold каждая операция допускает указанное число соседей, голосующих иначе. Для erode threshold – это число фоновых соседей, которые пиксель может иметь и всё же сохраниться: threshold=4 сохраняет любой пиксель, у которого включены хотя бы четыре из восьми соседей (в окне 3 на 3 центральный пиксель имеет восемь соседей), так что erode действует менее агрессивно. Для dilate threshold – это число передних соседей, которое фоновый пиксель должен превысить, прежде чем включиться: threshold=2 требует хотя бы трёх соседей переднего плана вместо одного, так что наращивание идёт менее агрессивно.
Форма с порогом полезна для настройки агрессивности морфологического прохода без изменения размера его окна, что также изменило бы масштаб признаков, на которые он воздействует. Большинство приложений придерживаются поведения по умолчанию; форма с порогом существует для случаев, когда поведение по умолчанию совсем чуть-чуть избыточно или недостаточно.