[PYTHON] Lassen Sie uns über die Tonkurve der Bildverarbeitung sprechen ~ LUT ist erstaunlich ~

Einführung

Ich habe gerade angefangen, OpneCV in Python zu verwenden Ich habe verschiedene Dinge ausprobiert und bin gestolpert Ich werde es schwer schreiben.

Wenn Sie es aufheben und sprechen ** LUT ist unglaublich! ** ich dachte ** Ich habe versucht, LUT zu verwenden! ** Es ist der Inhalt.

(Infolgedessen) habe ich auch die Leistung mit meiner eigenen Farbkonvertierungsfunktion verglichen.

Betriebsumgebung

Terminal: Windows 10
Konsole: cmd(Eingabeaufforderung)
python:3.6.8
Virtuelle Umgebung: venv

Wenn Sie cmd bequem machen möchten, klicken Sie hier >> [https://qiita.com/RoaaaA/items/694ae4ccfa4a69fc8286)

Einführung

Ich habe in einer Universitätsklasse (Papierkram) etwas über Computer Vision (CV) gelernt. Zum ersten Mal stieß ich auf etwas namens "** Tonkurve **". Was ist eine Tonkurve?

Jedes Pixel des digitalen Bildes hat einen Wert (Pixelwert), der den Farbton darstellt. Um den Farbton des Bildes zu ändern, wird der Pixelwert des Ausgabebilds mit dem Pixelwert des Eingabebilds verknüpft. Die Funktion, die eine solche Entsprechung ergibt, wird als Graustufentransformationsfunktion bezeichnet, und die grafische Darstellung davon wird als Tonkurve bezeichnet.

Wenn man das Netz betrachtet, scheint es denen vertraut zu sein, die Kameras mögen.

Unter den Tonkurven, die im Lehrbuch erschienen, waren die folgenden zwei. (* Natürlich sind viele andere erschienen)

Die horizontale Achse ist ** Eingabepixelwert ** und die vertikale Achse ist ** Ausgabepixelwert **.

toneCurve12.png toneCurve22.png
Abbildung 1 Figur 2

Einfach ausgedrückt ** Umwandlung zur Erhöhung des Kontrasts ** und ** Konvertierung, die den Kontrast verringert **.

Dieser Teil der Klasse war bereits vor über einem halben Jahr. Ich wollte diese Tonkurve tatsächlich auf das Bild anwenden.

Funktionalisierung

Als Funktion ausgedrückt ist es wie folgt (x ist der Eingangspixelwert 0 bis 255).

Funktion in Abbildung 1:

f(x) = \begin{cases} 2 \cdot x & (x < 128) \\ 255 & (otherwise)
  \end{cases}

Funktion in Abbildung 2:

f(x) = \begin{cases} 0 & (x < 128) \\ 2 \cdot x - 255 & (otherwise)
  \end{cases}

Es sieht so aus, als ob es verallgemeinert werden kann, aber lassen wir das jetzt.

Fehler 1

Zunächst habe ich beschlossen, den in Abbildung 1 gezeigten Code zu schreiben. Aber ... es blieb sofort stecken.

Als ich auf die obige Funktion kam Ich dachte, ich könnte einfach die Elementwerte des ursprünglichen Arrays von Pixelwerten verdoppeln.

Konvertierungsfunktion


def toneCurve(frame):
    return 2 * frame

frame = cv2.imread('.\\image\\castle.jpg')
cv2.imwrite('cas.jpg', toneCurve(frame))

frame ist ein Array von Pixelwerten

Aber es hat nicht funktioniert. Das Ausgabebild ist wie folgt.

Das Originalbild Konvertiertes Bild
Das Originalbild Fehlerbild 1

Anscheinend, wenn Sie einfach den durch cv2.imread () erhaltenen Pixelwert verdoppeln Alles, was größer als 255 (maximal) ist, wird 255 sein, anstatt ergänzt zu werden Es schien den Wert zyklisch umzuwandeln und zurückzugeben. (ex:256=0, 260=4)

Es ist sehr schrecklich und ich mag dieses Der Zweck ist nicht dieses Bild, also werde ich es verbessern.

Verbesserung 1 (Fehler 2)

Wenn Sie nachschlagen, können Sie cv2.add () verwenden Es scheint, dass Werte über 255 als 255 behandelt werden.

Ich habe es versucht.

Verbesserungen in Abbildung 1

Addiere deinen eigenen Pixelwert zu dir selbst = konstante Zeiten Weil es bedeutet Die Konvertierungsfunktion ist wie folgt.

Konvertierungsfunktion


def toneCurve11(frame, n = 1):
    tmp = frame
    if n > 1:
        for i in range(1,n):
            tmp = cv2.add(tmp, frame)
    return tmp

frame ist ein Array von Pixelwerten n gibt an, wie oft der Pixelwert multipliziert wird, dh wie oft hinzugefügt werden soll.

Dann ist es das Ergebnis.

Das Originalbild Konvertiertes Bild
Das Originalbild Fehlerbild 2

Ja! Das habe ich gesucht! Es wird ein Bild mit erhöhtem Kontrast ausgegeben. (War das Graustufenbild besser?)

Wie können wir jedoch die in Abb. 2 gezeigte Konvertierung erreichen, indem wir nur diese Methode hinzufügen? Möchten Sie ein Bild ausgeben?

** Ich hatte einen schnellen Treffer **: Feuerwerk:

Verbesserungen in Abbildung 2

Was ich mir ausgedacht habe, ist dies.

** Negative / Positive Inversion>cv2.add ()> Negative / Positive Inversion **

In der Abbildung sieht es so aus.

ori negapoei
1.Keine Konvertierung 2.Negative / positive Umkehrung
add renegaposi
3.cv2.add()Verdoppelt mit 4.Negative / positive Umkehrung

Die Änderungen liegen in der Größenordnung von 1, 2, 3, 4.

Der Konvertierungscode lautet wie folgt.

Konvertierungsfunktion


def negaPosi(frame):
    return 255 - frame


def toneCurve21(frame, n = 1):
    if n > 1:
        return negaPoso(toneCurve11(negaPosi(frame), n))
    return frame

Wie vorher frame ist ein Array von Pixelwerten n gibt an, wie oft der Pixelwert multipliziert wird, dh wie oft hinzugefügt werden soll.

Na dann das Ergebnis.

Das Originalbild Konvertiertes Bild
Das Originalbild Fehlerbild 3

Das Bild mit dem reduzierten Kontrast wurde sicher ausgegeben.

Pause

Selbst wenn ich das oben genannte mache, funktioniert es gut. Ich hatte das Gefühl, nach ** Bestellung ** gefragt zu werden, also beschloss ich, andere Methoden zu untersuchen.

Dann scheint cv2 eine praktische Sache namens ** LUT (Look Up Table) ** zu haben. Darüber hinaus, wenn die Bestellung recht klein gemacht werden kann ...

LUT Ich habe oben einige Ansätze gewählt, aber am Ende Wenn Sie den erfassten Pixelwert durch einen anderen Pixelwert ersetzen, können Sie ihn konvertieren.

Hier sind die möglichen Werte von Pixelwerten ** höchstens 256 Wege ** von 0 bis 255. Wenn ja, haben Sie eine Entsprechungstabelle, in der der Konvertierungszielwert für einen bestimmten Pixelwert im Voraus registriert wird. Wenn Sie sich auf einen Pixelwert beziehen, anstatt den Pixelwert selbst zu berechnen Berechnungskosten können durch einfaches Ersetzen reduziert werden.

Hier ist eine kurze Beschreibung der LUT.

Beispielsweise kann die folgende Entsprechungstabelle betrachtet werden.

Referenzpixel Verändere das Ziel
0 -> 0
1 -> 2
... ...
127 -> 254
128 -> 255
... ...
255 -> 255

Ja, diese Tabelle ist die Entsprechungstabelle der Tonkurve in Abbildung 1.

Wenn der Pixelwert von Frame [90] [90] ist Wenn es "[12, 245, 98]" wäre Nach dem Auftragen der LUT Es wird "[24, 255, 196]".

Verbesserung 2

Wir werden tatsächlich die LUT verwenden.

Verbesserung von Abbildung 1 (Re :)

Konvertierungsfunktion


def toneCurve12(frame, n = 1):
    look_up_table = np.zeros((256,1), dtype = 'uint8')
    for i in range(256):
        if i < 256 / n:
            look_up_table[i][0] = i * n
        else:
            look_up_table[i][0] = 255
    return cv2.LUT(frame, look_up_table)

frame ist ein Array von Pixelwerten n gibt an, wie oft der Pixelwert multipliziert werden soll.

Bedienungsanleitung

    look_up_table = np.zeros((256,1), dtype = 'uint8')

Erstellen Sie für den Teil von eine Korrespondenztabelle (256 x 1) zur Konvertierung.

Zu diesem Zeitpunkt sind die folgenden Werte noch gespeichert.

>>> look_up_table = np.zeros((256,1), dtype = 'uint8')
>>> look_up_table
array([[0],
       [0],
       [0],
       ...,
       [0],
       [0]], dtype=uint8)
>>> len(look_up_table)  
256

In der nächsten Zeile speichern wir die Werte, auf die verwiesen werden soll, in diesem Array.

    for i in range(256):
        if i < 256 / n:
            look_up_table[i][0] = i * n
        else:
            look_up_table[i][0] = 255

Registrieren Sie in Bezug auf den Teil von den Pixelwert in der Korrespondenztabelle für die zuvor erstellte Konvertierung.

Ebenfalls

        if i < 256 / n:

Der Teil von ist eine Verallgemeinerung des bedingten Ausdrucks, so dass er auch dann funktioniert, wenn der Pixelwert n-mal ist. (Beispiel: n = 3 [3-facher Pixelwert])

    return cv2.LUT(frame, look_up_table)

In Bezug auf den Teil von wird die Korrespondenz von der zuvor registrierten LUT übernommen. Gibt die konvertierten Bilddaten zurück.

Na dann das Ergebnis.

Das Originalbild Verbesserung 1 Verbesserung 2
Das Originalbild Fehlerbild 2 Erfolgsbild 1

Sie können das gewünschte Bild erhalten.

Werfen wir einen Blick auf die Ausführungszeit (ms).

n = 2 n = 3 n = 4
Verbesserung 1 4.9848556 9.9725723 15.921831
Verbesserung 2 4.9870014 4.9834251 4.9870014

Die Verarbeitung ist schneller.

Auf die gleiche Weise werden wir Abbildung 2 verbessern.

Verbesserung von Abbildung 2 (Re :)

Konvertierungsfunktion


def toneCurve22(frame, n = 1):
    look_up_table = np.zeros((256,1), dtype = 'uint8')
    for i in range(256):
        if i < 256 - 256 / n :
            look_up_table[i][0] = 0
        else:
            look_up_table[i][0] = i * n - 255 * (n - 1)
    return cv2.LUT(frame, look_up_table)

Was ich mache, ist fast das gleiche, also werde ich es nicht im Detail erklären,

        if i < 256 - 256 / n :

Der Teil von ist eine Verallgemeinerung des Funktionsteils, wenn "n = 2" ist, wobei "x <128". Wenn n = 2 x <256 - 256 / n = 128 Das heißt, Es kann in "x <128" umgewandelt werden.

Na dann das Ergebnis.

Das Originalbild Verbesserung 1 Verbesserung 2
Das Originalbild Fehlerbild 2 Erfolgsbild 1

Sie können das gewünschte Bild erhalten.

Werfen wir einen Blick auf die Ausführungszeit (ms).

n = 2 n = 3 n = 4
Verbesserung 1 25.915145 32.911539 36.406755
Verbesserung 2 4.9862861 4.9872398 4.9846172

Immerhin ist derjenige, der schnell verarbeitet, gut.

abschließend

Dieses Mal sprach ich über die Tonkurve.

OpenCV ist sehr praktisch. Meine Vorfahren ärgern sich nicht ... Darüber hinaus kann Python mit nur einem Befehl verwendet werden.

Wird jemand diesen Artikel sehen? Oder obwohl ich mir Sorgen mache Wenn dies ein Memorandum ist, versichern Sie Ich poste immer.

Ich hoffe, dass dieser Artikel eines Tages für jemanden nützlich sein wird.

Geben Sie zum Schluss den diesmal verwendeten Quellcode ein und beenden Sie den Vorgang. Was soll ich als nächstes tun?

Dann: Welle:

Quellcode

Unter dem aktuellen Verzeichnis In einem Verzeichnis namens image Es gibt eine Bilddatei namens Castle.jpg. Wenn Sie diesen Code verwenden, ändern Sie ihn bitte selbst.

Installieren Sie auch die folgende Bibliothek.

Konsole


$ pip install opencv-python

$ pip freeze
numpy==1.18.4
opencv-python==4.2.0.34

ex.py


import cv2
import numpy as np


def toneCurve(frame):
    return 2 * frame


def negaPosi(frame):
    return 255 - frame


def toneCurve11(frame, n = 1):
    tmp = frame
    if n > 1:
        for i in range(1, n):
            tmp = cv2.add(tmp, frame)
    return tmp


def toneCurve12(frame, n = 1):
    look_up_table = np.zeros((256, 1), dtype = 'uint8')
    for i in range(256):
        if i < 256 / n:
            look_up_table[i][0] = i * n
        else:
            look_up_table[i][0] = 255
    return cv2.LUT(frame, look_up_table)


def toneCurve21(frame, n = 1):
    if n > 1:
        return negaPoso(toneCurve11(negaPosi(frame), n))
    return frame


def toneCurve22(frame, n = 1):
    look_up_table = np.zeros((256, 1), dtype = 'uint8')
    for i in range(256):
        if i < 256 - 256 / n :
            look_up_table[i][0] = 0
        else:
            look_up_table[i][0] = i * n - 255 * (n - 1)
    return cv2.LUT(frame, look_up_table)


def main():
    img_path = '.\\image\\castle.jpg'
    img = cv2.imread(img_path)
    cv2.imwrite('.\\image\\tone00.jpg', toneCurve(img))
    cv2.imwrite('.\\image\\tone11.jpg', toneCurve11(img, 2))
    cv2.imwrite('.\\image\\tone12.jpg', toneCurve12(img, 2))
    cv2.imwrite('.\\image\\tone21.jpg', toneCurve21(img, 2))
    cv2.imwrite('.\\image\\tone22.jpg', toneCurve22(img, 2))

if __name__ == '__main__':
    main()

Referenz

[^ 1]: Auszug aus [Computer Graphics] cv(S. 262)

Recommended Posts

Lassen Sie uns über die Tonkurve der Bildverarbeitung sprechen ~ LUT ist erstaunlich ~
Die Bildanzeigefunktion von iTerm ist praktisch bei der Verarbeitung von Bildern.
Bildverarbeitung mit Python & OpenCV [Tonkurve]
Über die Hauptaufgaben der Bildverarbeitung (Computer Vision) und die verwendete Architektur
Über die Verarbeitungsgeschwindigkeit von SVM (SVC) von Scikit-Learn
Bildverarbeitung? Die Geschichte, Python für zu starten
Informationen zum Verhalten der Warteschlange während der Parallelverarbeitung
Lassen Sie uns den Entwicklungsstatus der Stadt anhand des Satellitenbildes erraten.
Sprachverarbeitung 100 Knocks-29: Holen Sie sich die URL des Flaggenbildes
Über die Komponenten von Luigi
Über die Funktionen von Python
Das Bild ist Namekuji
Verstehen Sie die Funktion der Faltung am Beispiel der Bildverarbeitung
Berücksichtigen Sie die Verarbeitungsgeschwindigkeit, um den Bildpuffer mit numpy.ndarray zu verschieben
[Word2vec] Lassen Sie uns das Ergebnis der Verarbeitung von Unternehmensbewertungen in natürlicher Sprache visualisieren