Wahrscheinlich eine der größten Entdeckungen des Jahres, also habe ich damit als Einführung in Pytorch gespielt. Es ist fast die gleiche Geschichte wie bei den folgenden Pionieren, daher werde ich mich auf Urans Nöte und einen kleinen Kommentar konzentrieren (was mir aufgefallen ist). Die Referenz ist wie folgt.
Citation
If you use this code for your research, please cite our paper:
@inproceedings{rottshaham2019singan,
title={SinGAN: Learning a Generative Model from a Single Natural Image},
author={Rott Shaham, Tamar and Dekel, Tali and Michaeli, Tomer},
booktitle={Computer Vision (ICCV), IEEE International Conference on},
year={2019}
}
【Referenz】 ①SinGAN: Learning a Generative Mode from a Single Natural Image@arXiv:1905.01164v2 [cs.CV] 4 Sep 2019 ②Code available at: https://github.com/tamarott/SinGAN ③ Tera war unglaublich, als ich SinGANs Artikel las ④ [Erklärung des Papiers] SinGAN: Lernen eines generativen Modells aus einem einzelnen natürlichen Bild ⑤ [SinGAN] Aktiviert verschiedene Bilderzeugungsaufgaben aus nur einem Bild
・ Umgebung und Ausführung ・ Kurzer Kommentar zum Papier ・ Über das Training · Animation ・ Super Auflösung ・ Malen Sie auf Bild
Laden Sie zuerst Zip von Github in Referenz (2) oben herunter und entpacken Sie es. Sie können es mit dem folgenden Befehl in der Pytorch-Umgebung des anderen Tages installieren.
Install dependencies
python -m pip install -r requirements.txt
This code was tested with python 3.6 Und was Sie tun können, ist: (Übersetzung von Github oben)
Train Um ein SinGAN-Modell mit Ihrem eigenen Bild zu trainieren, platzieren Sie das Trainingsbild unter Eingabe / Bilder und gehen Sie wie folgt vor:
python main_train.py --input_name <input_file_name>
Sie können das resultierende trainierte Modell auch verwenden, um Zufallsstichproben ab der gröbsten Skala (n = 0) zu generieren. Beim Training werden trainierte Modelle für jede Rauheitsskala (n) gespeichert.
Um diesen Code auf dem CPU-Computer auszuführen, geben Sie beim Aufrufen von main_train.py --not_cuda an
Random samples Um eine Zufallsstichprobe aus der Rauheitsskala zu generieren, trainieren Sie zuerst das SinGAN-Modell des gewünschten Bildes und gehen Sie dann wie folgt vor:
python random_samples.py --input_name <training_image_file_name> --mode random_samples --gen_start_scale <generation start scale number>
Hinweis: Wenn Sie das vollständige Modell verwenden möchten, geben Sie 0 für die Startrauheitsskala und 1 an, um die Generierung ab der zweiten Skala zu starten. Es scheint, dass die Schönheit des fertigen Produkts Skala 0 sein sollte.
Random samples of arbitrery sizes Um eine Zufallsstichprobe beliebiger Größe zu generieren, trainieren Sie zuerst das SinGAN-Modell des gewünschten Bildes (wie oben) und gehen Sie dann wie folgt vor:
python random_samples.py --input_name <training_image_file_name> --mode random_samples_arbitrary_sizes --scale_h <horizontal scaling factor> --scale_v <vertical scaling factor>
Animation from a single image Gehen Sie wie folgt vor, um aus einem einzelnen Bild eine kurze Animation zu erstellen:
python animation.py --input_name <input_file_name>
Dadurch wird automatisch eine neue Trainingsphase im Noise Padding-Modus gestartet. Wenn die Ausführung beendet ist, wird automatisch eine Gif-Animation für jede Startrauheitsskala generiert und in jeder Richtung gespeichert. Die Änderung ist am größten, wenn start_scale = 0 ist, und die Änderung wird kleiner, wenn die start_scale zunimmt. Harmonization Um das eingefügte Objekt mit dem Bild in Einklang zu bringen (siehe Beispiel in Abbildung 13 des Papiers), trainieren Sie zuerst das SinGAN-Modell für das gewünschte Hintergrundbild (wie oben) und dann die naiv eingefügte Referenz Speichern Sie das Bild und seine Binärmaske unter "Eingabe / Harmonisierung" (siehe Beispiel im Verzeichnis der Download-Datei). Gehen Sie dann wie folgt vor:
python harmonization.py --input_name <training_image_file_name> --ref_name <naively_pasted_reference_image_file_name> --harmonization_start_scale <scale to inject>
Beachten Sie, dass unterschiedliche Injektionsskalen unterschiedliche Harmonieeffekte erzeugen. Die gröbste Injektionsskala ist 1.
Editing Um das Bild zu bearbeiten (siehe Beispiel in Abbildung 12 des Papiers), trainieren Sie zuerst das SinGAN-Modell mit dem gewünschten unbearbeiteten Bild (wie oben) und dann mit dem einfach bearbeiteten Bild Speichern Sie es mit der Binärkarte als Referenzbild unter "Eingabe / Bearbeitung" (siehe Beispiel Gespeichertes Bild). Gehen Sie dann wie folgt vor:
python editing.py --input_name <training_image_file_name> --ref_name <edited_image_file_name> --editing_start_scale <scale to inject>
Sowohl maskierte als auch nicht maskierte Ausgaben werden gespeichert. Auch hier erzeugen unterschiedliche Injektionsskalen unterschiedliche Bearbeitungseffekte. Die gröbste Injektionsskala ist 1.
Paint to Image Um die Farbe in ein realistisches Bild umzuwandeln (siehe Beispiel in Abbildung 11 des Papiers), trainieren Sie zuerst das SinGAN-Modell mit dem gewünschten Bild (wie oben) und dann unter "Eingabe / Farbe". Speichern Sie die Farbe in und gehen Sie wie folgt vor:
python paint2image.py --input_name <training_image_file_name> --ref_name <paint_image_file_name> --paint_start_scale <scale to inject>
Auch hier erzeugen unterschiedliche Injektionsskalen unterschiedliche Bearbeitungseffekte. Die gröbste Injektionsskala ist 1.
Advanced option: Specify quantization_flag to be True, to re-train only the injection level of the model, to get a on a color-quantized version of upsamled generated images from previous scale. For some images, this might lead to more realistic results.
Super Resolution Gehen Sie wie folgt vor, um das Bild in Superauflösung zu bringen:
python SR.py --input_name <LR_image_file_name>
Dadurch wird das SinGAN-Modell automatisch auf einen 4-fachen Upsampling-Faktor trainiert (sofern dieser noch nicht vorhanden ist). Verwenden Sie für verschiedene SR-Koeffizienten den Parameter --sr_factor, wenn Sie die Funktion aufrufen. Der SR-Koeffizient ist standardmäßig 4, und je größer der Wert, desto größer das fertige Bild.
SinGAN-Ergebnisse für den BSD100-Datensatz können aus dem Ordner Downloads heruntergeladen werden.
Additional Data and Functions Single Image Fréchet Inception Distance (SIFID score) Gehen Sie wie folgt vor, um die SIFID zwischen dem tatsächlichen Bild und dem entsprechenden gefälschten Beispiel zu berechnen:
python SIFID/sifid_score.py --path2real <real images path> --path2fake <fake images path> --images_suffix <e.g. jpg, png>
Stellen Sie sicher, dass jeder der gefälschten Bilddateinamen mit dem entsprechenden tatsächlichen Bilddateinamen übereinstimmt.
Referenzen sind Papiere usw., aber ich denke, die Erfindung von sinGAN ist wie folgt.
Learning One-Daten sind in letzter Zeit wahrscheinlich sehr beliebt geworden, aber ich denke, es ist das erste Mal, dass ich sie tatsächlich gelernt und verwendet habe.
ResGAN befindet sich in Referenz ⑥ und WGAN-GP in Referenz ⑦ und wird als Methode mit hoher Konvergenzleistung vorgeschlagen. 【Referenz】 ⑥Generative Adversarial Network based on Resnet for Conditional Image Restoration@arXiv:1707.04881v1 [cs.CV] 16 Jul 2017 ⑦Improved Training of Wasserstein GANs Erstens ist ResGAN in Referenz ⑥ der folgende Generator.
Andererseits besteht der Generator jeder Stufe von sinGAN aus ResGAN unterhalb der Basisstufe mit Ausnahme der ersten. Das heißt, $ (\ bar x_ {n-1}) ↑ ^ r $, ein vergrößertes Bild von $ z_n $ und ein gröberes Bild, wird als Eingabe von $ G_n $ verwendet, und der Unterschied wird gelernt, um es klarer zu machen. Es erzeugt das Bild $ \ bar x_n $. Hinweis) Hier gibt $ ↑ ^ r $ die Vergrößerung des Bildes an. Apropos,
min_{G_n}max_{D_n}L_{adv}(G_n,D_n)+αL_{rec}(G_n)
Der erste Term ist WGAN-GP in Referenz ⑦, der durch die folgende Formel ausgedrückt wird. Der zweite Begriff ist
L_{rec} = ||G_n(0,(\bar{x}^{rec}_{n+1}) ↑^r) − x_n||^2,
and for
L_{rec} = ||G_N (z^∗) − x_N||^2
"Das Eingangsrauschbild zu diesem Zeitpunkt ist $ z_n (n = 0, ..., N-1) = 0 $, und nur $ z_N $ ist eine feste Zufallszahl, die zu Beginn des Trainings festgelegt wurde." (Referenz ④ Mehr zitiert)
Das Lernen wird fortgesetzt, indem ResGAN wie in der folgenden Abbildung gezeigt wiederholt wird. Hier beginnt das Lernen in der unteren Reihe, aber hier wird nur $ z_N $ eingegeben, das aus Zufallszahlen generiert wurde. Dicriminator vergleicht es mit dem reduzierten Realbild $ x_N $ des Originalbildes, das automatisch ermittelt wird, wenn die Anzahl der Trainings ermittelt wird. Geben Sie danach das Bild $ (\ bar x_ {n-1}) ↑ ^ r $ und $ z_ {N-1} $ ein, das das auf diese Weise erzeugte vergrößerte Bild $ \ bar x_ {n-1} $ ist. Machen. Auf diese Weise nutzen verschiedene Apps die erlernten Lernparameter und Bilder.
Wie oben erwähnt, denke ich, dass Sie lernen können. Wans Pytorch-Umgebung verwendet 1060, sodass der GPU-Speicher etwa 3 GB beträgt. Damit gab es einige Bilder wie cow.png, die nicht bis zum Ende gelernt werden konnten. Daher habe ich versucht, die Größe der Anfangsbilder (Eingabe / Bilder) zu reduzieren, aber die Größe des reduzierten Bildes wie n = 0 zum Lernen hat sich nicht geändert und der Speicherfehler ist nicht leicht verschwunden. Als ich es auf den 1/3 Platz reduzierte, gelang es mir, den Endwert von n etwas kleiner zu machen und ich konnte sicher lernen, aber das Ergebnis war, dass das Lernbild klein und nicht sehr interessant war.
Dies ist interessant, weil es sich bewegt, aber wenn Sie sich animation.py ansehen, scheint es, dass Sie sich bewegen, indem Sie die Lokalität des Features ändern (den Wert von start_scale ändern) und Zufallszahlen im latenten Raum schütteln. Als Ergebnis können Sie eine Animation erstellen, bei der ein kleiner Wert von n stark schwankt und sich ein großer Wert von n kaum bewegt. Nachfolgend einige Beispiele.
start_scale=0 | start_scale=1 | start_scale=2 |
---|---|---|
Gemäß der folgenden Tabelle im Papier ist die Genauigkeit vergleichbar mit SRGAN, das Wan neulich eingeführt hat. Also habe ich Folgendes versucht. In der folgenden Tabelle wird die Superauflösung nach rechts erhöht. Gleichzeitig wird die Größe nach rechts größer. Sie können die tatsächliche Größe und Superauflösung fühlen, indem Sie darauf klicken, um sie unabhängig anzuzeigen.
original | Erweiterung 1 | Erweiterung 2 | Erweiterung 3 |
---|---|---|---|
Es bedeutet, ein einfaches Bild in ein Bild umzuwandeln. Das folgende Beispiel wird in diesem Artikel veröffentlicht. Wenn Sie das Bild auf der linken Seite trainieren, das zweite einfache Bild in "Eingabe / Farben" einfügen und den Befehl ausführen, wird das Bild auf der rechten Seite ausgegeben. Diese Abbildung zeigt auch, dass die sinGAN-Ergebnisse anderen Methoden überlegen sind. Das Ausführungsergebnis dieses Wan ist wie folgt. Zu diesem Zweck habe ich beim 1060 einen Speicherfehler erhalten und konnte das Bild links nicht lernen. Deshalb, Das 250x141-Bild wurde auf 80x46 reduziert. Das Malbild ist 300x200. Das Ergebnis ist zu klein, aber je gröber die Lernparameter sind, desto gröber kann das Bild reproduziert werden. Wenn andererseits n = 1 ist, erscheint bis zu einem gewissen Grad ein kuhähnliches Bild.
Das Originalbild | Paint | n=1 | n=2 | n=3 | n=4 |
---|---|---|---|---|---|
・ Ich habe mit sinGAN gespielt ・ Vorerst habe ich das Prinzip verstanden ・ Mit dem neuen ResGAN konnte ich die Kraft des lokalen Lernens aus der gesamten Region realisieren.
・ Wenn es 1060 ist, ist die Größe des Bildes aufgrund des Mangels an GPU-Speicher begrenzt. ・ Ich denke, es ist eine Entdeckung, die uns ein Gefühl des Fortschritts gibt.
Der Generator und der Dicriminator von ResGAN werden entsprechend der Größe des Eingabebildes parameterangepasst und haben die folgende Struktur.
GeneratorConcatSkip2CleanAdd(
(head): ConvBlock(
(conv): Conv2d(3, 32, kernel_size=(3, 3), stride=(1, 1))
(norm): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(LeakyRelu): LeakyReLU(negative_slope=0.2, inplace=True)
)
(body): Sequential(
(block1): ConvBlock(
(conv): Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1))
(norm): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(LeakyRelu): LeakyReLU(negative_slope=0.2, inplace=True)
)
(block2): ConvBlock(
(conv): Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1))
(norm): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(LeakyRelu): LeakyReLU(negative_slope=0.2, inplace=True)
)
(block3): ConvBlock(
(conv): Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1))
(norm): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(LeakyRelu): LeakyReLU(negative_slope=0.2, inplace=True)
)
)
(tail): Sequential(
(0): Conv2d(32, 3, kernel_size=(3, 3), stride=(1, 1))
(1): Tanh()
)
)
WDiscriminator(
(head): ConvBlock(
(conv): Conv2d(3, 32, kernel_size=(3, 3), stride=(1, 1))
(norm): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(LeakyRelu): LeakyReLU(negative_slope=0.2, inplace=True)
)
(body): Sequential(
(block1): ConvBlock(
(conv): Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1))
(norm): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(LeakyRelu): LeakyReLU(negative_slope=0.2, inplace=True)
)
(block2): ConvBlock(
(conv): Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1))
(norm): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(LeakyRelu): LeakyReLU(negative_slope=0.2, inplace=True)
)
(block3): ConvBlock(
(conv): Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1))
(norm): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(LeakyRelu): LeakyReLU(negative_slope=0.2, inplace=True)
)
)
(tail): Conv2d(32, 1, kernel_size=(3, 3), stride=(1, 1))
...
GeneratorConcatSkip2CleanAdd(
(head): ConvBlock(
(conv): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1))
(norm): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(LeakyRelu): LeakyReLU(negative_slope=0.2, inplace=True)
)
(body): Sequential(
(block1): ConvBlock(
(conv): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1))
(norm): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(LeakyRelu): LeakyReLU(negative_slope=0.2, inplace=True)
)
(block2): ConvBlock(
(conv): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1))
(norm): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(LeakyRelu): LeakyReLU(negative_slope=0.2, inplace=True)
)
(block3): ConvBlock(
(conv): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1))
(norm): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(LeakyRelu): LeakyReLU(negative_slope=0.2, inplace=True)
)
)
(tail): Sequential(
(0): Conv2d(64, 3, kernel_size=(3, 3), stride=(1, 1))
(1): Tanh()
)
)
WDiscriminator(
(head): ConvBlock(
(conv): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1))
(norm): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(LeakyRelu): LeakyReLU(negative_slope=0.2, inplace=True)
)
(body): Sequential(
(block1): ConvBlock(
(conv): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1))
(norm): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(LeakyRelu): LeakyReLU(negative_slope=0.2, inplace=True)
)
(block2): ConvBlock(
(conv): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1))
(norm): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(LeakyRelu): LeakyReLU(negative_slope=0.2, inplace=True)
)
(block3): ConvBlock(
(conv): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1))
(norm): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(LeakyRelu): LeakyReLU(negative_slope=0.2, inplace=True)
)
)
(tail): Conv2d(64, 1, kernel_size=(3, 3), stride=(1, 1))
)
Recommended Posts