5.31. Hledání posunu¶
Porovnávání podle šablony odpovídá na otázku kde je tento výřez uvnitř snímku; skórování podobnosti odpovídá na otázku jak moc jsou si tyto dva obrazy celkově podobné. Mezi nimi leží jiná otázka: oba snímky ukazují stejnou scénu, ale kamera (nebo scéna) se mezi nimi pohnula – o kolik? To je problém posunu a modul image jej řeší jedinou metodou fázové korelace.
5.31.1. Posun pomocí fázové korelace¶
find_displacement() odhaduje tuhé zarovnání mezi dvěma stejně velkými obrazy pomocí fázové korelace – frekvenční metody, která na každém obraze spustí rychlou Fourierovu transformaci (FFT), vzájemně koreluje jejich fáze a v výsledku najde vrchol. Poloha vrcholu je posun, který oba obrazy zarovná:
d = img.find_displacement(template)
print("shift:", d.x_translation, d.y_translation,
" response:", d.response)
Vrácený objekt Displacement nese x_translation a y_translation – posun v pixelech v každé ose – plus response, skóre spolehlivosti od 0.0 do 1.0, kde 1.0 je dokonalý vrchol. Odfiltrování detekcí pod response > 0.3 zahodí falešné výsledky, u kterých fázová korelace nikdy nenašla čistý vrchol.
rotation i scale jsou ve výchozím režimu 0.0, resp. 1.0; reálné hodnoty nabývají pouze tehdy, je-li logpolar=True (viz níže).
Tato metoda s sebou nese dvě praktická omezení. Prvním jsou rozměry o mocnině dvou: FFT v jádru fázové korelace je nejrychlejší – a na kameře plně podporovaný pouze – při velikostech jako 32 na 32, 64 na 64 a 128 na 128. Nejčistším nastavením je zachytávat přímo v jedné z těchto velikostí předáním rozlišení metodě framesize() jako n-tice:
csi0.framesize((64, 64))
Aplikace, která potřebuje posun z většího snímku, místo toho vyřízne z oblasti, na které jí záleží, výřez o mocnině dvou a na něm spustí porovnávač.
Druhým jsou vstupy stejné velikosti: roi a template_roi musí vybírat shodné šířky a výšky, jinak porovnávač volání odmítne. Dvě zachycení ze stejné kamery ve stejné konfiguraci to splňují automaticky; zachycený snímek porovnávaný s načtenou referencí potřebuje oba nejprve oříznout na shodné výřezy o mocnině dvou.
5.31.2. Rotace a měřítko pomocí log-polární transformace¶
Výchozí režim hledá pouze posun. Když se dva snímky liší také v rotaci okolo zvoleného středu nebo v měřítku okolo téhož středu, spuštění fázové korelace na log-polární reprojekci každého obrazu změní tyto parametry na posun v log-polárním souřadnicovém systému – který týž porovnávač fázové korelace dokáže obnovit:
d = img.find_displacement(template, logpolar=True)
print("rotation rad:", d.rotation,
" scale:", d.scale,
" response:", d.response)
S logpolar=True metoda spouští stejnou porovnávací pipeline proti log-polárně promítnutým obrazům místo originálů. Pole rotation a scale výsledku se vracejí vyplněná: rotation je úhel v radiánech mezi dvěma snímky, scale je měřítkový faktor mezi nimi. x_translation a y_translation v tomto režimu ztrácejí smysl (posun podél log-polárních os neodpovídá lineárnímu posunu ve zdroji).
Keyword fix_rotation_scale=True pokrývá mezilehlý případ: oba obrazy se liší jak v posunu, tak v rotaci/měřítku a aplikace potřebuje pouze posun po korekci rotace a měřítka. Porovnávač nejprve spustí log-polární průchod, aby obnovil rotaci a měřítko, aplikuje inverzi na jeden z obrazů a poté spustí průchod pro posun, aby obnovil zbývající posun. Tento příznak má smysl pouze tehdy, je-li logpolar=False – žádá porovnávač v režimu posunu, aby nejprve odstranil rotaci/měřítko.
Vzor z polárních transformací – kartézská → polární → porovnání – je tím, co find_displacement() s logpolar=True dělá v jednom volání. Aplikace uloží při spuštění referenční log-polární výřez, zachytí a log-polárně transformuje každý živý snímek a metoda obnoví rozdíl rotace a měřítka mezi nimi. Pro aplikace, které potřebují sledování invariantní vůči rotaci a měřítku – dokovacího robota, jehož kamera se při přibližování k cíli naklání a přibližuje, stabilizovaný gimbal, který potřebuje vědět, jak se obraz otáčí vůči referenci – je toto standardní konstrukce.
5.31.3. Klasické použití¶
Nejběžnějším použitím find_displacement() je odhad pohybu mezi snímky v pipeline, která zpracovává pohybující se kameru. Kamera zachytí malý výřez o mocnině 2 ve snímku N, zachytí stejně velký výřez ve snímku N+1, spustí na obou find_displacement() a odečte posun v pixelech mezi nimi. Posun je odhadovaný pohyb kamery (nebo scény, podle toho, čí vztažná soustava je důležitá) mezi dvěma zachyceními, užitečný pro:
Snímání ve stylu optického toku – vznášející se dron s kamerou mířící dolů používá posun na jednotlivých snímcích k odhadu svého bočního pohybu a jeho zpětnému přivedení do letového řadiče.
Stabilizace obrazu – posun mezi po sobě jdoucími snímky je odečten ze zachyceného obrazu před jeho záznamem nebo přenosem, čímž vzniká plynulejší video proud.
Zarovnání při inspekci – skenovací kamera pohybující se podél dopravníku používá posun na jednotlivých snímcích k registraci každého snímku vůči následujícímu a sestavení sešitého pohledu na celý díl.
Každá z těchto aplikací má stejnou podobu: zachyť, posuň, akumuluj do průběžného odhadu, zachyť znovu.