5.13. Filtre liniare și de vecinătate¶
Operațiile de aritmetică pe pixeli din partea anterioară a capitolului combinau două imagini punct cu punct. Filtrele îndeplinesc o sarcină înrudită într-un mod diferit: ele calculează valoarea fiecărui pixel de ieșire pornind de la o mică vecinătate de pixeli de intrare din jurul poziției corespunzătoare. Ieșirea la (x, y) este o anumită statistică – media, mediana, valoarea cea mai frecventă – a pixelilor de intrare dintr-o mică casetă centrată pe (x, y).
Această mică schimbare de perspectivă – trecerea de la un pixel pe rând la o fereastră de pixeli pe rând – este cea care face să funcționeze o întreagă familie de operații utile. O simplă mediere pe o fereastră mică netezește zgomotul senzorului. Mediana pe aceeași fereastră elimină punctele izolate de un singur pixel fără a estompa muchiile la fel de mult. O mediere bilaterală refuză să netezească peste limitele de contrast puternic, păstrând muchiile obiectelor și curățând în același timp texturile din interiorul lor. Vecinătatea este unitatea de lucru; alegerea statisticii decide ce face filtrul.
5.13.1. Dimensiunea nucleului¶
Fiecare filtru de vecinătate primește un parametru size care stabilește raza ferestrei în pixeli. Fereastra în sine este pătrată și acoperă (2 * size + 1) pixeli pe fiecare latură – deci size=1 înseamnă o vecinătate de 3 pe 3, size=2 înseamnă 5 pe 5, size=3 înseamnă 7 pe 7 și așa mai departe.
Vecinătatea alunecă peste imagine câte un pixel pe rând, de la stânga sus la dreapta jos. Fiecare pixel de ieșire este rezultatul aplicării statisticii filtrului pe vecinătatea de intrare centrată pe el.¶
Dimensiunile mai mari înseamnă vecinătăți mai mari, ceea ce înseamnă o filtrare mai netedă (sau mai agresivă). Costul crește odată cu aria ferestrei, astfel încât un filtru size=3 efectuează de aproximativ nouă ori mai mult lucru per pixel decât un filtru size=1. Valoarea implicită practică pentru majoritatea operațiilor de curățare este size=1 sau size=2; recurgeți la dimensiuni mai mari doar când vecinătățile mici nu sunt suficiente pentru a suprima caracteristica pe care aplicația încearcă să o suprime.
5.13.2. Filtrul de medie¶
mean() înlocuiește fiecare pixel cu media aritmetică a vecinătății sale. Rezultatul netezește variația de la pixel la pixel pe dimensiunea ferestrei, ceea ce îl face cea mai ieftină modalitate de a suprima punctele de zgomot ale senzorului: variația de frecvență înaltă se mediază, iar conținutul de frecvență joasă supraviețuiește.
Compromisul este că și muchiile și alte caracteristici accentuate sunt mediate. O muchie luminoasă care avea lățimea de un pixel înainte de filtru are doi sau trei pixeli lățime după un filtru de medie size=1, cu luminozitatea diminuată la margini. Pentru reducerea pură a zgomotului pe o imagine săracă în textură (un perete curat, interiorul unui marker colorat), compromisul este acceptabil. Pentru o scenă aglomerată în care muchiile contează, unul dintre filtrele următoare este de obicei o alegere mai potrivită.
img.mean(1) # 3x3 box average -- fast, gentle smoothing
img.mean(2) # 5x5 box average -- stronger, slower
5.13.3. Mediană, mod, punct median¶
Celelalte trei filtre statistice de vecinătate înlocuiesc simpla medie aritmetică cu ceva mai robust față de valorile aberante.
median() returnează mediana vecinătății – valoarea care ajunge la mijlocul listei sortate de pixeli din fereastră. Un singur pixel foarte luminos sau foarte întunecat din fereastră nu trage mediana; el devine doar una dintre extremele eliminate. Efectul practic este că filtrarea cu mediană elimină punctele izolate de un singur pixel și zgomotul de tip sare-și-piper fără a estompa muchiile așa cum o face mean. Costul este un calcul mai mare per pixel – sortarea unei ferestre este mai lentă decât medierea ei – iar rezultatul nu este strict o medie, ceea ce contează uneori pentru calculele din aval.
Un parametru percentile (implicit 0.5) mută valoarea aleasă în afara medianei stricte. percentile=0.0 returnează minimul vecinătății, percentile=1.0 maximul; valorile intermediare aleg proporțional între ele în fereastra sortată. Aceasta îi conferă lui median capacitatea de a accentua părțile întunecate sau luminoase ale vecinătății fără a pierde robustețea față de valorile aberante a statisticii de ordine.
mode() returnează valoarea cea mai frecventă din vecinătate. Utilă când modelul de zgomot este „majoritatea pixelilor sunt corecți, câțiva au fost corupți în grade diferite”, unde răspunsul corect este oricare valoare care apare cel mai des – pe care mediana o poate rata atunci când valorile corupte se aglomerează pe o singură parte a ferestrei sortate.
midpoint() returnează o combinație ponderată a minimului și maximului vecinătății – bias=0.5 dă punctul median dintre ele, bias=0.0 dă minimul, bias=1.0 dă maximul. Mai rar folosit decât celelalte, dar merită cunoscut atunci când scopul este în mod specific extragerea caracteristicilor întunecate sau luminoase.
5.13.4. Bilateral, versiunea care păstrează muchiile¶
bilateral() este filtrul de vecinătate pe care merită cel mai mult să-l înțelegeți bine. El produce efectul de netezire al lui mean(), dar cu o constrângere suplimentară: cu cât un pixel din vecinătate diferă mai mult de pixelul central, cu atât contează mai puțin în medie. Rezultatul netezește interiorul fiecărei regiuni uniforme fără a se revărsa peste muchiile care le separă, ceea ce este exact ceea ce își doresc de fapt majoritatea aplicațiilor.
Doi parametri controlează cât de agresiv depreciază filtrul pixelii:
color_sigmadecide cum afectează ponderarea diferența de culoare. Valorile mai mici înseamnă că filtrul este mai strict în deprecierea pixelilor care diferă de centru.space_sigmadecide cum afectează ponderarea distanța spațială. Valorile mai mici acordă mai multă pondere pixelilor apropiați de centru.
Valorile implicite (color_sigma=0.1, space_sigma=1.0) sunt puncte de plecare rezonabile; ajustarea lor este de obicei o chestiune de rulare a filtrului pe un cadru de probă și de reglare până când muchiile sunt clare, iar interioarele sunt curate.
Bilateral este mai costisitor decât median() și semnificativ mai costisitor decât mean(), așa că merită să recurgeți la el doar atunci când comportamentul de păstrare a muchiilor este ceea ce are nevoie aplicația.
5.13.5. Pragul adaptiv¶
Filtrele de medie, mediană, mod și punct median poartă toate aceeași pereche de argumente cu cuvinte-cheie care transformă ieșirea lor într-un prag binar:
threshold=Truecomută filtrul în modul de prag.offset=Ndeplasează pragul local cuNunități înainte de comparație.
Mecanismul se bazează direct pe comportamentul obișnuit al filtrului. Fără threshold=True, filtrul își calculează statistica pe vecinătate și scrie acea statistică în pixelul de ieșire. Cu threshold=True, filtrul calculează aceeași statistică, apoi compară pixelul sursă de la aceeași poziție cu statistica plus decalajul și scrie valoarea maximă a formatului dacă sursa este mai mare, altfel zero.
Rezultatul este o imagine binară al cărei prag se deplasează odată cu luminozitatea locală de-a lungul cadrului. Regiunile luminoase primesc un prag ridicat, regiunile întunecate primesc un prag scăzut, iar un pixel de prim-plan care este local mai luminos decât vecinii săi se potrivește indiferent dacă se află într-o regiune luminoasă sau una întunecată – ceea ce este exact comportamentul pe care un singur prag global nu l-ar putea produce pe o imagine iluminată neuniform.
img.mean(3, threshold=True, offset=5)
Parametrul offset este locul în care aplicația controlează cât de strict este testul. Un mic decalaj pozitiv cere ca pixelul sursă să fie măsurabil mai luminos decât vecinii săi înainte de a fi considerat o potrivire, ceea ce suprimă rezultatele fals pozitive cauzate de zgomotul senzorului, cu prețul renunțării la prim-planul slab. Un mic decalaj negativ surprinde prim-planul slab, cu prețul de a lăsa să treacă o parte din zgomot. Alegerea depinde de ceea ce va face restul fluxului de prelucrare cu ieșirea binară.
Sub o iluminare neuniformă, un singur prag global nu poate descrie prim-planul la fiecare poziție. Un filtru de vecinătate rulat cu threshold=True produce un prag care se deplasează odată cu luminozitatea locală și clasifică prim-planul corect pe întregul cadru.¶
Familia de filtre rulează pragul adaptiv, așa că alegerea filtrului potrivit contează: mean() pentru cel mai ieftin prag adaptiv, median() atunci când intrarea are zgomot de tip sare-și-piper pe care filtrul ar trebui să-l respingă înainte de a calcula pragul local.