Matrisefiltre i bildebehandling

Denne posten er del 5 av 7 i serien Bildebehandling med python i vgs

En type filter kan være å for hver piksel beregne en ny pikselverdi basert på verdiene rundt. Om en lar den nye verdien være gjennomsnittet av pikslene rundt, blir bildet mer uskarpt.

uskarp = np.array([[1,1,1],
                   [1,1,1],
                   [1,1,1]])/9 # Alle verdiene blir 1/9

utsnitt = b[60:63, 110:113]   # Utsnittet gir en 3x3-matrise rundt b[61,111],
print(utsnitt)                  # som kan brukes til å beregne den nye verdien i b[61,111]

filtrert = utsnitt*uskarp       # Hvert element blir multiplisert med elementet på samme plass i filteret
print(filtrert) 

np.sum(filtrert) # Summen av alle elementene, som blir den nye verdien
[[ 82 133 166]
 [ 64 190 176]
 [ 35 148 151]]

[[ 9.11111111 14.77777778 18.44444444]
 [ 7.11111111 21.11111111 19.55555556]
 [ 3.88888889 16.44444444 16.77777778]]

 127.22222222222223 

For at en skal kunne beregne verdier også for pikslene langs kanten, lager vi en ramme rundt som kopierer kantverdiene ut. Som for utsnittet over.

utsnittRamme = np.pad(utsnitt, 1, mode="edge")
print(utsnittRamme)

[[ 82  82 133 166 166]
 [ 82  82 133 166 166]
 [ 64  64 190 176 176]
 [ 35  35 148 151 151]
 [ 35  35 148 151 151]]

Prosessen blir gjentatt for alle pikslene i bildet.

def konvolusjon(bilde, matrise):
    x,y = bilde.shape
    ut = np.zeros(bilde.shape)
    bilde = np.pad(bilde, 1, mode="edge")
    for i in range(x):
        for j in range(y):
            ut[i,j] = np.sum(bilde[i:i+3,j:j+3]*matrise)
    return np.abs(ut.astype(int))

print(konvolusjon(øre, uskarp))
visBilde(konvolusjon(øre, uskarp))
[[  9   9  14  26  36  33  21  11   9   9]
 [  9  16  30  46  50  43  27  16   9   9]
 [ 10  33  64  91  80  57  29  17  10   9]
 [ 15  54  99 126  96  63  33  25  14  11]
 [ 20  66 119 144 112  80  65  59  39  19]
 [ 22  66 117 136 111  99 107 109  72  35]
 [ 20  61 107 121  95  97 127 142  95  46]
 [ 19  56  95 123  95 101 116 137  92  47]
 [ 20  45  86 126 116 112 111 121  89  54]
 [ 20  35  79 132 144 132 117 115  92  63]]

def visBildeOgKonvolusjon(bilde, matrise):
    fig = plt.figure(figsize=(12,6))
    a = fig.add_subplot(1, 2, 1)
    imgplot = plt.imshow(bilde, cmap="gray",vmin=0,vmax=255)
    plt.axis("off")
    
    a = fig.add_subplot(1, 2, 2)
    k = konvolusjon(bilde, matrise)
    imgplot = plt.imshow(k, cmap="gray",vmin=0,vmax=255)
    plt.axis("off")

visBildeOgKonvolusjon(b, uskarp)

Ulike filter

Ulike matriser kan gi ulike effekter.

# Forsterker kontraster
skarpere = np.array([[ 0,-1, 0],
                     [-1, 5, -1],
                     [ 0,-1, 0]])

 
# Gir inntrykk av lys fra øvre høyre hjørne
emboss = np.array([[-2,-1, 0],
                   [-1, 1, 1],
                   [ 0, 1, 2]]) 

# Kantgjenkjenning
omriss = np.array([[-1,-1,-1],
                   [-1, 8,-1],
                   [-1,-1,-1]])

visBildeOgKonvolusjon(b,skarpere)

visBildeOgKonvolusjon(b,emboss)

visBildeOgKonvolusjon(b,omriss)

Oppgaveforslag

  • Utvid filterne over til 5×5-matriser, hva blir forskjellen?
  • Lag et filter som erstatter pikselverdien med medianen til pikslene rundt. Sammenlign med gjennomsnitt.
    • Sett så en del tilfeldige piksler til tilfeldige verdier, eller bruk dette bildet. Sammenlign gjennomsnittfilteret med medianen.

Serienavigasjon<< Kantgjenkjenning i bilder med deriverteÅ variere lysstyrken til bilder med numpy >>

Underviser i matematikk, fysikk og naturfag på Tryggheim vgs.