Skip navigation

Másodrendű derivált közelítése

Laplace operátor

A Laplace operátor definíciója másodrendű deriváltakat felhasználva, folytonos f függvényre:

Laplace(f) = \frac{\partial^{2}f}{\partial x^{2}}+\frac{\partial^{2}f}{\partial y^{2}}

Jellemzői

  • Az intenzitásértékek változásának változását mutatja. Élek ott lehetnek, ahol a második derivált értéke nulla és a környezetében előjelet vált.
  • Homályosabb élek esetén pontosabb eredményt adhat, mint az első derivált.
  • Csak az él helyét adja, az irányát nem.
  • Viszont minden irányban egyformán érzékeny, nem szükséges külön X, Y kernel.
  • Rendkívül zajérzékeny, előzetes simítás erősen javasolt!

Konvolúciós maszk példák

Diszkrét digitális raszterkép esetén közelíteni tudjuk, például az alábbi konvolúciós maszkok egyikével:

h_1 = \left[ \begin{matrix} 0 & 1 & 0 \\ 1 & -4 & 1 \\ 0 & 1 & 0 \end{matrix} \right]

h_2 = \left[ \begin{matrix} 1 & 1 & 1 \\ 1 & -8 & 1 \\ 1 & 1 & 1 \end{matrix} \right]

Zaj csökkentése

A gradiens operátorok nagyon érzékenyek a zajra. Előzetesen használjunk pl. Gauss simítást! A simító és a gradiens operátor összevonható egy közös konvolúciós maszkba az alábbi módon.

\frac{d}{dx}\left(f*g\right) = f*\frac{d}{dx}g

Vagyis elegendő a simító maszk deriváltját kiszámítani előzetesen.

Marr-Hildreth operátor

Második derivált számítása Gauss-simított képen, közös konvolúciós kernellel.

Jellemzői

A két műveletet összevonhatjuk egy közös konvolúciós maszkba: a LoG (Laplacian of Gaussian) kernel alkalmazásával dolgozhatunk, ami konvolúció a Gauss szűrő második deriváltjával.

LoG kernel függvény (1D változata, valamint 9x9 diszkrét egész közelítés 1.4 szigma értékkel):

0 1 1 2 2 2 1 1 0
1 2 4 5 5 5 4 2 1
1 4 5 3 0 3 5 4 1
2 5 3 -12 -24 -12 3 5 2
2 5 0 -24 -40 -24 0 5 2
2 5 3 -12 -24 -12 3 5 2
1 4 5 3 0 3 5 4 1
1 2 4 5 5 5 4 2 1
0 1 1 2 2 2 1 1 0

OpenCV függvények

Konvolúció használatával

  • Mint az elsőrendű derivált esetén, manuálisan megadott vagy számított kernellel.

Laplace függvény hívásával

dst = cv2.Laplacian(src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]])

A paraméterek hasonlóak a Sobel függvényéhez.

  • ksize pozitív, páratlan szám kell legyen.
  • ksize == 1 esetben a h1 maszkkal (lásd fentebb) történik a konvolúció. Egyébként a Sobel operátor segítségével közelít parciális deriváltakat.

Figyeljünk arra, hogy a Laplace függvény nem végez simítást a képen, azt előzetesen tegyük meg!

Laplace operátor használata élkereséshez

Figyelnünk kell arra, hogy él ott lehet, ahol (elvileg) a Laplace érték nulla, és a szomszédsághoz képest előjelváltás történik! Erre sajnos nincs kész függvény az OpenCV-ben. A képek digitális volta miatt eleve nem biztos, hogy pontosan nulla értéket fogunk kapni az élek helyén, így vizsgáljuk inkább csak az előjelváltásokat a vizsgált pont lokális környezetében!

Az angol nyelvű OpenCV dokumentáció példaprogramja látszólag megoldja a feladatot, de vigyázzunk, mert nem végez előjelváltás keresést, csak a Laplace eredmény abszolútértékét képzi, ami elrontja az élkeresési lehetőségét! Az élek a sötét területen vannak, a világosan megjelenő területek mellett! Ez hibás!

A nulla-átmenet előjelváltással problémakör részletes ismertetése angol nyelven itt olvasható: https://homepages.inf.ed.ac.uk/rbf/HIPR2/zeros.htm.

Egy egyszerűsített közelítő megoldás megvalósítható min-max szűrők (morfológiai erózió és dilatáció) segítségével. Hajtsunk végre a Laplace eredményen egy minimum és egy maximum szűrést.

img = cv2.imread('OpenCV-logo.png', cv2.IMREAD_GRAYSCALE)
blurred = cv2.GaussianBlur(img, (5, 5), 2.0)
LoG = cv2.Laplacian(blurred, cv2.CV_16S, ksize=3)
minLoG = cv2.morphologyEx(LoG, cv2.MORPH_ERODE, np.ones((3, 3)))
maxLoG = cv2.morphologyEx(LoG, cv2.MORPH_DILATE, np.ones((3, 3)))

Azokon a helyeken legyen élpont, ahol a lokális környezet minimuma negatív, a maximuma pedig pozitív érték. Vegyük figyelembe, hogy a nulla értéktől csak kis mértékben való eltérés zaj hatására is kialakulhat, ezért élt ott detektáljunk, ahol a nullától eltérés egy megadott érték feletti (a példánkban -10 és 10 értékeket használunk).

zero_cross = np.logical_and(minLoG < -10, maxLoG > 10)
zero_cross_im = np.zeros(zero_cross.shape, np.uint8)
zero_cross_im[zero_cross] = 255
cv2.imshow('zero_cross_im', zero_cross_im)

A megoldást megvalósító példaprogramunk a 07_03_Laplace_zero_crossing.py.

Feladat

Egészítsük ki a programunkat úgy, hogy ne csak "élpont vagy sem" logikai döntést hozzunk, hanem annak erősségét is próbáljuk megállapítani. Például ha az előző pontban megadott kritérium teljesül, akkor vegyük a maximum és a minimum érték különbségét! Ne felejtsük, ha erősséget is rendelünk az élpontokhoz, akkor utána küszöböléssel szabályozhatjuk, milyen erősségűeket szeretnénk megtartani.

Laplace élerősség-kép a GolyoAlszik_rs.jpg képre:

Eredmények összehasonlítása

Az OpenCV dokumentáció példaprogramja és a min-max szűrős nulla átmenet közelítés eredményét az OpenCV-logo.png képen hasonlítjuk össze.

Jól látható, hogy az első esetben az eredmény párhuzamosan futó, dupla élekből áll. A második eredmény egyszeres élt ad.

Az alsó sorban a zöld színű valódi kontúr és a vörös színű Laplace eredmény egymásra vetítését látjuk. Az első esetben a vörös vonalak körülveszik a zöld kontúrt. A második esetben nagy mértékű az átfedés, amit a zöld és vörös színek elegyéből előálló sárga szín jelez.

OpenCV dokumentáció példaprogramja Nulla átmenet közelítése