5.31. Визначення зміщення¶
Пошук шаблону відповідає на питання де в кадрі знаходиться цей фрагмент; оцінка подібності відповідає на питання наскільки схожі ці два зображення загалом. Між ними є інше питання: два кадри показують одну і ту саму сцену, але між ними камера (або сцена) перемістилась – на скільки? Це проблема зміщення, і модуль image вирішує її єдиним методом фазової кореляції.
5.31.1. Зміщення методом фазової кореляції¶
find_displacement() оцінює жорстке вирівнювання між двома зображеннями однакового розміру за допомогою фазової кореляції – метод у частотній області, що виконує швидке перетворення Фур’є (FFT) для кожного зображення, крос-корелює їхні фази та визначає пік у результаті. Положення піку – це зсув, що вирівнює два зображення:
d = img.find_displacement(template)
print("shift:", d.x_translation, d.y_translation,
" response:", d.response)
Повернутий об’єкт Displacement містить x_translation та y_translation – зсув пікселів по кожній осі – а також response, коефіцієнт впевненості від 0.0 до 1.0, де 1.0 відповідає ідеальному піку. Фільтрація виявлень нижче response > 0.3 відкидає хибні результати, в яких фазова кореляція так і не знайшла чіткого піку.
У режимі за замовчуванням rotation та scale дорівнюють відповідно 0.0 і 1.0; вони набувають реальних значень лише при logpolar=True (див. нижче).
Метод має два практичні обмеження. Перше – розміри, що є ступенями двійки: FFT, що лежить в основі фазової кореляції, є найшвидшим – і на камері повністю підтримується – для розмірів 32×32, 64×64 та 128×128. Найчистіше налаштування – захоплювати безпосередньо при одному з таких розмірів, передавши роздільну здатність до framesize() як кортеж:
csi0.framesize((64, 64))
Застосунок, якому потрібне зміщення з більшого кадру, натомість вирізає фрагмент із розміром, що є ступенем двійки, з цікавої для нього ділянки та запускає відповідний алгоритм на ньому.
Друге обмеження – однаковий розмір вхідних даних: roi та template_roi повинні вибирати однакові ширину та висоту, інакше метод відхилить виклик. Два знімки з однієї камери при однаковій конфігурації автоматично задовольняють цю умову; захоплений кадр, що порівнюється із завантаженим еталоном, вимагає попереднього обрізання обох до відповідних фрагментів зі розмірами, що є ступенями двійки.
5.31.2. Обертання та масштаб через логарифмічно-полярне перетворення¶
Режим за замовчуванням знаходить лише трансляцію. Коли два кадри також відрізняються обертанням навколо обраного центру або масштабом відносно того самого центру, запуск фазової кореляції на логарифмічно-полярному перепроеціюванні кожного зображення перетворює ці параметри на трансляцію в системі логарифмічно-полярних координат – яку той самий алгоритм фазової кореляції може відновити:
d = img.find_displacement(template, logpolar=True)
print("rotation rad:", d.rotation,
" scale:", d.scale,
" response:", d.response)
При logpolar=True метод запускає той самий конвеєр зіставлення для логарифмічно-полярно-проеційованих зображень замість оригіналів. Поля rotation та scale результату повертаються заповненими: rotation – кут у радіанах між двома кадрами, scale – коефіцієнт масштабу між ними. x_translation та y_translation у цьому режимі не мають змісту (трансляція вздовж логарифмічно-полярних осей не відповідає лінійній трансляції у джерелі).
Ключове слово fix_rotation_scale=True охоплює проміжний випадок: два зображення відрізняються як трансляцією, так і обертанням/масштабом, а застосунку потрібна лише трансляція після корекції обертання та масштабу. Алгоритм спочатку виконує логарифмічно-полярний прохід для відновлення обертання та масштабу, застосовує зворотну операцію до одного з зображень, а потім виконує прохід трансляції для відновлення залишкового зсуву. Прапорець має значення лише при logpolar=False – він просить алгоритм у режимі трансляції спочатку усунути обертання/масштаб.
Патерн із полярних перетворень – декартові → полярні → зіставлення – це те, що find_displacement() з logpolar=True робить за один виклик. Застосунок зберігає еталонний логарифмічно-полярний фрагмент при запуску, захоплює та логарифмічно-полярно перетворює кожен живий кадр, і метод відновлює різницю в обертанні та масштабі між ними. Для застосунків, що потребують трекера, інваріантного до обертання та масштабу – стикувальний робот, камера якого нахиляється та наближається в міру наближення до цілі, стабілізований стабілізатор, якому потрібно знати, як зображення обертається відносно еталону – це стандартна конструкція.
5.31.3. Класичне використання¶
Найпоширеніше використання find_displacement() – покадрова оцінка руху у конвеєрі, що обробляє рухому камеру. Камера захоплює невеликий фрагмент розміром зі ступенем двійки на кадрі N, захоплює фрагмент того самого розміру на кадрі N+1, запускає find_displacement() на обох і зчитує зсув пікселів між ними. Зсув – це оцінена рухомість камери (або сцени, залежно від того, чия система відліку важлива) між двома знімками, корисна для:
Вимірювання на кшталт оптичного потоку – дрон-зависач з направленою донизу камерою використовує попередньо обчислене зміщення для оцінки бічного руху та зворотного зв’язку з контролером польоту.
Стабілізація зображення – зміщення між послідовними кадрами віднімається із захопленого зображення перед його записом або передачею, що дає більш плавний відеопотік.
Вирівнювання при інспекції – сканувальна камера, що рухається вздовж конвеєра, використовує покадрове зміщення для реєстрації кожного кадру відносно наступного та побудови зшитого виду всього об’єкта.
Кожен з цих застосунків має однакову форму: захопити, визначити зміщення, накопичити в поточній оцінці, захопити знову.