5.13. Лінійні та сусідські фільтри

Операції піксельної математики, розглянуті раніше в цьому розділі, поєднували два зображення попіксельно. Фільтри виконують подібну роботу інакше: вони обчислюють значення кожного вихідного пікселя з невеликого сусідства вхідних пікселів навколо відповідної позиції. Вихідне значення в (x, y) є деякою статистикою – середнім, медіаною, найпоширенішим значенням – вхідних пікселів у невеликому вікні з центром у (x, y).

Ця невелика зміна підходу – від роботи з одним пікселем до вікна пікселів – дозволяє реалізувати цілу сім’ю корисних операцій. Просте середнє у невеликому вікні згладжує шум датчика. Медіана в тому ж вікні усуває одиничні «артефакти» без такого сильного розмивання країв. Двостороннє середнє не згладжує сильні контрастні межі, зберігаючи краї об’єктів та прибираючи шум усередині. Сусідство – це одиниця роботи; вибір статистики визначає, що саме робить фільтр.

5.13.1. Розмір ядра

Кожен сусідський фільтр приймає параметр size, який задає радіус вікна в пікселях. Саме вікно є квадратним і охоплює (2 * size + 1) пікселів з кожного боку – тому size=1 означає сусідство 3 на 3, size=2 означає 5 на 5, size=3 означає 7 на 7 і так далі.

A small image grid with a highlighted 3-by-3 sub-grid representing the filter's neighbourhood. An arrow shows the neighbourhood sliding one pixel to the right. A second arrow shows it sliding down to the next row at the end of the row. The output pixel for each position is drawn under the neighbourhood, with a small note saying that the output is some statistic of the input neighbourhood.

Сусідство ковзає по зображенню по одному пікселю зліва направо і зверху вниз. Кожен вихідний піксель є результатом застосування статистики фільтра до вхідного сусідства з центром у ньому.

Більші розміри означають ширше сусідство, а отже, більш агресивне або м’якше фільтрування. Вартість зростає разом із площею вікна: фільтр із size=3 виконує приблизно в дев’ять разів більше роботи на піксель, ніж фільтр із size=1. Практичне значення за замовчуванням для більшості задач очищення – size=1 або size=2; до більших розмірів варто вдаватися лише тоді, коли мале сусідство не може придушити потрібну ознаку.

5.13.2. Фільтр середнього

mean() замінює кожен піксель арифметичним середнім його сусідства. Результат згладжує попіксельні відхилення в межах вікна, що робить цей фільтр найдешевшим способом придушення шумових «артефактів» датчика: високочастотні відхилення усереднюються, низькочастотний вміст зберігається.

Компромісом є те, що краї та інші різкі ознаки також усереднюються. Яскравий край, який до фільтрації займав один піксель, після фільтра size=1 розтягується до двох-трьох пікселів із плавним зниженням яскравості на схилах. Для чистого зменшення шуму на зображеннях без дрібних деталей (чиста стіна, внутрішня частина кольорового маркера) такий компроміс прийнятний. Для насиченої сцени, де важливі краї, зазвичай краще підходить один із наступних фільтрів.

img.mean(1)        # 3x3 box average -- fast, gentle smoothing
img.mean(2)        # 5x5 box average -- stronger, slower

5.13.3. Медіана, мода, середина

Три інші статистичні сусідські фільтри замінюють просте арифметичне середнє чимось більш стійким до викидів.

median() повертає медіану сусідства – значення, яке опиняється в середині відсортованого списку пікселів вікна. Одиночний дуже яскравий або дуже темний піксель у вікні не зміщує медіану: він просто потрапляє до відкинутих крайніх значень. На практиці медіанна фільтрація усуває поодинокі «артефакти» і шум типу «сіль та перець», не розмиваючи краї, як це робить mean. Ціна – більше обчислень на піксель: сортування вікна повільніше за усереднення – і результат не є строгим середнім, що іноді важливо для подальших математичних операцій.

Параметр percentile (за замовчуванням 0.5) зміщує вибране значення відносно строгої медіани. percentile=0.0 повертає мінімум сусідства, percentile=1.0 – максимум; проміжні значення пропорційно вибирають між ними у відсортованому вікні. Це дає median можливість акцентувати темні або яскраві частини сусідства, зберігаючи стійкість до викидів, властиву порядковій статистиці.

