5.20. Регресія та схожість¶
Ще два вимірювання класу Image підсумовують зображення як щось інше, ніж розподіл значень пікселів. Лінійна регресія порогових пікселів дає застосунку пряму, на яку він може реагувати – класичний вхідний сигнал для робота, що слідує по лінії. Вимірювання схожості дає застосунку єдине число, що описує, наскільки схожі два зображення – природний вхід для регресійного тесту еталонного зображення або детектора грубих змін.
5.20.1. Лінійна регресія¶
Коли пікселі переднього плану зображення утворюють пряму через кадр – стрічка на трасі, за якою слідує робот, лінія горизонту, край дороги або коридору – застосунку зазвичай не потрібен кожен окремий піксель переднього плану. Йому потрібна пряма найкращого наближення через них усі, параметризована так, щоб можна було визначити орієнтацію прямої та місце її перетину з кадром.
get_regression() виконує це наближення. Він приймає той самий формат кортежу порогів, що використовують binary() та find_blobs(), ідентифікує кожен піксель, що відповідає порогу, та повертає єдиний результат line, що описує пряму найкращого наближення через ці пікселі:
line = img.get_regression([(0, 60)])
if line:
img.draw_line((line.x1(), line.y1(),
line.x2(), line.y2()),
color=(255, 0, 0))
Наближення виконується методом лінійної регресії Тейла-Сена – надійним методом, що краще tolerates викиди, ніж більш знайоме наближення методом найменших квадратів. Невелика кількість пікселів далеко від справжньої прямої не спотворює результат так, як це було б при найменших квадратах, що відповідає реальності шумного виходу порогової обробки.
Результат line містить кінцеві точки, обрізані до прямокутника зображення (x1, y1, x2, y2), довжину та магнітуду прямої (length, magnitude), а також геометричний опис прямої у полярній формі (theta, rho) – кут нахилу прямої від горизонталі та її перпендикулярну відстань від початку координат. Полярна форма – це те, що зазвичай потрібно контурному циклу: theta говорить роботу, в який бік нахилена пряма, rho – де пряма перетинає зображення, а зворотний зв’язок по обох параметрах тримає робота по центру лінії.
Кілька ключових аргументів налаштовують надійність та вартість. x_stride та y_stride пропускають пікселі під час наближення – більші кроки роблять регресію дешевшою коштом використання меншої кількості пікселів. area_threshold та pixels_threshold відхиляють прямі, за якими стоїть недостатня кількість відповідних пікселів. target_size масштабує вхід до меншого розміру перед наближенням – регресія виконується швидше на сурогаті зображення розміром 80×60 без великих втрат точності напрямку прямої.
Якщо прийнятну пряму не вдалося побудувати – якщо поріг не знайшов жодного пікселя або знайшов шаблон, що не схожий на пряму – метод повертає None. Реальний код слідування по лінії перевіряє кожен виклик get_regression() на None перед зверненням до атрибутів прямої.
5.20.2. Схожість зображень¶
Інший вид вимірювання: замість питання «що містить зображення?», поставити питання «наскільки схожі ці два зображення?». Операція, до якої слід вдатися, – get_similarity(), яка обчислює Індекс структурної схожості (SSIM) між вихідним зображенням та опорним зображенням.
s = img.get_similarity(reference)
print(s.mean, s.stdev)
SSIM – стандартна метрика схожості зображень, що використовується у всій обробці зображень, оскільки вона поводиться так, як людська інтуїція щодо схожості – невеликий зсув або невелика зміна яскравості лише трохи знижує оцінку, тоді як велика структурна зміна (відсутній об’єкт, інша сцена) знижує її різко. Оцінка варіюється від -1 до +1: +1 означає, що два зображення ідентичні, 0 – що вони не пов’язані, а -1 – що вони структурно протилежні. Повернутий об’єкт similarity надає середнє значення SSIM по всьому зображенню, а також стандартне відхилення, мінімум та максимум оцінок по плиткам.
Для порівнянь, де менше число краще, ніж більше – регресійний тест, що має показувати нуль при «нічого не змінилося» і зростати в міру накопичення змін – прапорець dssim=True повертає структурну несхожість: середнє значення SSIM, віднімане від 1, тому значення, що повертається, є 0.0 для ідентичних зображень і зростає в міру їх відмінності.
5.20.3. Випадки використання SSIM¶
Два поширені застосування:
Регресійне тестування за еталонним зображенням. Тестовий фреймворк захоплює опорний кадр за відомих правильних умов і зберігає його як еталонне зображення. Наступні тестові запуски захоплюють за тих самих умов і порівнюють з еталонним зображенням за допомогою SSIM. Оцінка вище певного порогу (0.95 або 0.98 залежно від допуску) є прохідною; нижче – ні. Тестовий фреймворк не повинен знати що змінилося – оцінка SSIM є сигналом.
Виявлення грубих змін. Застосунок, якому потрібна більш груба версія різниці кадрів – та, що ігнорує невеликі зміни яскравості, але реагує на великі структурні зміни – може використовувати SSIM по відношенню до опорного кадру замість порепіксельного difference() із наступним порогом. SSIM менш чутливий до дрейфу освітлення, ніж порепіксельна різниця, що робить його кращим вибором, коли мета – виявити «сцена виглядає суттєво інакше», а не «змінився будь-який окремий піксель».
Обидва застосування використовують той самий виклик – img.get_similarity(reference) – і спрацьовують на порозі поверненої оцінки. Різниця лише в тому, чи поріг є високим (регресійний тест, пошук майже ідентичного збігу) або низьким (виявлення змін, пошук будь-якої великої структурної зміни).
5.20.4. Форма перетворення з порівнянням¶
Корисна тонкість: get_similarity() приймає ті самі параметри x, y, x_scale, y_scale, roi, rgb_channel, alpha, color_palette, alpha_palette, hint та transform, що й draw_image(). Опорне зображення позиціонується, масштабується та трансформується цими параметрами перед запуском порівняння SSIM.
Це означає, що застосунок може запитати «наскільки схожа ця сцена на опорний кадр після відомого зміщення / обертання / масштабування» без підготовки попередньо трансформованого опорного зображення. Це дешевий спосіб побудувати трекер, який шукає простір параметрів і повідомляє, яке перетворення опорного зображення найкраще відповідає поточному кадру.