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()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-4-6ffbddb15a25> in <module>
      5 import matplotlib.pyplot as plt
      6 
----> 7 lena = misc.lena()
      8 plt.gray()
      9 plt.imshow(lena)
AttributeError: module 'scipy.misc' has no attribute 'lena'

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:

In [ ]:
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:

In [ ]:
lena.dtype

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

In [ ]:
lena.shape

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

In [ ]:
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()
In [ ]:
import matplotlib.pyplot as plt
import matplotlib.image as mpimg

Matplotlib unterstützt nur PNG-Bilder.

In [ ]:
img=mpimg.imread('frankfurt.png')
In [ ]:
print(img[:3])
In [ ]:
plt.axis("off")
imgplot = plt.imshow(img)
lum_img = img[:,:,1]
print(lum_img)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-5-1ad0aaad3bed> in <module>
----> 1 lum_img = img[:,:,1]
      2 print(lum_img)
NameError: name 'img' is not defined
In [ ]:
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.)

In [ ]:
windmills = mpimg.imread('windmills.png')
plt.axis("off")
plt.imshow(windmills)
plt.imshow(windmills)

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:

In [ ]:
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)

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

In [ ]:
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)
In [ ]:
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)

Wir werden das Bild von rechts nach links tönen indem wir den "reverse" Parameter der Python-Funktion auf "True" setzen:

In [ ]:
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, reverse=True)
tinted_windmills =  windmills * horizontal_brush
plt.axis("off")
plt.imshow(tinted_windmills)
In [ ]:
def horizontal_gradient_line(image, reverse=False):
    """
    We create a vertical gradient line with the shape (image.shape[0], 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_rows, number_of_columns = image.shape[:2]
    C = np.linspace(1, 0, number_of_rows)
    C = C[np.newaxis,:]
    C = np.concatenate((C, C, C)).transpose()
    C = C[:, np.newaxis]
    return C
vertical_brush = horizontal_gradient_line(windmills)
tinted_windmills =  C * windmills 
plt.imshow(tinted_windmills)
plt.imshow(tinted_windmills)

Ein Farbton wird entweder durch die Mischung einer Farbe mit Grau produziert, oder durch gleichzeitige Tönung und Schattierung.

In [ ]:
charlie = mpimg.imread('Chaplin.png')
plt.gray()
print(charlie)
plt.imshow(charlie)
In [ ]:
colored = np.dstack((charlie*0.1, charlie*1, charlie*0.5))
plt.imshow(colored)
Graustufenbilder: http://scikit-image.org/docs/dev/auto_examples/plot_tinting_grayscale_images.html In [ ]:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
charlie = mpimg.imread('Chaplin.png')
#  colormaps plt.cm.datad
cmaps = set(plt.cm.datad.keys())
X = [  (4,3,1, (1, 0, 0)), (4,3,2, (0.5, 0.5, 0)), (4,3,3, (0, 1, 0)), 
       (4,3,4, (0, 0.5, 0.5)),  (4,3,(5,8), (0, 0, 1)), (4,3,6, (1, 1, 0)), 
       (4,3,7, (0.5, 1, 0) ),               (4,3,9, (0, 0.5, 0.5)),
       (4,3,10, (0, 0.5, 1)), (4,3,11, (0, 1, 1)),    (4,3,12, (0.5, 1, 1))]
fig = plt.figure(figsize=(6, 5))
#fig.subplots_adjust(bottom=0, left=0, top = 0.975, right=1)
for nrows, ncols, plot_number, factor in X:
    sub = fig.add_subplot(nrows, ncols, plot_number)
    sub.set_xticks([])
    plt.colors()
    
    sub.imshow(charlie*0.0002, cmap=cmaps.pop())
    sub.set_yticks([])
#fig.show()