{ "nbformat": 4, "nbformat_minor": 0, "metadata": { "accelerator": "GPU", "colab": { "name": "kl_py_img_style_transfer_colab.ipynb", "provenance": [], "private_outputs": true, "collapsed_sections": [], "toc_visible": true, "include_colab_link": true }, "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.6" } }, "cells": [ { "cell_type": "markdown", "metadata": { "id": "view-in-github", "colab_type": "text" }, "source": [ "\"Open" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "6msVLevwcRhm" }, "source": [ "

\n", " \n", " \n", "

\n", "\n", "\n", "

\n", "\n", "\n", "\n", "# AI képek átalakítása Python és Tensorflow-val\n", "\n", "\n", "\n" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "aDyGj8DmXCJI" }, "source": [ "## Ez az oktatóprogram mély tanuláson alapszik.\n", "\n", "Egy képet egy másik kép stílusában komponál át.\n", "\n", "Játékosan elérhető hogy hasonló kép készüljön mint Picasso vagy Van Gogh alkotása. \n", "\n", "### Ezt neurális stílusátvitelnek nevezük, és a technikát a művészi stílus neurális algoritmusával valósítjük meg.\n", "\n", "Megjegyzés: \n", " - Ez az oktatóanyag bemutatja az eredeti stílusátviteli algoritmust. \n", " \n", " - Optimalizálja a kép tartalmát egy adott stílushoz. \n", " \n", " - A modern és antik megközelítések egy-egy modellt képezhet a stilizált kép közvetlen generálására (hasonlóan a cycganhez). \n", " \n", " Ez a megközelítés sokkal gyorsabb (akár 1000x). Egy előre kiképzett tetszőleges képstilizáló modul elérhető a TensorFlow Hub-ban és a TensorFlow Lite-hoz.\n", "\n", "A neurális stílusátvitel egy olyan optimalizálási technika, amelyet két kép - egy tartalomkép és egy stílus referenciakép (például egy híres festőművész alkotása) készítéséhez használnak, és összekeverik őket, így a kimeneti kép úgy néz ki, mint a tartalomkép, de “festett” a stílus referenciaképének stílusában.\n", "\n", "Ezt úgy valósítják meg, hogy a kimeneti képet úgy optimalizálják, hogy megfeleljen a tartalom kép tartalmi statisztikájának és a stílus referencia kép stílus statisztikájának. Ezeket a statisztikákat a képekből egy konvolúciós hálózat segítségével vonják ki.\n", "\n", "\n", "### Munka megkezdése előtt érdemes a rendszert frissiteni:\n", "`$conda update python\n", "$conda update keras\n", "$conda update tensorflow`\n", "\n", "\n", "### Minta forrása:\n", "https://www.tensorflow.org/tutorials/generative/style_transfer\n", "\n" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "3kb_UJY-jCEl" }, "source": [ "### Kiinduló kép egy mokus a farönkön\n", "\n", "\n", "\n", "\n", "### Stilus kép:\n", "\n", "\n", "\n", "\n", "### Eredmény kép:\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "xE4Yt8nArTeR" }, "source": [ "---\n", "\n", "## Vizualizácios bemenetek\n", "\n", "Itt határozzuk meg a kép betöltésének funkcióját, és korlátozzuk annak maximális méretét 512 pixelre.\n", "\n", "### Több képkezelő eljárás kerül meghatározásra\n", "\n", "---" ] }, { "cell_type": "code", "metadata": { "id": "D8PdhnbvWdY9", "colab_type": "code", "colab": {} }, "source": [ "from __future__ import absolute_import, division, print_function, unicode_literals\n" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "EDjxzYJlWdZC", "colab_type": "code", "colab": {} }, "source": [ "## tensorflow és más modulok betöltése\n", "try:\n", " # %tensorflow_version ellenőrzése\n", " %tensorflow_version 2.x\n", "except Exception:\n", " pass\n", "import tensorflow as tf\n", "import IPython.display as display\n", "\n", "import matplotlib.pyplot as plt\n", "import matplotlib as mpl\n", "mpl.rcParams['figure.figsize'] = (12,12)\n", "mpl.rcParams['axes.grid'] = False\n", "\n", "import numpy as np\n", "import PIL.Image\n", "import time\n", "import functools\n", "\n", "## Veziok kiírása\n", "print('TF verzio : ', tf.__version__)\n", "print('KERAS verzio : ', tf.keras.__version__)\n" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "-ibtEZvBWdZF", "colab_type": "code", "colab": {} }, "source": [ "## képállományok elérése a WEB -en\n", "#content_path = tf.keras.utils.get_file('YellowLabradorLooking_new.jpg', 'https://storage.googleapis.com/download.tensorflow.org/example_images/YellowLabradorLooking_new.jpg')\n", "#style_path = tf.keras.utils.get_file('kandinsky5.jpg','https://storage.googleapis.com/download.tensorflow.org/example_images/Vassily_Kandinsky%2C_1913_-_Composition_7.jpg')\n", "\n", "## mokus\n", "# content_path = tf.keras.utils.get_file('forras_kep1.jpg', r'https://1.bp.blogspot.com/-1xfgXDl6mYQ/XmIwnys8MDI/AAAAAAAAaFw/16mXksGvTiE3kgdXzU4LTNkM9YVnbvHXwCLcBGAsYHQ/s320/FB_IMG_1580926207371.jpg')\n", "style_path = tf.keras.utils.get_file('cel_kep1.jpg', r'https://1.bp.blogspot.com/-PA6HO5WxmMo/XmIxUVZsLbI/AAAAAAAAaGI/n4jHuu8NctsdnoFDzvy0mSHAuRJKdYlFwCLcBGAsYHQ/s320/1-style.jpg')\n", "\n", "## sas\n", "content_path = tf.keras.utils.get_file('forras_kep2.jpg', r'https://1.bp.blogspot.com/-WaDe31Qr3yg/XmIwn8KKNcI/AAAAAAAAaGE/OZaPJcax2-4_kwUZ8iguZRASS5W7Ycr_gCPcBGAYYCw/s1600/FB_IMG_1581224344102.jpg')\n" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "colab_type": "code", "id": "3TLljcwv5qZs", "colab": {} }, "source": [ "\n", "\n", "## kép brtöltő eljárás definiciója\n", "def tensor_to_image(tensor):\n", " tensor = tensor*255\n", " tensor = np.array(tensor, dtype=np.uint8)\n", " if np.ndim(tensor)>3:\n", " assert tensor.shape[0] == 1\n", " tensor = tensor[0]\n", " return PIL.Image.fromarray(tensor)\n", "\n", "\n", "def load_img(path_to_img):\n", " max_dim = 512 ## max\n", " img = tf.io.read_file(path_to_img)\n", " img = tf.image.decode_image(img, channels=3)\n", " img = tf.image.convert_image_dtype(img, tf.float32)\n", "\n", " shape = tf.cast(tf.shape(img)[:-1], tf.float32)\n", " long_dim = max(shape)\n", " scale = max_dim / long_dim\n", "\n", " new_shape = tf.cast(shape * scale, tf.int32)\n", "\n", " img = tf.image.resize(img, new_shape)\n", " img = img[tf.newaxis, :]\n", " return img\n", "\n", "## kép megjelenítés\n", "def imshow(image, title=None):\n", " if len(image.shape) > 3:\n", " image = tf.squeeze(image, axis=0)\n", "\n", " plt.imshow(image)\n", " if title:\n", " plt.title(title)" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "colab_type": "code", "id": "_UWQmeEaiKkP", "scrolled": false, "colab": {} }, "source": [ "## eljárások meghívása\n", "content_image = load_img(content_path) ## képfile bolvasása\n", "style_image = load_img(style_path) ## stilus képfile bolvasása\n", "\n", "plt.subplot(1, 2, 1) ## megjelenítési pozició\n", "imshow(content_image, 'Eredeti kép') ## megjelenítés\n", "\n", "plt.subplot(1, 2, 2) ## megjelenítési pozició\n", "imshow(style_image, 'Stilus kép') ## megjelenítés" ], "execution_count": 0, "outputs": [] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "YMzChXSlKTA2" }, "source": [ "---\n", "\n", "## Gyors stílusátvitel a TF-Hub segítségével lehet megtámogatni\n", "\n", "### Elérése:\n", "\n", " [TensorFlow Hub](https://tensorflow.org/hub) \n", "\n", " \n", " ---" ] }, { "cell_type": "code", "metadata": { "colab_type": "code", "id": "du6mqYbVgGcW", "colab": {} }, "source": [ "## A hub használathoz installálni kell a modult (ezt csak egyszer kell megtenni)\n", "# !pip install \"tensorflow_hub>=0.6.0\"" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "colab_type": "code", "id": "iYSLexgRKSh-", "colab": {} }, "source": [ "import tensorflow_hub as hub\n", "#hub_module = hub.load('https://tfhub.dev/google/magenta/arbitrary-image-stylization-v1-256/1') ## regi verzio\n", "hub_module = hub.load('https://tfhub.dev/google/magenta/arbitrary-image-stylization-v1-256/2') ## újabb verzio\n", "stylized_image = hub_module(tf.constant(content_image), tf.constant(style_image))[0]\n", "tensor_to_image(stylized_image)" ], "execution_count": 0, "outputs": [] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "GEwZ7FlwrjoZ" }, "source": [ "## A tartalom és a stílus ábrázolás paramétereinek megadása\n", "\n", "Használja a modell köztes rétegeit a kép tartalmának és stílusának ábrázolásához. \n", "\n", "A hálózat bemeneti rétegétől kezdve az első néhány réteg aktiválás alacsony szintű funkciókat képvisel, például éleket és textúrákat.\n", "\n", " A hálózaton való áthaladás során az utolsó néhány réteg magasabb szintű funkciókat képvisel - objektumrészeket, mint például a kerekeket vagy a szemét. \n", "\n", "Ebben az esetben a VGG19 hálózati architektúrát használjujk egy előre képzett képosztályozó hálózatot. \n", "\n", "Ezekre a köztes rétegekre van szükség a tartalom és a stílus képek ábrázolásának meghatározásához. \n", "\n", "A bemeneti képhez próbáljuk meg egyeztetni a megfelelő stílus- és tartalomcél reprezentációkat ezeken a közbenső rétegeken.\n", "\n", "Model elérése:\n", " [VGG19](https://keras.io/applications/#vgg19) \n" ] }, { "cell_type": "code", "metadata": { "colab_type": "code", "id": "fMbzrr7BCTq0", "colab": {} }, "source": [ "## model betoltés és paraméterezés\n", "x = tf.keras.applications.vgg19.preprocess_input(content_image*255)\n", "x = tf.image.resize(x, (224, 224))\n", "vgg = tf.keras.applications.VGG19(include_top=True, weights='imagenet')\n", "prediction_probabilities = vgg(x)\n", "prediction_probabilities.shape" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "colab_type": "code", "id": "1_FyCm0dYnvl", "colab": {} }, "source": [ "## Prediktiv modell\n", "predicted_top_5 = tf.keras.applications.vgg19.decode_predictions(prediction_probabilities.numpy())[0]\n", "[(class_name, prob) for (number, class_name, prob) in predicted_top_5]" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "colab_type": "code", "id": "Yh_AV6220ebD", "colab": {} }, "source": [ "## VGG19-et betöltése az osztályozó fej nélkül, és rétegnevek felsorolása nélkül\n", "vgg = tf.keras.applications.VGG19(include_top=False, weights='imagenet')\n", "\n", "print()\n", "for layer in vgg.layers:\n", " print(layer.name)" ], "execution_count": 0, "outputs": [] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "Wt-tASys0eJv" }, "source": [ "Choose intermediate layers from the network to represent the style and content of the image:\n" ] }, { "cell_type": "code", "metadata": { "colab_type": "code", "id": "ArfX_6iA0WAX", "colab": {} }, "source": [ "## Válasszunk köztes rétegek a hálózatból, hogy hogyan ábrázolja a kép stílusát és tartalmát:\n", "## Tartalmi réteg, ahova behúzza a funkciótérképeket\n", "content_layers = ['block5_conv2'] \n", "\n", "# Stilus réteg megadása\n", "style_layers = ['block1_conv1',\n", " 'block2_conv1',\n", " 'block3_conv1', \n", " 'block4_conv1', \n", " 'block5_conv1']\n", "\n", "num_content_layers = len(content_layers)\n", "num_style_layers = len(style_layers)" ], "execution_count": 0, "outputs": [] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "2o4nSwuN0U3X" }, "source": [ "## Középső rétegek a stílus és a tartalom számára\n", "\n", "Ezek a közbenső kimenetek engedik meg az előre képzett képosztályozó hálózatunkban a stílus és a tartalom ábrázolásainak meghatározását.\n", "\n", "Magas szinten annak érdekében, hogy egy hálózat elvégezhesse a kép osztályozását (amelyet erre a hálózatra kiképeztek), meg kell értenie a képet.\n", "\n", " Ehhez a nyers képet bemeneti képpontként kell venni, és létre kell hozni egy olyan belső ábrázolást, amely a nyers kép pixeleket a képen lévő tulajdonságok komplex megértésévé alakítja.\n", "\n", "Ez is az oka annak, hogy a konvolúciós ideghálózatok képesek jól általánosítani: képesek megragadni az osztályokon belüli invarianciákat és meghatározó jellemzőket (pl. Macskák vagy kutyák), amelyek a háttérzajt és más kellemetlenségeket kiváltják. \n", "\n", "Így, valahol a nyers kép beillesztése a modellbe és a kimeneti osztályozási címke között, a modell komplex szolgáltatáskivonatként szolgál. A modell köztes rétegeinek elérésével leírhatja a bemeneti képek tartalmát és stílusát.\n", "\n", "## Ezek után készítsuk el a modellt\n", "\n", "A tf.keras.applications hálózatait úgy tervezték meg, hogy a Keras funkcionális API segítségével könnyedén kivonhassák a közbenső réteg értékeit.\n", "\n", "A modell meghatározásához a funkcionális API használatával adja meg a bemeneteket és a kimeneteket:\n", "\n", "Ez a következő függvény egy VGG19 modellt épít fel, amely visszaadja a közbenső réteg kimeneteinek listáját:" ] }, { "cell_type": "code", "metadata": { "colab_type": "code", "id": "nfec6MuMAbPx", "colab": {} }, "source": [ "def vgg_layers(layer_names):\n", " # # Töltsünk be modellünket. Töltsük be az előképzett VGG-t, a képzett az imagenet adatokon\n", " vgg = tf.keras.applications.VGG19(include_top=False, weights='imagenet')\n", " vgg.trainable = False\n", " \n", " outputs = [vgg.get_layer(name).output for name in layer_names]\n", "\n", " model = tf.keras.Model([vgg.input], outputs)\n", " return model" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "colab_type": "code", "id": "LkyvPpBHSfVi", "colab": {} }, "source": [ "style_extractor = vgg_layers(style_layers)\n", "style_outputs = style_extractor(style_image*255)\n", "\n", "## Nézzük meg az egyes rétegek kimeneti statisztikáit\n", "for name, output in zip(style_layers, style_outputs):\n", " print(name)\n", " print(\" shape: \", output.numpy().shape)\n", " print(\" min: \", output.numpy().min())\n", " print(\" max: \", output.numpy().max())\n", " print(\" mean: \", output.numpy().mean())\n", " print()" ], "execution_count": 0, "outputs": [] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "lGUfttK9F8d5" }, "source": [ "---\n", "\n", "## Stilus számítások\n", "\n", "A kép tartalmát a közbenső jellemző térképek értékei képviselik.\n", "\n", "Kiderült, hogy a kép stílusát leírhatjuk az eszközökkel és a különféle térképek közötti összefüggésekkel. \n", "\n", "Számítson ki egy Gram-mátrixot, amely tartalmazza ezt az információt, úgy, hogy az objektumvektor külső termékét magával veszi az egyes helyekre, és átlagolja ezt a külső terméket az összes helyre. \n", "\n", "\n", "Ez a Gram-mátrix egy adott rétegre kiszámítható:\n", "\n", "$$G^l_{cd} = \\frac{\\sum_{ij} F^l_{ijc}(x)F^l_{ijd}(x)}{IJ}$$\n", "\n", "Ez tömören megvalósítható a `tf.linalg.einsum` függvény használatával: \n", "\n", "---" ] }, { "cell_type": "code", "metadata": { "colab_type": "code", "id": "HAy1iGPdoEpZ", "colab": {} }, "source": [ "def gram_matrix(input_tensor):\n", " result = tf.linalg.einsum('bijc,bijd->bcd', input_tensor, input_tensor)\n", " input_shape = tf.shape(input_tensor)\n", " num_locations = tf.cast(input_shape[1]*input_shape[2], tf.float32)\n", " return result/(num_locations)" ], "execution_count": 0, "outputs": [] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "1HGHvwlJ1nkn" }, "source": [ "---\n", "\n", "## Kivonatolt stílus és tartalom\n", "\n", "Készítsünk egy modellt, amely visszatér a stílus és a tartalom informáciokkal tenzoraihoz.\n", "\n", "---" ] }, { "cell_type": "code", "metadata": { "colab_type": "code", "id": "Sr6QALY-I1ja", "colab": {} }, "source": [ "class StyleContentModel(tf.keras.models.Model):\n", " def __init__(self, style_layers, content_layers):\n", " super(StyleContentModel, self).__init__()\n", " self.vgg = vgg_layers(style_layers + content_layers)\n", " self.style_layers = style_layers\n", " self.content_layers = content_layers\n", " self.num_style_layers = len(style_layers)\n", " self.vgg.trainable = False\n", "\n", " def call(self, inputs):\n", " \"Expects float input in [0,1]\"\n", " inputs = inputs*255.0\n", " preprocessed_input = tf.keras.applications.vgg19.preprocess_input(inputs)\n", " outputs = self.vgg(preprocessed_input)\n", " style_outputs, content_outputs = (outputs[:self.num_style_layers], \n", " outputs[self.num_style_layers:])\n", "\n", " style_outputs = [gram_matrix(style_output)\n", " for style_output in style_outputs]\n", "\n", " content_dict = {content_name:value \n", " for content_name, value \n", " in zip(self.content_layers, content_outputs)}\n", "\n", " style_dict = {style_name:value\n", " for style_name, value\n", " in zip(self.style_layers, style_outputs)}\n", " \n", " return {'content':content_dict, 'style':style_dict}" ], "execution_count": 0, "outputs": [] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "Xuj1o33t1edl" }, "source": [ "---\n", "\n", "Amikor képre hívnak egy képet, ez a modell visszatér a \"stílus_rétegek\" grammátrixa (stílusa) és a \"tartalom_rétegek\" tartalmával.\n", "\n", "---" ] }, { "cell_type": "code", "metadata": { "colab_type": "code", "id": "rkjO-DoNDU0A", "colab": {} }, "source": [ "extractor = StyleContentModel(style_layers, content_layers)\n", "\n", "results = extractor(tf.constant(content_image))\n", "\n", "style_results = results['style']\n", "\n", "print('Styles:')\n", "for name, output in sorted(results['style'].items()):\n", " print(\" \", name)\n", " print(\" shape: \", output.numpy().shape)\n", " print(\" min: \", output.numpy().min())\n", " print(\" max: \", output.numpy().max())\n", " print(\" mean: \", output.numpy().mean())\n", " print()\n", "\n", "print(\"Contents:\")\n", "for name, output in sorted(results['content'].items()):\n", " print(\" \", name)\n", " print(\" shape: \", output.numpy().shape)\n", " print(\" min: \", output.numpy().min())\n", " print(\" max: \", output.numpy().max())\n", " print(\" mean: \", output.numpy().mean())\n" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "colab_type": "code", "id": "kdgpTJwL_vE2", "colab": {} }, "source": [ "style_targets = extractor(style_image)['style']\n", "content_targets = extractor(content_image)['content']\n", "\n", "image = tf.Variable(content_image) ## tartalmazzák a képet az optimalizálás érdekében. A gyors megvalósítás érdekében inicializálja a tartalomképpel\n", "\n", "def clip_0_1(image): ## Mivel ez úszó kép, definiáljon egy funkciót a pixelértékek 0 és 1 közötti tartására:\n", " return tf.clip_by_value(image, clip_value_min=0.0, clip_value_max=1.0)\n", "\n", "opt = tf.optimizers.Adam(learning_rate=0.02, beta_1=0.99, epsilon=1e-1) ## optimalizáslás beállításai\n", "\n", "style_weight=1e-2\n", "content_weight=1e4" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "colab_type": "code", "id": "0ggx2Na8oROH", "colab": {} }, "source": [ "def style_content_loss(outputs):\n", " style_outputs = outputs['style']\n", " content_outputs = outputs['content']\n", " style_loss = tf.add_n([tf.reduce_mean((style_outputs[name]-style_targets[name])**2) \n", " for name in style_outputs.keys()])\n", " style_loss *= style_weight / num_style_layers\n", "\n", " content_loss = tf.add_n([tf.reduce_mean((content_outputs[name]-content_targets[name])**2) \n", " for name in content_outputs.keys()])\n", " content_loss *= content_weight / num_content_layers\n", " loss = style_loss + content_loss\n", " return loss" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "colab_type": "code", "id": "0t0umkajFIuh", "colab": {} }, "source": [ "@tf.function()\n", "def train_step(image): ## kép változtatási lépések\n", " with tf.GradientTape() as tape:\n", " outputs = extractor(image)\n", " loss = style_content_loss(outputs)\n", "\n", " grad = tape.gradient(loss, image)\n", " opt.apply_gradients([(grad, image)])\n", " image.assign(clip_0_1(image))" ], "execution_count": 0, "outputs": [] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "5FHMJq4UBRIQ" }, "source": [ "---\n", "\n", "### futtassünk pár válzoztató lépés közvetlenül és nézzük meg a hatását\n", "\n", "---" ] }, { "cell_type": "code", "metadata": { "colab_type": "code", "id": "Y542mxi-O2a2", "colab": {} }, "source": [ "train_step(image) ## 1 lépés\n", "train_step(image) ## 2 lépés\n", "train_step(image) ## 3 lépés\n", "train_step(image) ## 4 lépés\n", "train_step(image) ## 5 lépés\n", "tensor_to_image(image) # megjelenítés" ], "execution_count": 0, "outputs": [] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "mNzE-mTbBVgY" }, "source": [ "---\n", "\n", "## Mivel eddig működik, végezzünk optimalizálást is\n", "\n", "---\n" ] }, { "cell_type": "code", "metadata": { "colab_type": "code", "id": "rQW1tXYoLbUS", "colab": {} }, "source": [ "import time\n", "start = time.time()\n", "\n", "epochs = 5 ## léptető paraméter \n", "steps_per_epoch = 80 ## léptető paraméter \n", "\n", "step = 0\n", "for n in range(epochs):\n", " for m in range(steps_per_epoch):\n", " step += 1\n", " train_step(image)\n", " print(\".\", end='')\n", " display.clear_output(wait=True)\n", " display.display(tensor_to_image(image))\n", " print(\"Train step: {}\".format(step))\n", " \n", "end = time.time()\n", "print(\"Total time: {:.1f}\".format(end-start))" ], "execution_count": 0, "outputs": [] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "GWVB3anJMY2v" }, "source": [ "---\n", "\n", "## Teljes variációs veszteség\n", "\n", "Ennek az alapvető megvalósításnak az egyik hátránya, hogy sok magas frekvenciájú művet hoz létre. \n", "\n", "Csökkentse ezeket a kép nagyfrekvenciájú összetevőinek kifejezett szabályzási kifejezés használatával. \n", "\n", "A stílusátvitel során ezt gyakran így hívják: *total variation loss*\n", "\n", "\n", "---" ] }, { "cell_type": "code", "metadata": { "colab_type": "code", "id": "7szUUybCQMB3", "colab": {} }, "source": [ "def high_pass_x_y(image):\n", " x_var = image[:,:,1:,:] - image[:,:,:-1,:]\n", " y_var = image[:,1:,:,:] - image[:,:-1,:,:]\n", "\n", " return x_var, y_var" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "colab_type": "code", "id": "Atc2oL29PXu_", "colab": {} }, "source": [ "x_deltas, y_deltas = high_pass_x_y(content_image)\n", "\n", "plt.figure(figsize=(14,10))\n", "plt.subplot(2,2,1)\n", "imshow(clip_0_1(2*y_deltas+0.5), \"Horizontal Deltas: Original\")\n", "\n", "plt.subplot(2,2,2)\n", "imshow(clip_0_1(2*x_deltas+0.5), \"Vertical Deltas: Original\")\n", "\n", "x_deltas, y_deltas = high_pass_x_y(image)\n", "\n", "plt.subplot(2,2,3)\n", "imshow(clip_0_1(2*y_deltas+0.5), \"Horizontal Deltas: Styled\")\n", "\n", "plt.subplot(2,2,4)\n", "imshow(clip_0_1(2*x_deltas+0.5), \"Vertical Deltas: Styled\")" ], "execution_count": 0, "outputs": [] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "lqHElVgBkgkz" }, "source": [ "---\n", "\n", "## Most megmutatjuk, hogyan nővelhető a magas frekvenciájú komponensek.\n", "\n", "Ez a magas frekvenciájú elem alapvetõen egy éledetektor is. \n", "\n", "Hasonló kimenetet kaphatunk például a Sobel éldetektorról, például:\n", "\n", "---" ] }, { "cell_type": "code", "metadata": { "colab_type": "code", "id": "HyvqCiywiUfL", "colab": {} }, "source": [ "## plt.figure(figsize=(14,10))\n", "plt.figure(figsize=(10,8))\n", "\n", "sobel = tf.image.sobel_edges(content_image)\n", "plt.subplot(1,2,1)\n", "imshow(clip_0_1(sobel[...,0]/4+0.5), \"Horizontal Sobel-edges\")\n", "plt.subplot(1,2,2)\n", "imshow(clip_0_1(sobel[...,1]/4+0.5), \"Vertical Sobel-edges\")" ], "execution_count": 0, "outputs": [] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "vv5bKlSDnPP7" }, "source": [ "---\n", "\n", "### A rendezési veszteség az értékek négyzeteinek összege:\n", "\n", "---" ] }, { "cell_type": "code", "metadata": { "colab_type": "code", "id": "mP-92lXMIYPn", "colab": {} }, "source": [ "def total_variation_loss(image):\n", " x_deltas, y_deltas = high_pass_x_y(image)\n", " return tf.reduce_sum(tf.abs(x_deltas)) + tf.reduce_sum(tf.abs(y_deltas))\n", "\n", "total_variation_loss(image).numpy()\n", "\n", "tf.image.total_variation(image).numpy()" ], "execution_count": 0, "outputs": [] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "nTessd-DCdcC" }, "source": [ "## Optimalizáció ujra futtatása\n", "\n", "Válasszon súlyt `total_variation_loss`:" ] }, { "cell_type": "code", "metadata": { "colab_type": "code", "id": "BzmfcyyYUyWq", "colab": {} }, "source": [ "total_variation_weight=30\n", "\n", "@tf.function()\n", "def train_step(image):\n", " with tf.GradientTape() as tape:\n", " outputs = extractor(image)\n", " loss = style_content_loss(outputs)\n", " loss += total_variation_weight*tf.image.total_variation(image)\n", "\n", " grad = tape.gradient(loss, image)\n", " opt.apply_gradients([(grad, image)])\n", " image.assign(clip_0_1(image))\n", "\n", "image = tf.Variable(content_image)" ], "execution_count": 0, "outputs": [] }, { "cell_type": "code", "metadata": { "colab_type": "code", "id": "q3Cc3bLtoOWy", "colab": {} }, "source": [ "import time\n", "start = time.time()\n", "\n", "epochs = 6 ##--- 600 ig lépdel\n", "steps_per_epoch = 100\n", "\n", "step = 0\n", "for n in range(epochs):\n", " for m in range(steps_per_epoch):\n", " step += 1\n", " train_step(image)\n", " print(\".\", end='')\n", " display.clear_output(wait=True)\n", " display.display(tensor_to_image(image))\n", " print(\"Train step: {}\".format(step))\n", "\n", "end = time.time()\n", "print(\"Total time: {:.1f}\".format(end-start))" ], "execution_count": 0, "outputs": [] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "KKox7K46tKxy" }, "source": [ "---\n", "\n", "### Végül mentsük az eredményünket\n", "\n", "---" ] }, { "cell_type": "code", "metadata": { "colab_type": "code", "id": "SSH6OpyyQn7w", "colab": {} }, "source": [ "file_name = 'stylized-sas.png'\n", "tensor_to_image(image).save(file_name)\n", "\n", "try:\n", " from google.colab import files\n", "except ImportError:\n", " pass\n", "else:\n", " files.download(file_name)" ], "execution_count": 0, "outputs": [] } ] }