mode() повертає найпоширеніше значення в сусідстві. Корисний, коли модель шуму така: «більшість пікселів правильні, кілька були пошкоджені різною мірою», і правильна відповідь – та, що зустрічається найчастіше, – яку медіана може пропустити, якщо пошкоджені значення скупчуються з одного боку відсортованого вікна.

midpoint() повертає зважену комбінацію мінімуму та максимуму сусідства: bias=0.5 дає середину між ними, bias=0.0 – мінімум, bias=1.0 – максимум. Використовується рідше за інші, але варто знати про нього, коли мета – цілеспрямовано виділяти темні або яскраві ознаки.

5.13.4. Двосторонній – варіант зі збереженням країв

bilateral() – це сусідський фільтр, який найбільше варто розуміти добре. Він дає ефект згладжування, як mean(), але з додатковим обмеженням: чим більше піксель сусідства відрізняється від центрального пікселя, тим менше він впливає на середнє. Результат згладжує внутрішню частину кожної однорідної ділянки, не перетікаючи через краї, що їх розділяють, – а це саме те, чого потребує більшість застосунків.

Два параметри визначають, наскільки агресивно фільтр знецінює пікселі:

  • color_sigma визначає, як різниця кольору впливає на зважування. Менші значення означають суворіше знецінення пікселів, що відрізняються від центрального.

  • space_sigma визначає, як просторова відстань впливає на зважування. Менші значення надають більшу вагу пікселям, близьким до центру.

Значення за замовчуванням (color_sigma=0.1, space_sigma=1.0) є розумними початковими точками; налаштування зазвичай зводиться до запуску фільтра на зразковому кадрі та підбору параметрів до отримання чітких країв і чистих внутрішніх ділянок.

Двосторонній фільтр дорожчий за median() і значно дорожчий за mean(), тому до нього варто вдаватися лише тоді, коли поведінка зі збереженням країв дійсно потрібна застосунку.

5.13.5. Адаптивна порогова обробка

Фільтри середнього, медіани, моди та середини мають однакову пару ключових аргументів, які перетворюють їхній вивід на бінарний поріг:

  • threshold=True перемикає фільтр у режим порогової обробки.

  • offset=N зміщує локальний поріг порівняння на N одиниць.

Механізм безпосередньо базується на звичайній поведінці фільтра. Без threshold=True фільтр обчислює свою статистику по сусідству і записує її у вихідний піксель. З threshold=True фільтр обчислює ту саму статистику, потім порівнює вихідний піксель на тій самій позиції зі статистикою плюс зміщення, і записує максимальне значення для формату, якщо джерело більше, або нуль – якщо ні.

Результатом є бінарне зображення, поріг якого рухається разом із локальною яскравістю по кадру. У яскравих ділянках встановлюється високий поріг, у темних – низький, і піксель переднього плану, що є локально яскравішим за своїх сусідів, визначається як відповідний незалежно від того, чи він знаходиться у яскравій чи темній ділянці – саме така поведінка, яку єдиний глобальний поріг не міг би забезпечити для нерівномірно освітленого зображення.

img.mean(3, threshold=True, offset=5)

Параметр offset – це те місце, де застосунок контролює суворість перевірки. Невелике позитивне зміщення вимагає, щоб вихідний піксель був помітно яскравішим за своїх сусідів для визначення відповідності, що пригнічує хибнопозитивні спрацювання через шум датчика ціною втрати слабкого переднього плану. Невелике від’ємне зміщення вловлює слабкий передній план ціною пропуску частини шуму. Вибір залежить від того, що решта конвеєра робитиме з бінарним виводом.

Three image panels in a row. The first is an input grayscale frame with a brightness gradient and foreground marks scattered across at uniform darkness. The second panel shows a global threshold applied to it: the foreground is correctly classified on the bright side, but the entire dark side reads as foreground because page and foreground both fall below the cutoff. The third panel shows an adaptive threshold applied to the same input: the foreground is correctly classified across the whole frame.

За нерівномірного освітлення єдиний глобальний поріг не може описати передній план у кожній позиції. Сусідський фільтр, запущений із threshold=True, формує поріг, що рухається разом із локальною яскравістю, і правильно класифікує передній план по всьому кадру.

Сімейство фільтрів виконує адаптивну порогову обробку, тому вибір правильного фільтра має значення: mean() для найдешевшого адаптивного порогу, median() коли вхід містить шум типу «сіль та перець», який фільтр має відкинути перед обчисленням локального порогу.