Bilddaten

3.2.6. Bilddaten#

Digitale Bilder bestehen aus drei Farbwerten (rot, grün, blau) pro Pixel, d.h. Bildelement. Aus diesen drei Werten wird bei der Darstellung die gewünschte Farbe zusammengestellt. Der Wertebereich ist dabei entweder zwischen 0 und 255 (8-bit) oder als Gleitkommazahl zwischen 0 und 1.

import numpy as np
np.set_printoptions(precision=2, linewidth=65)

import matplotlib.pyplot as plt
plt.rc('figure', dpi=150)

Im weiteren wird ein Bild vom Campus Haspel campus_haspel.jpeg zur Demonstration verwendet. Die Bilddaten können mit der plt.imread-Funktion als dreidimensionales Array von 8-bit vorzeichenlosen ganzen Zahlen eingelesen werden.

data = plt.imread('./campus_haspel.jpeg')
print( "Form:", data.shape )
print( "Datentyp der Elemente:", data.dtype)
Form: (3024, 4032, 3)
Datentyp der Elemente: uint8
# Auszug aus den dreidimensionalem Datensatz
print( data )
[[[ 52  42  43]
  [ 46  36  37]
  [ 42  33  34]
  ...
  [ 58  46  32]
  [ 54  37  21]
  [ 50  32  12]]

 [[ 46  37  38]
  [ 43  35  33]
  [ 41  35  35]
  ...
  [ 58  46  34]
  [ 59  43  27]
  [ 51  34  16]]

 [[ 37  33  30]
  [ 38  35  30]
  [ 40  36  33]
  ...
  [ 50  40  28]
  [ 53  39  26]
  [ 55  42  26]]

 ...

 [[125 106  91]
  [122 105  89]
  [121 105  89]
  ...
  [  9  14  10]
  [  5  14   9]
  [  9  20  14]]

 [[129  96  87]
  [123  95  84]
  [112  94  80]
  ...
  [ 12  14  11]
  [  4  14   6]
  [  5  16   8]]

 [[134  95  88]
  [132  99  90]
  [120 101  87]
  ...
  [ 12  14  11]
  [  7  14   7]
  [  4  15   7]]]

Mit der bereits vorgestellten Funktion plt.imshow kann das Bild in Echtfarben dargestellt werden. Dies funktioniert, da die Funktion die einzelnen Ebenen, hier der letzte Index, des Datensatzes als Farbinformationen (rot, grün, blau) interpretiert. Wäre noch eine vierte Ebene dabei, würde sie als individueller Transparenzwert verwendet worden.

plt.imshow( data );
../../../_images/542c957027b339743b2d6703adf5c1efdf88b0a7f2abb348d821481ade26e89d.png

Natürlich können auch die einzelnen Farbebenen individuell betrachtet werden. Dazu wird der letzte Index festgehalten.

titel = ["Rotwerte", "Grünwerte", "Blauwerte"]

for i in range(3):
    # Als Farbskale wird die invertierte '_r' Grauskala 
    # verwendet 'Greys'
    plt.imshow( data[:,:,i], cmap='Greys_r' )
    plt.title(titel[i])
    plt.colorbar()
    plt.show()
../../../_images/fd00b6b3a1a24011461a77c435a80a68fa82f33f1343ad131367a9e247bc5332.png ../../../_images/1864badf6a9ce0875d155457b556ccaf0443cb5121800f2fba4b15b17e36f349.png ../../../_images/28b74bed19853fada1c832e4256e9698b49bd300a8dbf79aea33c2d6e5783c70.png

Da die Bilddaten als Arrays gespeichert sind, sind viele der möglichen Optionen, z.B. zur Teilauswahl oder Operationen, verfügbar. Das untere Beispiel zeigt einen Ausschnitt im Rotkanal des Bildes.

bereich = np.array(data[1320:1620, 400:700, 0], dtype=float)
plt.imshow( bereich, cmap="Greys_r" )
plt.colorbar();
../../../_images/fcd0c5ea59d66ba92cee82639311329cd0ccc1e81453cecffc3b54127498d1c4.png

Als Beispiel für eine Bildoperation wird der Laplace-Operator vorgestellt. Er kann genutzt werden um Ränder von Objekten zu identifizieren. Dazu wird für jeden Bildpunkt \(\sf B_{i,j}\) – außer an den Rändern – folgender Wert \(\sf \phi_{i, j}\) berechnet:

\[ \sf \phi_{i, j} = \left|B_{i-1, j} + B_{i, j-1} - 4\cdot B_{i, j} + B_{i+1, j} + B_{i, j+1}\right| \]

Folgende Funktion implementiert diese Operation. Darüber hinaus werden alle Werte von \(\sf \phi\) unterhalb eines Schwellwerts auf Null und oberhalb auf 255 gesetzt.

def img_lap(data, schwellwert=25):
    
    # Erstellung einer Kopie der Daten, nun jedoch als
    # Array mit Gleitkommazahlen
    bereich = np.array(data, dtype=float)
    
    # Aufteilung der obigen Gleichung in zwei Teile
    lapx = bereich[2:, :] - 2*bereich[1:-1, :] + bereich[:-2, :]
    lapy = bereich[:, 2:] - 2*bereich[:, 1:-1] + bereich[:, :-2]
    
    # Zusammenführung der Teile und Bildung des Betrags
    lap = np.abs(lapx[:,1:-1] + lapy[1:-1, :])
    
    # Schwellwertanalyse
    lap[lap > schwellwert] = 255
    lap[lap < schwellwert] = 0
    
    return lap

Die Anwendung des Laplace-Operators auf den oberen Bildausschnitt ergibt folgende Ausgabe. Hier sind deutlich die Umrisse der Bildstrukturen erkennbar.

lap = img_lap(bereich)
plt.imshow(lap, cmap="Greys")
plt.colorbar();
../../../_images/01488100bb4b188cd95b4438e2a1c8193cbafcd889a391a1c4ae5224c7a1cbd2.png

Zum Vergleich noch beide Abbildungen nebeneinander. Im folgenden wird die Funktion plt.subplot verwendet, welche mehrere Graphiken in einer Abbildung ermöglicht. Beispiele und Dokumentation sind beispielsweise hier zu finden.

ax = plt.subplot(1, 2, 1)
ax.imshow(bereich, cmap="Greys_r")

ax = plt.subplot(1, 2, 2)
ax.imshow(lap, cmap="Greys");
../../../_images/f53363eda334a7d3e42258c1c1f9023357186d4dd63f11193df87834e5d23860.png