5.30. Potrivirea șabloanelor¶
Detectoarele tratate până acum răspund la întrebări despre conținutul unui singur cadru: unde sunt blob-urile, încotro merg liniile, ce spune un cod tipărit. O altă clasă de întrebări compară o imagine cu alta. Această regiune a cadrului capturat seamănă cu peticul de referință pe care l-am stocat la momentul calibrării? Metodele de potrivire răspund la această întrebare.
Analiza tonală și statistică a introdus get_similarity() pentru întrebarea înrudită – cât de asemănătoare sunt, în ansamblu, aceste două imagini de aceeași dimensiune? – cu SSIM ca metrică de bază. Întrebarea de potrivire rămasă este cea de localizare: nu „cât de asemănătoare sunt aceste două imagini”, ci „unde anume, în interiorul acestei imagini mai mari, apare acel petic mai mic?” Instrumentul potrivit pentru întrebarea de localizare este potrivirea șabloanelor.
5.30.1. Apelul de bază¶
find_template() caută primul loc în care o imagine șablon mică apare în interiorul cadrului capturat. Implementarea folosește corelația încrucișată normalizată (NCC): șablonul alunecă peste cadru, scorul de potrivire pentru fiecare poziție este calculat din corelația dintre pixelii șablonului și pixelii subiacenți ai cadrului (normalizată față de mediile și varianțele locale, astfel încât modificările de amplificare (gain) să nu păcălească potrivirea), iar prima poziție al cărei scor depășește threshold este returnată sub forma unei casete de încadrare:
template = image.Image("/sdcard/template.bmp", copy_to_fb=False)
template.to_grayscale()
match = img.find_template(template, threshold=0.7,
search=image.SEARCH_DS)
if match is not None:
img.draw_rectangle(match, color=(255, 0, 0))
Metoda funcționează doar pe imagini în tonuri de gri. Capturați în tonuri de gri (alegerea naturală pentru orice cameră fără senzor de culoare) sau convertiți pe loc prin to_grayscale() înainte de apel. Același lucru este valabil pentru șablonul încărcat de pe disc: un șablon color este convertit cu aceeași metodă, iar rezultatul este ceea ce așteaptă mecanismul de potrivire.
threshold este un număr cu virgulă mobilă de la 0.0 la 1.0. O valoare de 1.0 cere o potrivire perfectă, pixel cu pixel (ceea ce nu se întâmplă niciodată cu imagini capturate reale), 0.0 acceptă orice, iar valorile între 0.6 și 0.8 acoperă cazul obișnuit în care șablonul a fost capturat în condiții de iluminare similare, iar scena nu s-a schimbat dramatic. Creșteți pragul pentru a suprima fals-pozitivele; coborâți-l pentru a accepta potriviri mai zgomotoase, cu prețul unui număr mai mare de potriviri eronate.
5.30.2. Strategia de căutare¶
search alege între două strategii. image.SEARCH_EX este căutarea exhaustivă: șablonul alunecă prin fiecare poziție la pas de step pixeli din cadru și returnează prima potrivire de peste prag. image.SEARCH_DS este căutarea în diamant: mecanismul de potrivire eșantionează mai întâi grosier, apoi rafinează în jurul celui mai bun scor, ceea ce este dramatic mai rapid, dar poate rata o potrivire reală dacă trecerea grosieră s-a nimerit lângă un maxim local care îl depășește pe cel global. Pentru o secvență de procesare în timp real, în care șablonul este bine definit și improbabil de confundat, SEARCH_DS este alegerea implicită potrivită; pentru o calibrare punctuală, în care costul unei ratări este mai mare decât costul unei scanări mai lente, SEARCH_EX este mai sigur.
step controlează saltul de pixeli în timpul trecerii exhaustive (căutarea în diamant își gestionează propriul pas). Valori mai mari ale lui step accelerează scanarea, cu prețul preciziei sub-pixel. roi restrânge căutarea la o regiune a cadrului, atât îngustând ceea ce ia în considerare mecanismul de potrivire, cât și reducând volumul de lucru.
Valoarea returnată este un tuplu casetă de încadrare (x, y, w, h) care identifică cea mai bună potrivire, sau None dacă nicio poziție nu a depășit pragul. Caseta de încadrare se transmite direct către draw_rectangle() sau crop() pentru etapa următoare de procesare.
5.30.3. Capcana scalării și a rotației¶
Capcana clasică a potrivirii șabloanelor este sensibilitatea la scală și la rotație. Mecanismul de potrivire compară șablonul cu cadrul pixel cu pixel; un șablon capturat de la o anumită distanță nu se potrivește cu același obiect capturat de la altă distanță, iar un șablon capturat frontal nu se potrivește cu același obiect privit din lateral. Pragul scade discret sub nivelul de potrivire chiar și atunci când obiectul este evident vizibil pentru ochiul uman, iar metoda returnează None.
Există câteva soluții de ocolire pentru cazurile simple. Aplicația poate captura mai multe șabloane la scale diferite și poate rula find_template() pentru fiecare, în secvență, acceptându-l pe primul care depășește pragul; costul crește odată cu numărul de șabloane. Aplicația poate prelucra în prealabil cadrul cu rotation_corr() sau cu transformarea polară (Transformări geometrice) pentru a elimina rotația problematică înainte de rularea potrivirii; șablonul potrivit trebuie totuși să corespundă geometriei corectate.
O expresie utilă pentru secvențele de inspecție QA împerechează mecanismul de potrivire a șabloanelor cu calculatorul de similaritate introdus de analiza tonală și statistică: find_template() localizează piesa în cadrul capturat, iar caseta de încadrare returnată este decupată și transmisă către get_similarity() în raport cu peticul de referință. Etapa de potrivire a șablonului decide unde se află piesa; etapa de scor de similaritate decide dacă piesa este acceptabilă. Cele două etape rulează la fiecare cadru, pragul aplicat lui mean este poarta de admis/respins, iar caseta de încadrare potrivită, desenată înapoi în cadru, este previzualizarea din IDE pe care operatorul o urmărește.