5.30. Mallmatchning¶
Detektorerna som hittills har behandlats besvarar frågor om innehållet i en enskild bildruta: var blobbarna finns, vart linjerna går, vad en tryckt kod säger. En annan klass av frågor jämför en bild mot en annan. Ser detta område av den infångade bildrutan ut som den referensbit jag lagrade vid kalibreringstillfället? Matchningsmetoderna besvarar den frågan.
Tonal och statistisk analys introducerade get_similarity() för den närliggande frågan – hur lika är dessa två bilder med samma storlek överlag? – med SSIM som underliggande mått. Den återstående matchningsfrågan är den om lokalisering: inte ”hur lika är dessa två bilder” utan ”var inuti denna större bild dyker den mindre biten upp?” Rätt verktyg för lokaliseringsfrågan är mallmatchning.
5.30.1. Det grundläggande anropet¶
find_template() letar efter den första plats där en liten mall-bild förekommer inuti den infångade bildrutan. Implementeringen använder normaliserad korskorrelation (NCC): mallen glider över bildrutan, matchningspoängen för varje position beräknas utifrån korrelationen mellan mallens pixlar och de underliggande pixlarna i bildrutan (normaliserad mot de lokala medelvärdena och varianserna så att förändringar i förstärkning inte lurar matchningen), och den första position vars poäng klarar threshold returneras som en begränsningsruta:
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))
Metoden fungerar endast på gråskalebilder. Fånga in i gråskala (det naturliga valet för alla kameror utan färgsensor), eller konvertera på plats via to_grayscale() före anropet. Detsamma gäller mallen som laddas från disk: en färgmall konverteras med samma metod, resultatet är vad matcharen förväntar sig.
threshold är ett flyttal från 0.0 till 1.0. Ett värde på 1.0 kräver en perfekt pixel-för-pixel-matchning (vilket aldrig inträffar med verkliga infångade bilder), 0.0 accepterar vad som helst, och värden mellan 0.6 och 0.8 täcker det vanliga fallet där mallen fångades in under liknande belysning och scenen inte har ändrats dramatiskt. Höj tröskelvärdet för att undertrycka falska positiva träffar; sänk det för att acceptera brusigare matchningar till priset av fler felaktiga träffar.
5.30.2. Sökstrategi¶
search väljer mellan två strategier. image.SEARCH_EX är den uttömmande sökningen: mallen glider genom varje position med step pixlars avstånd i bildrutan och returnerar den första träffen över tröskelvärdet. image.SEARCH_DS är diamantsökningen: matcharen samplar grovt först och förfinar sedan kring den bästa poängen, vilket är dramatiskt snabbare men kan missa en verklig matchning om den grova genomgången råkade hamna nära ett lokalt maximum som överträffar det globala. För en realtidspipeline där mallen är väldefinierad och osannolikt förväxlas är SEARCH_DS rätt standardval; för en engångskalibrering där kostnaden för en miss är högre än kostnaden för en långsammare avsökning är SEARCH_EX säkrare.
step styr pixelhoppet under den uttömmande genomgången (diamantsökningen sköter sitt eget steg). Större step-värden snabbar upp avsökningen till priset av subpixelnoggrannhet. roi begränsar sökningen till ett område av bildrutan, vilket både inskränker vad matcharen tar hänsyn till och minskar arbetet.
Det returnerade värdet är en (x, y, w, h)-begränsningsruta-tupel som identifierar den bästa matchningen, eller None om ingen position klarade tröskelvärdet. Begränsningsrutan passar direkt in i draw_rectangle() eller crop() för nästa bearbetningssteg.
5.30.3. Skalnings- och rotationsfällan¶
Den klassiska fallgropen med mallmatchning är känslighet för skala och rotation. Matcharen jämför mallen mot bildrutan pixel-för-pixel; en mall som fångades in på ett avstånd matchar inte samma objekt infångat på ett annat avstånd, och en mall som fångades in rakt framifrån matchar inte samma objekt sett snett från sidan. Tröskelvärdet faller tyst under matchningsnivån även när objektet är tydligt synligt för ett mänskligt öga, och metoden returnerar None.
Det finns några sätt att kringgå detta för de enkla fallen. Applikationen kan fånga in flera mallar i olika skalor och köra find_template() för var och en i tur och ordning och acceptera den första som klarar tröskelvärdet; kostnaden skalar med antalet mallar. Applikationen kan förbehandla bildrutan med rotation_corr() eller den polära transformen (Geometriska transformer) för att ta bort den störande rotationen innan matchningen körs; den matchade mallen måste fortfarande matcha den korrigerade geometrin.
Ett användbart idiom för QA-inspektionspipelines parar mallmatcharen med likhetspoängsättaren som Tonal och statistisk analys introducerade: find_template() lokaliserar delen i den infångade bildrutan och den returnerade begränsningsrutan beskärs ut och skickas till get_similarity() mot referensbiten. Mallmatchningssteget avgör var delen är; likhetspoängsteget avgör huruvida delen är godtagbar. De två stegen körs varje bildruta, tröskelvärdet på mean är godkänd/underkänd-grinden, och den matchade begränsningsrutan som ritas tillbaka in i bildrutan är förhandsgranskningen i IDE:n som operatören tittar på.