[PYTHON] Niedrigrangige Approximation von Bildern durch Singularitätszerlegung

Einführung

Führen Sie eine Singularwertzerlegung durch? > Begrüßung

Ich habe das Gefühl, dass die Menschen um mich herum erst in letzter Zeit einzelne Werte zerlegen, deshalb habe ich beschlossen, es auch zu versuchen. Stellen Sie sich das Bild vorerst als eine Matrix vor und führen Sie eine Singular-Value-Zerlegung (SVD) durch, um ein Bild mit einer niedrigen Approximation zu erstellen. Für die Singularitätszerlegung [Wikipedia](https://ja.wikipedia.org/wiki/%E7%89%B9%E7%95%B0%E5%80%A4%E5%88%86%E8%A7% Bitte beachten Sie A3).

Ich weiß nicht, wer die Geschichte der Singularwertzerlegung von Bildern begonnen hat, aber ich bin in diesem Artikel T. Kumamoto, M. Suzuki und H. Matsueda arXiv: 1608.08333. Ich habe von 1608.08333 gelernt).

Der Quellcode ist https://github.com/kaityo256/image_svd Es ist in.

Bilder laden

Verwenden Sie Pillow of Python, um das Bild zu laden. Wenn nicht

$ pip install Pillow

Lassen Sie es uns einfügen.

Obwohl es sich um ein Eingabebild handelt, ist es einfacher, die Approximationsgenauigkeit zu verstehen, wenn Zeichen vorhanden sind. Deshalb habe ich vorerst so etwas vorbereitet.

stop.jpg

Konvertieren Sie dies zuerst in Graustufen.

from PIL import Image
img = Image.open('stop.jpg')
gray_img = img.convert('L')
gray_img.save('stop_mono.jpg')

Ich fühle mich so.

stop_mono.jpg

Singularitätszerlegung

Verwenden Sie numpy und scipy für die Singularitätszerlegung. Lass es uns importieren.

import numpy as np
from scipy import linalg

Der Zugriff auf Bilddaten kann unverändert mit einem Array von Numpy gelesen werden. Danach können Sie mit linalg.svd von scipy SVD. Es ist zu einfach.

a = np.asarray(gray_img)
u, s, v = linalg.svd(a)

Die hier erzeugten u, s und v sind das Ergebnis der Singularwertzerlegung. Von diesen ist s eine Liste von Singularwerten.

Niedrige Rangnäherung

Wenn nur die höheren Ränge ausgewählt und aus den Singularitätszerlegungen rekonstruiert werden, wird eine Annäherung mit niedrigem Rang erhalten.

image.png

Obwohl Σ (s im Code) tatsächlich eine Matrix ist, ist es ein Vektor im Rückgabewert von linalg.svd, sodass es in eine Matrix konvertiert werden muss. Wenn Sie danach die geschnittenen Stücke mit der erforderlichen Menge multiplizieren, erhalten Sie eine niedrigrangige angenäherte Matrix. Der Code sieht so aus.

rank = 10
ur = u[:, :rank]
sr = np.matrix(linalg.diagsvd(s[:rank], rank,rank))
vr = v[:rank, :]
b = np.asarray(ur*sr*vr)
img2 = Image.fromarray(np.uint8(b))
img2.save('stop_r10_mono.jpg')

Das erhaltene Ergebnis ist wie folgt.

stop_r10_mono.jpg

Farbversion

Das Obige ist der Einfachheit halber eine Graustufe. Wenn Sie jedoch jedes RGB-Element als SVD verwenden, können Sie auch eine Farbversion erstellen. Der einzige süchtig machende Punkt hier ist, dass ich in der monochromen Version Image.fromarray so wie es ist verwendet habe, aber in Farbe muss ich es zu einem Array von (r, g, b) Tapples machen. Das Objekt, das durch Multiplizieren der Matrix von numpy erstellt werden kann, ist ein Matrix-Objekt. Um danach als Array darauf zugreifen zu können, müssen Sie es mit np.asarray an ein Array zurückgeben. Wenn Sie darauf achten, können Sie es sofort tun.

Erstellen Sie eine Funktion der niedrigrangigen Approximation der Matrix wie folgt.

def perform_svd(a,rank):
    u, s, v = linalg.svd(a)
    ur = u[:, :rank]
    sr = np.matrix(linalg.diagsvd(s[:rank], rank,rank))
    vr = v[:rank, :]
    return np.asarray(ur*sr*vr)

Der Punkt ist, dass der Rückgabewert ein Array mit asarray ist. Mit diesem können Sie leicht eine Farbversion erstellen.

    w = img.width
    h = img.height
    A = np.asarray(img)
    r = perform_svd(A[:,:,0],rank).reshape(w*h)
    g = perform_svd(A[:,:,1],rank).reshape(w*h)
    b = perform_svd(A[:,:,2],rank).reshape(w*h)
    B = np.asarray([r,g,b]).transpose(1,0).reshape(h,w,3)
    img2 = Image.fromarray(np.uint8(B))
    img2 = Image.fromarray(np.uint8(data))
    img2.save(`stop_r10.jpg`)

Wenn Sie ein "Numpy" -Array aus Bilddaten erstellen, handelt es sich um ein dreidimensionales Array von (Höhe, Breite, Farbe). Wenn Sie also jede Farbe SVD und anhängen, ist es ein Array von (Farbe, Höhe * Breite). Nachdem Sie es durch Transponieren ersetzt haben, formen Sie es in die ursprüngliche 3D-Array-Form um und tauchen Sie es in "Image.fromarray" ein.

Das resultierende Bild sieht so aus.

stop_r10.jpg

abschließend

Wenn Sie mit diesem Bild 20 Ränge einnehmen, können Sie das Originalbild fast wiederherstellen. Es würde Spaß machen herauszufinden, wie viel zu nehmen ist und welche Art von Bild welches Spektrum hat.

Nein, aber wenn Sie das Bild lesen, es grau skalieren, in eine Matrix umwandeln, SVD erstellen, eine Annäherung mit niedrigem Rang erstellen, es im Bild wiederherstellen und speichern und die entsprechende Bibliothek mit Python importieren, können Sie dies in 15 Zeilen tun. Aha ... Ich denke, dass "der Reichtum der Bibliothek die Stärke der Sprache ist" ...

Recommended Posts

Niedrigrangige Approximation von Bildern durch Singularitätszerlegung
Niedrigrangige Approximation des Bildes durch Tucker-Zerlegung
Schritt-für-Schritt-Approximation von Bildern mit niedrigem Rang durch HOSVD
Niedrigrangige Approximation von Bildern durch HOSVD und HOOI
Singularitätszerlegung (SVD), Low Rank Approximation (LRA) in Python
Versuchen Sie, die Daimyo-Matrix durch einen Singularwert zu zerlegen
Versuchen Sie die Singularwertzerlegung mit Python
Geschichte der Potenznäherung von Python
Gesichtserkennung durch Sammeln von Bildern von Angers.
Klassifizierung von Gitarrenbildern durch maschinelles Lernen Teil 1
Klassifizierung von Gitarrenbildern durch maschinelles Lernen Teil 2
Suchen Sie nach dem Wert der Instanz in der Liste
Optischer Fluss, das von OpenCV aufgenommene dynamische Bild
Ich verglich die Identität der Bilder nach Hu Moment