5.31. Potrivirea prin deplasare¶
Template matching answers where is this patch inside the frame; similarity scoring answers how alike are these two images overall. A different question sits between them: the two frames show the same scene, but the camera (or the scene) moved between them – by how much? That is the displacement problem, and the image module solves it with a single phase-correlation method.
5.31.1. Deplasare prin corelație de fază¶
find_displacement() estimează alinierea rigidă dintre două imagini de aceeași dimensiune folosind corelația de fază – o metodă din domeniul frecvenței care rulează o transformată Fourier rapidă (FFT) pe fiecare imagine, corelează încrucișat fazele lor și localizează vârful din rezultat. Poziția vârfului este translația care aliniază cele două imagini:
d = img.find_displacement(template)
print("shift:", d.x_translation, d.y_translation,
" response:", d.response)
Obiectul Displacement returnat conține x_translation și y_translation – deplasarea în pixeli pe fiecare axă – plus response, un scor de încredere de la 0.0 la 1.0 unde 1.0 este un vârf perfect. Filtrarea detectărilor sub response > 0.3 elimină rezultatele false în care corelația de fază nu a găsit niciodată un vârf curat.
Atât rotation, cât și scale sunt 0.0 și, respectiv, 1.0 în modul implicit; ele iau valori reale doar când logpolar=True (vezi mai jos).
Metoda are două constrângeri practice. Prima sunt dimensiunile putere a lui doi: FFT-ul din inima corelației de fază este cel mai rapid – și pe cameră, complet suportat doar – la dimensiuni precum 32 pe 32, 64 pe 64 și 128 pe 128. Cea mai curată configurație este să capturați direct la una dintre aceste dimensiuni, transmițând rezoluția către framesize() ca tuplu:
csi0.framesize((64, 64))
O aplicație care are nevoie de deplasare dintr-un cadru mai mare decupează în schimb un petic putere a lui doi din regiunea care o interesează și rulează potrivitorul pe acesta.
A doua sunt intrările de aceeași dimensiune: roi și template_roi trebuie să selecteze lățimi și înălțimi identice, altfel potrivitorul refuză apelul. Două capturi de la aceeași cameră cu aceeași configurație satisfac automat această condiție; un cadru capturat comparat cu o referință încărcată necesită ca ambele să fie mai întâi decupate la petice putere a lui doi care se potrivesc.
5.31.2. Rotație și scară prin log-polar¶
Modul implicit găsește doar translația. Când cele două cadre diferă și prin rotație în jurul unui centru ales sau prin scară în jurul aceluiași centru, rularea corelației de fază pe re-proiecția log-polar a fiecărei imagini transformă acei parametri în translație în sistemul de coordonate log-polar – pe care același potrivitor prin corelație de fază îl poate recupera:
d = img.find_displacement(template, logpolar=True)
print("rotation rad:", d.rotation,
" scale:", d.scale,
" response:", d.response)
Cu logpolar=True, metoda rulează aceeași secvență de potrivire pe imaginile proiectate log-polar în loc de cele originale. Câmpurile rotation și scale ale rezultatului revin completate: rotation este unghiul în radiani dintre cele două cadre, scale este factorul de scară dintre ele. x_translation și y_translation devin lipsite de sens în acest mod (translația de-a lungul axelor log-polar nu corespunde unei translații liniare în sursă).
Cuvântul-cheie fix_rotation_scale=True acoperă cazul intermediar: cele două imagini diferă atât prin translație, cât și prin rotație/scară, iar aplicația are nevoie doar de translație după corectarea rotației și a scării. Potrivitorul rulează mai întâi trecerea log-polar pentru a recupera rotația și scara, aplică inversul uneia dintre imagini, apoi rulează trecerea de translație pentru a recupera deplasarea rămasă. Indicatorul are sens doar când logpolar=False – îi cere potrivitorului în modul translație să elimine mai întâi rotația/scara.
Tiparul din transformările polare – cartezian → polar → potrivire – este ceea ce face find_displacement() cu logpolar=True într-un singur apel. Aplicația stochează un petic log-polar de referință la pornire, capturează și transformă în log-polar fiecare cadru live, iar metoda recuperează diferența de rotație și scară dintre ele. Pentru aplicații care au nevoie de un dispozitiv de urmărire invariant la rotație și scară – un robot de andocare a cărui cameră se înclină și mărește pe măsură ce se apropie de o țintă, un cardan stabilizat care trebuie să știe cum se rotește imaginea față de o referință – aceasta este construcția standard.
5.31.3. Utilizarea clasică¶
Cea mai frecventă utilizare a find_displacement() este estimarea mișcării de la cadru la cadru într-o secvență care procesează o cameră în mișcare. Camera capturează un petic mic putere a lui 2 la cadrul N, capturează peticul de aceeași dimensiune la cadrul N+1, rulează find_displacement() pe cele două și citește deplasarea în pixeli dintre ele. Deplasarea este mișcarea estimată a camerei (sau a scenei, în funcție de al cui cadru de referință contează) între cele două capturi, utilă pentru:
Detectare în stil flux optic – o dronă în zbor staționar cu o cameră îndreptată în jos folosește deplasarea per cadru pentru a-și estima mișcarea laterală și a o transmite înapoi controlerului de zbor.
Stabilizarea imaginii – deplasarea dintre cadrele consecutive este scăzută din imaginea capturată înainte ca aceasta să fie înregistrată sau transmisă, producând un flux video mai fluid.
Alinierea pentru inspecție – o cameră de scanare care se deplasează de-a lungul unui transportor folosește deplasarea per cadru pentru a alinia fiecare cadru cu următorul și a construi o vedere asamblată a întregii piese.
Fiecare dintre aceste aplicații ia aceeași formă: capturare, deplasare, acumulare într-o estimare curentă, capturare din nou.