Bildverarbeitung

Einführung

Charlie Chaplin, changed with Python, Numpy and Matplotlib

Heutzutage ist es so einfach wie nie Fotos zu machen. Um Fotos zu erstellen und anzuschauen ist im wesentlichen nur ein Smartphone nötig. Wenn wir die Kosten für das Smartphone nicht berücksichtigen, so ist das Fotografieren kostenlos. In der vorigen Generation brauchten Hobby- und Hauptberufliche Künstler spezielle und teure Ausrüstung gebraucht und die Kosten für ein Foto waren weit entfernt von kostenlos.

Wir machen Bilder um großartige Momente der Zeit zu bewahren. Bewahrte Erinnerungen sind bereit in der Zukunft wieder "geöffnet" zu werden.

Ähnlich wie man Dinge einmacht, müssen wir darauf achten die richtigen Vorbereitungen zu treffen. Natürlich bieten Smartphones eine ganze Reihe von Bildverarbeitungs-Software. Sobald wir aber eine große Menge an Fotos bearbeiten müssen, werden andere Tools benötigt. An dieser Stelle kommt Python ins Spiel. Python und dessen Module wie Numpy, Scipy, Matplotlib und weitere spezielle Module stellen optimale Funktionalitäten bereit um mit einer Flut von Bilder umzugehen.

Dieses Kapitel befasst sich mit Grundladen der Bildverarbeitung und -manipulation. Dies wird für notwendiges Wissen für dieses Kapitel. Wir verwenden hier die Module NumPy, Matplotlib und SciPy.

Wir beginnen mit dem SciPy-Packet misc. Die Hilfe-Datei sagt, dass scypi.misc "verschiedene Werkzeuge ohne anderes zu Hause" beinhaltet.

# the following line is only necessary in Python notebook:
%matplotlib inline
from scipy import misc
import matplotlib.pyplot as plt
lena = misc.lena()
plt.gray()
plt.imshow(lena)
plt.show()

Zusätzlich zum Bild erkennen wir, dass die Ticks an den Achsen ebenfalls ausgegeben werden. Das ist sicherlich interessant, wenn Sie Informationen zur Größe und Pixel-Position benötigen, jedoch möchte man in den meisten Fällen das Bild ohne diese Informationen sehen. Indem wir den Befehl plt.axis("off") hinzufügen, können wir die Ticks und Achsen ausblenden:

from scipy import misc
import matplotlib.pyplot as plt
lena = misc.lena()
plt.axis("off") # removes the axis and the ticks
plt.gray()
plt.imshow(lena)
plt.show()

Wir sehen, dass der Typ des Bildes ein Integer-Array ist:

lena.dtype
Der obige Code führt zu folgendem Ergebnis:
dtype('int64')

Wir können auch die Größe des Bildes prüfen:

lena.shape
Der obige Code liefert folgendes Ergebnis:
(512, 512)

Das misc-Packet beinhaltet auch ein Bild eines Waschbären:

import scipy.misc
face = scipy.misc.face()
print(face.shape)
print(face.max)
print(face.dtype)
plt.axis("off")
plt.gray()
plt.imshow(face)
plt.show()
(768, 1024, 3)
<built-in method max of numpy.ndarray object at 0x7451ff0>
uint8
import matplotlib.pyplot as plt
import matplotlib.image as mpimg

Matplotlib unterstützt nur PNG-Bilder.

img=mpimg.imread('frankfurt.png')
print(img[:3])
[[[ 0.41176471  0.56862748  0.80000001]
  [ 0.40392157  0.56078434  0.79215688]
  [ 0.40392157  0.56862748  0.79607844]
  ..., 
  [ 0.48235294  0.62352943  0.81960785]
  [ 0.47843137  0.627451    0.81960785]
  [ 0.47843137  0.62352943  0.82745099]]
 [[ 0.40784314  0.56470591  0.79607844]
  [ 0.40392157  0.56078434  0.79215688]
  [ 0.40392157  0.56862748  0.79607844]
  ..., 
  [ 0.48235294  0.62352943  0.81960785]
  [ 0.47843137  0.627451    0.81960785]
  [ 0.48235294  0.627451    0.83137256]]
 [[ 0.40392157  0.56862748  0.79607844]
  [ 0.40392157  0.56862748  0.79607844]
  [ 0.40392157  0.56862748  0.79607844]
  ..., 
  [ 0.48235294  0.62352943  0.81960785]
  [ 0.48235294  0.62352943  0.81960785]
  [ 0.48627451  0.627451    0.83137256]]]
