Bildverarbeitung durch Matrix Basics & Contents-Reinventor der Python-Bildverarbeitung-

Eine Geschichte über die Bildverarbeitung nur durch Matrixberechnung, ohne sich auf die Bildverarbeitungsbibliothek zu verlassen. Auch mit Pythonista möglich

Zwischenausgaben ZeichnungGraustufen ・ [Faltungsfilterung](http: // qiita.com/secang0/items/f3a3ff629988dc660d87) ・ Affin-Konvertierung

Vorwort

Was ist ein "Neuerfinder"?

Anstatt mich auf Open CV oder Pillow zu verlassen, werde ich tatsächlich verschiedene Bildverarbeitungen mit numpy und matplotlib schreiben. Diese Kombination kann auch mit der iOS-App Pythonista verwendet werden.

Ausführungsumgebung

Verwenden Sie zusätzlich zu den Standardbibliotheken numpy und matplotlib. Ich benutze keine Pandas oder Scipy. Diese Kombination scheint eine Grammatik zu sein, die für Matlab-Benutzer einfach zu verwenden ist.

Python 3 unter Windows 10.5.2|Anaconda 4.2.0 numpy 1.12.1|matplotlib 2.0.0 Numpy 1.8.0 | matplotlib 1.4.0 in Pythonista3 Ich habe die Operation mit bestätigt.

import numpy as np
import matplotlib.pyplot as plt

Vorausgesetztes Wissen

Es setzt Kenntnisse in Python 3 und Kenntnisse in Numpy und Matplotlib voraus. (Der Rest ist mit Numpy verbunden, z. B. Kenntnis der Matrizen)

Grundlagen

Laden / Anzeigen / Speichern von Bildern

Verwenden Sie matplotlib.pyplot, um Bilder zu laden, anzuzeigen und zu speichern. Außerdem wird das gelesene Bild in numpy.ndarray gespeichert. Diesmal lesen und schreiben wir labyrinth.jpeg im selben Verzeichnis.

labyrinth.jpeg

#Bilder laden
#Dreidimensionales np in img.Das Array von Array wird gespeichert.
img = plt.imread('labyrinth.jpeg') 
type(img) #=> numpy.ndarray
img.size #=> (1367, 1345, 3)


#Bildschirm
plt.imshow(img) 
plt.show() #Wenn das verwendete Bild klein ist, sieht es verschwommen aus, aber machen Sie sich jetzt keine Sorgen

#Bild speichern
plt.imsave('labyrinth-1.jpeg', img) #Erweiterung.Selbst wenn Sie es in png ändern, wird es ordnungsgemäß gespeichert.

labyrinth_show.png

Bitte beachten Sie, dass die horizontale Skala zum Zeitpunkt der Lagerung nicht verfügbar ist.

Es ist keine Übertreibung zu sagen, dass wir jetzt über Eingabe-, Ausgabe- und Debugging-Mittel verfügen.

Selbstgemachte Pixel

Einige Benutzer möchten möglicherweise ein Bild erstellen, indem Sie die Pixel selbst angeben. In einem solchen Fall können Sie die Pixel mit einem 2D- oder 3D-np.array angeben, aber hier ist ein kleiner Trick, deshalb werde ich ihn vorstellen.

Schwarzweißbild (zweidimensionales Array von (Höhe = 3) * (Breite = 3))

img_gray = np.array([
                    [0,63,127],
                    [63,127,0],
                    [255,0,127]
], dtype = np.uint8)

#Bildschirm
plt.imshow(img_gray, cmap = 'gray', vmin = 0, vmax = 255, interpolation = 'none')
plt.show()

img_gray_show.png

Zunächst ein Schwarzweißbild. Es gibt ungefähr vier Orte, die ich nicht verstehe.

  1. dtype = np.uint8
  2. cmap = 'gray'
  3. vmin = 0, vmax = 255
  4. interpolation = 'none'

Ist.

Lassen Sie uns jeden erklären. (1 und 3 werden zusammen erklärt)

dtype = np.uint8, vmin = 0, vmax = 255 Wenn Sie einen Farbwähler verwendet haben, werden Sie feststellen, dass Farben häufig zwischen 0 und 255 dargestellt werden. Dieser Trick ist jedoch erforderlich, um dies plt zu vermitteln.

Die dtype-Spezifikation ist diesmal eigentlich nicht erforderlich. Dies ist eher eine nützliche Bezeichnung für Farbe, aber es scheint sich zu lohnen. Für Schwarzweißbilder müssen vmin und vmax angegeben werden. Wenn dies weggelassen wird, wird es ohne Erlaubnis von imshow () normalisiert.

cmap = 'gray' Angesichts der Tatsache, dass cmap für Farbkarte steht und Grau Grau bedeutet, ist dies ziemlich vorhersehbar. Mit anderen Worten, es ist eine Spezifikation, eindimensionale Daten als schwarz-grau-weiß zu interpretieren. Wenn Sie dies versuchen und in in this ändern, ändert sich die Interpretation und auch die Farbe. (Die Verwendung von YlOrBr_r ist beispielsweise wie Sepia.) Erstellen Sie Ihre eigene cmap Es ist auch möglich.

interpolation = 'none' Dadurch wird der Filter entfernt, der selbst angewendet wird. (Eher Anti-Aliasing) Ich weiß nicht, warum es von Anfang an angewendet wird, aber es ist zumindest ärgerlich, sicherzustellen, dass jedes Pixel die gewünschte Farbe hat, also werde ich es entfernen. Vielleicht hängt das von der Version ab.

RGB-Bild ((Höhe = 3) * (Breite = 3) * (RGB) dreidimensionales Array)

img_rgb = np.array([
                    [[255,0,0],[0,255,0],[0,0,255]],
                    [[255,255,0],[0,255,255],[255,0,255]],
                    [[0,0,0],[127,127,127],[255,255,255]],
], dtype = np.uint8)

#Bildschirm
plt.imshow(img_rgb, cmap = 'gray', vmin = 0, vmax = 255, interpolation = 'none')
# => plt.imshow(img_rgb, interpolation = 'none')Gleich wie

plt.show()

img_rgb_show.png

Der Code ist fast der gleiche wie zuvor. (Auch wenn Sie cmap, vmax, vmin angeben, wird dies ignoriert.)

RGBA-Bild ((Höhe = 3) * (Breite = 3) * (RGBA) dreidimensionales Array)

img_rgba = np.array([
                    [[255,0,0,0],[0,255,0,0],[0,0,255,0]],
                    [[255,0,0,127],[0,255,0,127],[0,0,255,127]],
                    [[255,0,0,255],[0,255,0,255],[0,0,255,255]],
], dtype = np.uint8)

#Bildschirm
plt.imshow(img_rgba, cmap = 'gray', vmin = 0, vmax = 255, interpolation = 'none')
# => plt.imshow(img_rgba, interpolation = 'none')Gleich wie

plt.show()

img_rgba_show.png

Ebenso ist der Code fast der gleiche wie zuvor.

Zur Erinnerung: A in RGBA ist ein Alpha-A, das Transparenz darstellt. Es ist schwer zu sagen, ob dies transparent ist, selbst wenn Sie das Bild oben betrachten, aber wenn Sie Gimp usw. betrachten, können Sie sehen, dass es transparent ist.

img_rgba_ss.png (Bild überlagert das Schachbrettmuster)

Erstellen Sie vorerst eine Funktion, die diese zusammenfasst.

def img_show(img : np.ndarray, cmap = 'gray', vmin = 0, vmax = 255, interpolation = 'none') -> None:
    '''np.Zeigen Sie ein Bild mit Array als Argument an.'''
    
    #Setzen Sie dtype auf uint8
    #Überlauf- und Unterlaufbehandlung
    
    img = np.clip(img,vmin,vmax).astype(np.uint8)
    
    #Bild anzeigen
    plt.imshow(img, cmap = cmap, vmin = vmin, vmax = vmax, interpolation = interpolation)
    plt.show()
    plt.close()

Jetzt können Sie Ihr eigenes Punktbild erstellen.

Erweiterung (einfache Erweiterung)

Die hier behandelte Erweiterung ist ein ganzzahliges Vielfaches und eine Erweiterung ohne Interpolation. Verwenden Sie wiederholen.

#5 in vertikaler Richtung und 3 mal in horizontaler Richtung
#Bilder laden
img = plt.imread('labyrinth.jpeg')

#Bild vergrößern
img_expand = img.repeat(5, axis = 0).repeat(3, axis = 1)

img_show(img_expand)

img_expand.png Auf den ersten Blick schrumpft es in horizontaler Richtung, aber wenn Sie sich die Skala ansehen, wird es vergrößert. (Sie können mit img_expand.size überprüfen)

Dies ist eine Erweiterung, die nur selten verwendet wird. Die tatsächlich verwendete Erweiterung wird später beschrieben. (Pläne)

Bilder anordnen

Versuchen Sie, dieselben Bilder horizontal oder vertikal anzuordnen. Verketten ist bequem.

img = plt.imread('labyrinth.jpeg')

img_verticle = np.concatenate((img, img), axis = 0) #Vertikal
img_horizontal = np.concatenate((img,)*3, axis = 1) #Seite

#Bildschirm
img_show(img_verticle)
img_show(img_horizontal)

labyrinth_verticle_show.png labyrinth_horizontal_show.png

Im horizontalen Bild wird die Anzahl der Wiederholungen durch Multiplizieren des Tapples angegeben.

Auf Quadrat zugeschnitten (3/30 hinzugefügt)

Das Trimmen kann einfach durch Indexoperation erfolgen.

img = plt.imread('labyrinth.jpeg')

#1000 vertikal:1500, 0 daneben:500 ausschneiden
img_show(img[1000:1500,0:500])

img_trim.png

RGB-Zerlegung

def decomposition(img : np.ndarray, channel : list = [1.,1.,1.]) -> np.ndarray:
    '''Betonen Sie für jeden Kanal die Intensität, die dem Kanal zugewiesen wurde'''
    
    float_img = img * channel
    return np.array(float_img,dtype = np.uint8)

img = plt.imread('labyrinth.jpeg')
img_show(decomposition(img, [1.,0.,0.]), cmap = 'Reds')
img_show(decomposition(img, [0.,1.,0.]), cmap = 'Greens')
img_show(decomposition(img, [0.,0.,1.]), cmap = 'Blues')

labyrinth_red.png labyrinth_green.png labyrinth_blue.png Der obige Code definiert eine Funktion namens Zerlegung (Kanalzerlegung scheint auf Englisch als Farbzerlegung bezeichnet zu werden). Dies funktioniert im Grunde genommen als "img * [0,0,1]", aber da der Typ etwas kompliziert ist, habe ich eine Funktion definiert.

Ich habe es für alle Fälle mit Gimp überprüft, aber es sah genauso aus.

Graustufen

labyrinth_mid_v.png

Das Konvertieren eines Pixels mit einem dreidimensionalen Wert von RGB in ein Pixel mit nur einem eindimensionalen Wert von Y wird als Grauskalierung bezeichnet. Kurz gesagt, es ist eine Methode zum Erstellen eines Schwarzweißbildes. Es gibt verschiedene Graustufenmethoden, aber hier beschäftigen wir uns nur mit der Zwischenwertmethode und der G-Kanal-Methode.

Zwischenwertmethode

Die Zwischenwertmethode verwendet den Durchschnitt aus dem Maximalwert in RGB und dem Minimalwert in RGB als Y. Mit anderen Worten wird eine Berechnung wie "(max (R, G, B) + min (R, G, B)) / 2" durchgeführt.

img = plt.imread('labyrinth.jpeg')

img_mid_v = np.max(img, axis = 2)/2 +np.min(img, axis = 2)/2
img_show(img_mid_v)

labyrinth_mid_v.png

Hier ein Punkt. Über die Berechnungsformel von img_mid_v Sie fragen sich vielleicht, ob "img_mid_v = (np.max (img, Achse = 2) + np.min (img, Achse = 2)) / 2" nicht gut ist. Die Antwort ist nein." Der Grund dafür ist, dass uint8 überläuft, wenn Sie zuerst die Maximal- und Minimalwerte hinzufügen. Nachdem der Typ float geworden ist, kehrt er mit img_show zu uint8 zurück.

Übrigens ändert sich "np.max (img, Achse = 2) // 2 + np.min (img, Achse = 2) // 2" nicht viel, aber die Minimal- und Maximalwerte werden abgeschnitten. Ich möchte vorsichtig sein.

G-Kanal

Es scheint, dass Menschen G unter RGB am stärksten erkennen. Die G-Kanal-Methode hat dies berücksichtigt. Bei der G-Kanal-Methode wird der Wert von G als der Wert von Y angesehen. Kurz gesagt, es ist eine sehr grobe Methode, aber sie ist so effektiv, dass Menschen seltsam sind. (Es ist noch seltsamer, dass sich in R und G auf der Netzhaut so viele Pyramidenzellen befinden sollten)

Der Code ist einfach. ... heißt Ellipse Dies ist ein praktisches Symbol.

img = plt.imread('labyrinth.jpeg')
img_g_channel = img[...,1]
img_show(img_g_channel)

labyrinth_g_channel.png

Die Idee ist dieselbe wie bei der vorherigen RGB-Zerlegung. Es ist jedoch bedauerlich, dass es nicht lange dauern wird, bis diese einfache Methode angewendet wird.

Andere Methoden werden in Zukunft behandelt.

Binarisierung

Nachdem wir nun ein Schwarzweißbild haben, versuchen wir es mit der Binärisierung, wobei der Wert von Y "1 für Pixel über dem Schwellenwert und 0 für Pixel unter dem Schwellenwert" ist. Verwenden Sie für Schwarzweißbilder das mit der G-Kanal-Methode erstellte.

img = plt.imread('labyrinth.jpeg')
img_g_channel = img[...,1]

#Schwellenwert einstellen
threshold = 75

img_binary = img_g_channel >= threshold
img_binary = np.uint8(img_binary * 255)
img_show(img_binary)

labyrinth_binary.png

Irgendwie habe ich das Gefühl, dass das Labyrinth auftaucht.

Klappfilter

Am Ende der Grundlagen werde ich vorstellen, wie man einen Filter durch Falten macht. Räumliche Filterung ist für den Filter durch Faltung leicht zu verstehen.

Der diesmal verwendete Filter verwendet die folgenden zwei Matrixfaltungen.

\frac{1}{256}\left(
\begin{matrix}
21 & 31 & 21 \\
31 & 48 & 31 \\
21 & 31 & 21 
\end{matrix}
\right)

Dies ist ein Unschärfefilter, der oft als Gaußsche Unschärfe bezeichnet wird. Dies ist ein Filter, der häufig zur Rauschunterdrückung vor der Konturextraktion verwendet wird.

\left(
\begin{matrix}
0 & -1 & 0 \\
-1 & 4 & -1 \\
0 & -1 & 0 
\end{matrix}
\right)

Dies ist ein Laplace-Filter und wird häufig zur Konturextraktion verwendet. Kann eine Person, die den Ausdruck, dass die Idee mit der bipolaren Zelle in der Mitte identisch ist, leicht verstehen kann, diesen Punkt erreicht haben?

Erstellen Sie zunächst eine Funktion zum Falten eines zweidimensionalen Arrays (Sie müssen es nicht selbst mit scipy oder PIL erstellen, aber leider müssen Sie es selbst unter den Bindungsbedingungen von Numpy und matplotlib erstellen.

def convolve2d(img, kernel):
    #Berechnen Sie die Größe der Submatrix
    sub_shape = tuple(np.subtract(img.shape, kernel.shape) + 1)
    
    #Da der Funktionsname lang ist, wird er einmal weggelassen
    strd = np.lib.stride_tricks.as_strided
    
    #Erstellen Sie eine Submatrix-Matrix
    submatrices = strd(img,kernel.shape + sub_shape,img.strides * 2)
    
    #Berechnen Sie die Einstein-Summe aus Submatrix und Kernel
    convolved_matrix = np.einsum('ij,ijkl->kl', kernel, submatrices)
 
    return convolved_matrix

Der obige Code wird unter Verwendung der Matrix der Submatrix von img gefaltet. Weitere Informationen finden Sie unter stackoverflow-Lehrer.

#Erstellen eines Filterkerns
gaussian = np.array([[21,31,21],
                     [31, 48,31],
                     [21,31,21]])/256
laplacian = np.array([[ 0,-1, 0],
                      [-1, 4,-1],
                      [ 0,-1, 0]]) 

#Bilder laden
img = plt.imread('labyrinth.jpeg')
img = img[...,1] #Dieses Mal wird nur der G-Kanal als Ziel ausgewählt.

#Wenden Sie die Gaußsche Unschärfe 20 Mal an
for _ in range(20):
    img = convolve2d(img, gaussian)

labyrinth_gaussian.png

An diesem Punkt mag es wie eine abgeschnittene Änderung erscheinen, aber wenn Sie es in bmp speichern und vergrößern, werden Sie feststellen, dass es überraschend anders ist. gaussian_compare.png

#Wenden Sie den Laplace-Filter an
img = convolve2d(img, laplacian)
plt.imshow(b,cmap = 'gray_r', vmax = img.max()*0.5) 
#Der Maximalwert beträgt nicht immer 255.
#Auch wenn auf den Maximalwert eingestellt, wurden andere Werte zerkleinert, so*0.Korrigiert um 5.

plt.show()
plt.close()

labyrinth_laplacian.png

Es fehlt ein wenig an Wirkung, also lassen Sie uns die Grundlagen zusammenfassen.

img = np.array([
                [[  0,  0,  0],[  0, 63,127],[255,  0,  0]],
                [[ 63, 63, 63],[  0,  0,255],[  0,  0,  0]],
                [[255,255,255],[  0,  0,  0],[ 63,127,  0]]
], dtype = np.uint8)


img = img.repeat(100,axis = 1).repeat(100,axis = 0)#Erweiterung
img = np.concatenate((img,)*2, axis = 1) #Horizontal kopieren
img = np.concatenate((img,)*2, axis = 0) #Vertikal kopieren
print('RGB-Bild')
img_show(img)


#Generieren Sie ein Schwarzweißbild mit der Zwischenwertmethode
img = np.array(np.max(img, axis = 2)/2 +np.min(img, axis = 2)/2, dtype = np.uint8)
print('Schwarzweiss-Bild')
img_show(img)

#Gaußsche Unschärfe
img = convolve2d(img, gaussian)

#Konturextraktion
img = convolve2d(img, laplacian)

print('Konturextraktion')
plt.imshow(img,cmap = 'gray_r', vmax = img.max())
plt.show()
plt.close()

RGB-Bild sumup_1.png Schwarzweiss-Bild sumup_2.png Konturextraktion sumup_3.png

In der Basisausgabe haben wir auch die G-Kanal-Methode und die Binarisierung gesehen.

Mittlere

** * Wir werden es nach und nach hinzufügen. Wenn Sie interessiert sind, halten Sie es bitte auf Lager. ** ** ** Es ist schon zu lang, also habe ich es nur skizziert und aufgelistet. Für weitere Informationen folgen Sie bitte dem Link. Außerdem ändern sich die verwendeten Bilder gegenüber der Zwischenausgabe. Warum habe ich ein Bild ohne Rot verwendet ...

Zeichnung von Zahlen (hinzugefügt an 3/30 Tagen)

Um eine Figur zu zeichnen, verwenden Sie msgid, um die Koordinaten auf dem Bild zu erhalten.

x, y = np.mgrid[:100,:100]

Beachten Sie, dass die positive Richtung von $ x $ nach unten und die positive Richtung von $ y $ richtig ist.

** Für diejenigen, die mehr erfahren möchten **

Graustufen (hinzugefügt am 30.03.)

Die Grauskalierung ist eine Methode zur Berechnung des Schwarz-Weiß-Werts Y aus den jedem Pixel zugewiesenen RGB-Werten. Hier Verschiedene Graustufenmethoden, die in [Basic] nicht behandelt wurden (http://qiita.com/secang0/items/1229212a37d8c9922901) ) Probiere auch. Eine ausführliche Erklärung finden Sie unter dem Link. Sie werden in derselben Reihenfolge behandelt.

** Für diejenigen, die mehr erfahren möchten **

Faltungsfilterung (hinzugefügt 4/1)

Behandelt Tiefpassfilter, Hochpassfilter und Differenzfilter.

** Für diejenigen, die mehr erfahren möchten **

Affin-Konvertierung (hinzugefügt 4/5 Tage)

Es gibt viele Möglichkeiten, ein Bild zu verzerren. Die Affintransformation ist eine Transformation, die lineare Transformation (Vergrößerung / Verkleinerung / Drehung / Scherung) und parallele Bewegung kombiniert. ** Für diejenigen, die mehr erfahren möchten **

Recommended Posts

Bildverarbeitung durch Matrix Basics & Contents-Reinventor der Python-Bildverarbeitung-
Grundlagen der binärisierten Bildverarbeitung durch Python
Graustufen durch Matrix-Reinventor der Python-Bildverarbeitung-
Faltungsfilterung durch Matrix-Reinventor der Python-Bildverarbeitung-
Bildverarbeitung mit Python (Pillow)
Affin-Konvertierung durch Matrix (Vergrößerung / Verkleinerung / Drehung / Scherung / Bewegung) - Erfinder der Python-Bildverarbeitung -
Python: Grundlagen der Bilderkennung mit CNN
Python-Bildverarbeitung
Bildverarbeitung durch Python 100 Knock # 1 Kanalersatz
[Lernnotiz] Grundlagen des Unterrichts mit Python
Lineares Zeichnen mit einer Matrix-Originalforschung von einem Neuerfinder der Python-Bildverarbeitung-
Python-Grundlagen ①
Grundlagen von Python ①
Bildverarbeitung mit Python 100 Knock # 6 Farbreduktionsverarbeitung
Zeichnen mit Matrix-Reinventor von Python Image Processing-
Analyse des Röntgenmikrotomographiebildes durch Python
Bildverarbeitung? Die Geschichte, Python für zu starten
Bildverarbeitung mit Python 100 Knock # 11 Glättungsfilter (Durchschnittsfilter)
Kommunikationsverarbeitung durch Python
Grundlagen der Python-Scraping-Grundlagen
Erste Python-Bildverarbeitung
Bildverarbeitung mit Python
# 4 [Python] Grundlagen der Funktionen
Grundlagen von Python: Ausgabe
Verschiedene Verarbeitung von Python
[Sprachverarbeitung 100 Schläge 2020] Zusammenfassung der Antwortbeispiele von Python
Extrahieren Sie die Tabelle der Bilddateien mit OneDrive & Python
Bildverarbeitung mit Python (Teil 2)
Python: Grundlagen der Verwendung von Scikit-Learn ①
Bildverarbeitung mit Python (Teil 1)
Bildverarbeitung mit Python (3)
Nachbearbeitung von Python (NG)
Bildverarbeitungssammlung in Python
Python x GIS-Grundlagen (1)
[Python] Bildverarbeitung mit Scicit-Image
[Für Anfänger] Grundlagen von Python erklärt durch Java Gold Teil 2
[Für Anfänger] Grundlagen von Python erklärt durch Java Gold Teil 1
Visualisierung der von numpy erstellten Matrix
Python x GIS-Grundlagen (3)
Grundlagen der Echtzeit-Bildverarbeitung mit opencv
Fehler geteilt durch 0 Verarbeitung von ZeroDivisionError 2
Bilderfassung von Firefox mit Python
Erweiterung des Python-Wörterbuchs um Argumente
[Python] [Inhaltsverzeichnis Links] Python-Programmierung
Erste Schritte mit Python Grundlagen von Python
Persönliche Notizen für die Python-Bildverarbeitung
Die Bildverarbeitung mit Python 100 klopft an die Binärisierung Nr. 3
Überprüfung der Grundlagen von Python (FizzBuzz)
Grundlagen von Python x GIS (Teil 2)
Bildverarbeitung mit Python 100 Knock # 4 Otsu-Binarisierung (Diskriminierungsanalyse-Methode)
Verhalten von Python3 durch Sakuras Server
100 Bildverarbeitung mit Python Knock # 2 Graustufen
Erste Schritte mit Python3
100 Sprachverarbeitung Knock Kapitel 1 von Python
Informationen zur Grundlagenliste der Python-Grundlagen
Geschichte der Potenznäherung von Python
Lernen Sie die Grundlagen von Python ① Grundlegende Anfänger
Japanische Sprachverarbeitung durch Python3 (5) Ensemble-Lernen verschiedener Modelle durch Voting Classifier
Lernen Sie die Grundlagen der Dokumentklassifizierung durch Verarbeitung natürlicher Sprache, Themenmodell
[Wissenschaftlich-technische Berechnung mit Python] Berechnung des Matrixprodukts mit @ operator, python3.5 oder höher, numpy