5.5. Області та маски¶
Кожна операція в модулі image за замовчуванням обробляє кожен піксель вихідного зображення. Це найпростіша поведінка, і вона правильна, коли алгоритм справді охоплює весь кадр – рівномірна корекція кольору, глобальна гістограма, прохід кодування для передачі. Але більшість алгоритмів на практиці хочуть аналізувати менший фрагмент. Трекер плями, що стежить за кольоровим маркером, цікавиться лише тією частиною сцени, де маркер може з’явитися, а не стіною за ним. Прохід морфологічного очищення безпечний лише над пікселями, які попередній етап позначив як кандидати. Детектор облич може запускатися лише всередині обмежувального прямокутника, звуженого грубішим детектором. Модуль image підтримує таку роботу через два механізми, що обмежують операцію підмножиною пікселів: прямокутні області інтересу та двійкові маски. Вони вільно поєднуються, і майже кожен метод, що торкається пікселів, приймає один або інший – або обидва – як іменований аргумент.
5.5.1. Області інтересу¶
Область інтересу – це прямокутник пікселів, що задається четвіркою (x, y, w, h), введеною на сторінці координат. Близько тридцяти методів приймають іменований аргумент roi; коли він присутній, операція виконується лише над пікселями всередині цього прямокутника, залишаючи решту зображення недоторканою. Коли roi має значення None або пропущено, операція виконується над усім зображенням – так само, як якби було передано roi=(0, 0, width, height).
У коді цей аргумент стоїть поряд з іншими аргументами операції:
# Compute a histogram over a centred crop of the image.
h = img.get_histogram(roi=(64, 64, 128, 128))
Першою перевагою ROI є контроль хибних спрацювань. Трекер кольору, що дивиться лише на стіл, ніколи не спрацює на людину, що проходить повз; детектор меж, що запускається лише всередині визначеної робочої зони, ніколи не повідомить про межі самого кріплення камери. Скорочення простору пошуку до тієї частини сцени, яка дійсно цікавить алгоритм, – найдешевше покращення, яке конвеєр може зробити для підвищення власної надійності.
Другою перевагою є конвеєр від грубого до точного. Об’єкти результатів виявлення – blob, rect, apriltag тощо – надають свої обмежувальні прямокутники у вигляді тієї самої четвірки (x, y, w, h), яку приймає roi. Таким чином грубий перший етап може повернути обмежувальний прямокутник, він безпосередньо підставляється в roi наступного етапу, і другий етап виконується над вужчою областю. Кожне прогресивне звуження і прискорює наступний етап, і робить його результати надійнішими, оскільки простір пошуку вже відфільтровано.
5.5.2. Двійкові маски¶
Прямокутник є правильною формою, коли область інтересу вирівняна по осях. Коли це не так – криволінійна область, невипукла, пікселі, які попередній етап класифікував як «збіги» – операції потрібно вказати обмежитись довільним шаблоном пікселів. Для цього використовується двійкова маска: окреме Image тих самих розмірів, що й вихідне, яке використовується як перемикач увімкнення/вимкнення для кожного пікселя. Ненульовий піксель у масці означає «включити відповідний вихідний піксель»; нульовий – «залишити вихідний піксель без змін».
Маска зазвичай є зображенням BINARY – однобітовий на піксель формат, створений саме для цієї мети – але підійде будь-яке однокальне зображення, оскільки споживач сприймає будь-яке ненульове значення як «увімкнено».
Методи фільтрації, порогування та арифметики приймають іменований аргумент mask. Форма однакова для кожного: окремо виділене двійкове зображення тих самих розмірів, що й вихідне, передане як аргумент.
ROI та маски поєднуються. Передайте обидва, і операція виконається лише над пікселями, які знаходяться всередині ROI і увімкнені в масці. Два механізми дають коду застосунку незалежні важелі – один для прямокутної області інтересу, один для довільного шаблону всередині неї – не змушуючи жодну форму успадковувати обмеження від іншої.
ROI обмежує операцію прямокутником, вирівняним по осях. Маска додатково звужує її до довільного шаблону пікселів. Вони поєднуються: змінюються лише пікселі, що знаходяться всередині ROI і увімкнені в масці.¶
5.5.3. Побудова масок¶
Три методи Image будують типові геометрії масок на місці, обнуляючи пікселі за межами обраної області:
mask_rectangle()зберігає прямокутник.mask_circle()зберігає коло.mask_ellipse()зберігає еліпс.
Кожен приймає (x, y, w, h) (для прямокутника та еліпса) або (x, y, radius) (для кола). Виклик будь-якого з них без аргументів центрує геометрію та масштабує її, щоб заповнити зображення – ця форма використовується, коли мета – просте повноекранне коло або еліпс, що приховує лише кути.
mask = image.Image(img.width(), img.height(), image.BINARY)
mask.clear() # start from all zeros
mask.mask_ellipse() # centred, full-size oval
Цікаві маски рідко виходять лише з методів mask_*. Вони походять з попередніх етапів конвеєра: прохід порогування виробляє двійкове зображення, ненульові пікселі якого позначають збіги – саме та форма, яку потрібно передати в аргумент mask= наступного етапу. Прохід морфологічного очищення вдосконалює цю маску, не змінюючи її форми. Будь-яке однокальне зображення саме по собі є допустимою маскою.
5.5.4. Як операції змінюють зображення¶
Шаблон, видимий у кожному фрагменті коду на попередніх сторінках – операція повертає той самий img для ланцюжкового виклику – варто явно виділити, щоб не доводилося повторювати це при кожному введенні нового методу. На поверхні Image виділяються три сімейства методів, кожне з яких по-різному обробляє вихідне зображення:
Оперуючі методи змінюють пікселі джерела на місці та повертають те саме зображення для ланцюжкового виклику. Сімейства малювання, арифметики, порогування та фільтрації поводяться саме так.
img.gaussian(1)розмиваєimgі повертає той самийimg; перевизначення –img = img.gaussian(1)– нешкідливе, але зайве.Методи перетворення за замовчуванням також виконують операцію на місці, але приймають
copy=Trueтаcopy_to_fb=Trueдля виділення окремого результуючого зображення, коли джерело потрібно зберегти. Перетворення форматів та геометричні копії є основними членами цього сімейства.Методи інспекції зчитують пікселі та повертають об’єкт результату – список виявлених ознак, гістограму, набір статистичних даних – не змінюючи вихідне зображення.
Ця тричленна класифікація є послідовною на всій поверхні. Знаючи, до якого сімейства належить метод, застосунок розуміє, чого очікувати від виклику: чи збережуться пікселі джерела, чи буде виділено окреме результуюче зображення, і чи є значення, що повертається, самим джерелом або чимось іншим.