plt.axis("off")
imgplot = plt.imshow(img)
lum_img = img[:,:,1]
print(lum_img)
[[ 0.56862748  0.56078434  0.56862748 ...,  0.62352943  0.627451
   0.62352943]
 [ 0.56470591  0.56078434  0.56862748 ...,  0.62352943  0.627451    0.627451  ]
 [ 0.56862748  0.56862748  0.56862748 ...,  0.62352943  0.62352943
   0.627451  ]
 ..., 
 [ 0.31764707  0.32941177  0.32941177 ...,  0.30588236  0.3137255
   0.31764707]
 [ 0.31764707  0.3137255   0.32941177 ...,  0.3019608   0.32156864
   0.33725491]
 [ 0.31764707  0.3019608   0.33333334 ...,  0.30588236  0.32156864
   0.33333334]]
plt.axis("off")
imgplot = plt.imshow(lum_img)



Färbung, Schatten und Farbton

Jetzt möchten wir auf die Tönung eines Bildes eingehen. Tönung ist ein Ausdruck aus der Farb-Theorie ist eine oft von Malern verwendete Technik. Es ist kaum vorstellbar, wenn man an Maler denkt, gleichzeitig nicht an die Niederlande zu denken. Wir verwenden ein Bild mit "Holländischen Windmühlen" in unserem nächsten Beispiel. (Das Bild wurde in Kinderdijk aufgenommen, ein Dorf in den Niederlanden über 15km östlich von Rotterdam und über 50km entfernt von Den Haag. Es ist ein UNESCO Weltkulturerbe seit 1997.)

windmills = mpimg.imread('windmills.png')
plt.axis("off")
plt.imshow(windmills)
plt.imshow(windmills)
Der obige Python-Code liefert folgendes Ergebnis:
<matplotlib.image.AxesImage at 0x7f916e577908>

Wir möchten nun das Bild tönen. Das bedeutet wir "mischen" unsere Farben mit weiss. Dies wird die Helligkeit des Bildes erhöhen. Wir schreiben dafür eine Python-Funktion, welche ein Bild und eine Prozent-Angabe als Parameter entgegen nimmt. "percentage" auf 0 zu setzen, wird das Bild nicht verändern. Wenn Sie es auf eins setzen, wird das Bild vollständig aufgehellt:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
def tint(imag, percent):
    """
    imag: the image which will be shaded
    percent: a value between 0 (image will remain unchanged
             and 1 (image will completely white)
    """
    tinted_imag = imag + (np.ones(imag.shape) - imag) * percent
    return tinted_imag
windmills = mpimg.imread('windmills.png')
tinted_windmills = tint(windmills, 0.8)
plt.axis("off")
plt.imshow(tinted_windmills)
plt.imshow(tinted_windmills)
Wir können die folgenden Ergebnisse erwarten, wenn wir den obigen Python-Code ausführen:
<matplotlib.image.AxesImage at 0x7f916e8f5c50>

Ein Schatten ist eine Mischung einer Farbe mit Schwarz, was die Helligkeit verringert.

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
def shade(imag, percent):
    """
    imag: the image which will be shaded
    percent: a value between 0 (image will remain unchanged
             and 1 (image will be blackened)
    """
    tinted_imag = imag * (1 - percent)
    return tinted_imag
windmills = mpimg.imread('windmills.png')
tinted_windmills = shade(windmills, 0.7)
plt.imshow(tinted_windmills)
Der obige Python-Code liefert Folgendes:
<matplotlib.image.AxesImage at 0x7f916e59c3c8>
def vertical_gradient_line(image, reverse=False):
    """
    We create a horizontal gradient line with the shape (1, image.shape[1], 3))
    The values are incremented from 0 to 1, if reverse is False,
    otherwise the values are decremented from 1 to 0.
    """
    number_of_columns = image.shape[1]
    if reverse:
        C = np.linspace(1, 0, number_of_columns)
    else:
        C = np.linspace(0, 1, number_of_columns)
    C = np.dstack((C, C, C))
    return C
horizontal_brush = vertical_gradient_line(windmills)
tinted_windmills =  windmills * horizontal_brush
plt.axis("off")
plt.imshow(tinted_windmills)
Der obige Code führt zu folgendem Ergebnis:
<matplotlib.image.AxesImage at 0x7f916c2c6908>