{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"accelerator": "GPU",
"colab": {
"name": "kl_py_img_style_transfer.ipynb",
"provenance": [],
"private_outputs": true,
"collapsed_sections": [],
"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": [
""
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "6msVLevwcRhm"
},
"source": [
"# AI képek átalakítása tensorflow-val"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "aDyGj8DmXCJI"
},
"source": [
"## Ez az oktatóprogram mélyreható 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",
"\n",
"### Minta forrása:\n",
"https://www.tensorflow.org/tutorials/generative/style_transfer\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "3kb_UJY-jCEl"
},
"source": [
"Kiinduló kép egy mokus a farönkön\n",
"\n",
"\n",
"Eredmény stilus kép mokus:\n",
"\n",
"\n",
"---\n",
"\n",
"Stilus kép:\n",
"\n",
"\n",
"---\n",
"\n",
"Kiinduló kép egy sas az égen\n",
"\n",
"\n",
"Eredmény stilus kép sas:\n",
"\n",
"\n",
"---\n",
"\n",
"Kiinduló kép egy delfin\n",
"\n",
"\n",
"Eredmény stilus kép delfin:\n",
""
]
},
{
"cell_type": "markdown",
"metadata": {
"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": "La3tSULDFye1"
},
"source": [
"from __future__ import absolute_import, division, print_function, unicode_literals"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "60hVzGbjF23a"
},
"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__)"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "HwZIrdfgF_9k"
},
"source": [
"## képállományok elérése a WEB -en\n",
"## mokus\n",
"# content_path = tf.keras.utils.get_file('forras_kep.jpg', r'https://1.bp.blogspot.com/-1xfgXDl6mYQ/XmIwnys8MDI/AAAAAAAAaFw/16mXksGvTiE3kgdXzU4LTNkM9YVnbvHXwCLcBGAsYHQ/s320/FB_IMG_1580926207371.jpg')\n",
"## sas\n",
"# content_path = tf.keras.utils.get_file('forras2_kep.jpg', r'https://1.bp.blogspot.com/-WaDe31Qr3yg/XmIwn8KKNcI/AAAAAAAAaGE/OZaPJcax2-4_kwUZ8iguZRASS5W7Ycr_gCPcBGAYYCw/s1600/FB_IMG_1581224344102.jpg')\n",
"# delfin\n",
"content_path = tf.keras.utils.get_file('forras7_kep.jpg', r'https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8PlWVdYoFJ6LZB2VR8jP0ciLrFO-nTorhftc8UAcTkrjAfsABYZmbc9qrDfiQhW7rBvlzC40kWuOxXl9zx5bI6uFey4YBLQHqzR9vJdp2ENQUXpUQ2KusYHtk3tzd3BnSuOAKPlzQdaeg1VoCi8SupExVcwNiCP7y3CQUfLqRAaPMJyBUn--3bXiD/s550/kl_en2.jpg')\n",
"## stilus\n",
"style_path = tf.keras.utils.get_file('cel_kep14.jpg', r'https://cdn.nwmgroups.hu/s/img/i/1412/20141222ai-mi-mesterseges-inteligencia-artificial3.jpg')\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "3TLljcwv5qZs"
},
"source": [
"## 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",
"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": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "_UWQmeEaiKkP"
},
"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": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"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": {
"id": "du6mqYbVgGcW"
},
"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": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "iYSLexgRKSh-"
},
"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') ## újjabb verzio\n",
"stylized_image = hub_module(tf.constant(content_image), tf.constant(style_image))[0]\n",
"tensor_to_image(stylized_image)"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"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": {
"id": "fMbzrr7BCTq0"
},
"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": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "1_FyCm0dYnvl"
},
"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": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "Yh_AV6220ebD"
},
"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": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "Wt-tASys0eJv"
},
"source": [
"Choose intermediate layers from the network to represent the style and content of the image:\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "ArfX_6iA0WAX"
},
"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": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"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": {
"id": "nfec6MuMAbPx"
},
"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": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "LkyvPpBHSfVi"
},
"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": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"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": {
"id": "HAy1iGPdoEpZ"
},
"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": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"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": {
"id": "Sr6QALY-I1ja"
},
"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": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"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": {
"id": "rkjO-DoNDU0A"
},
"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": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "kdgpTJwL_vE2"
},
"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": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "0ggx2Na8oROH"
},
"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": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "0t0umkajFIuh"
},
"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": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"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": {
"id": "Y542mxi-O2a2"
},
"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": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"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": {
"id": "rQW1tXYoLbUS"
},
"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": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"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": {
"id": "7szUUybCQMB3"
},
"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": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "Atc2oL29PXu_"
},
"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": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"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": {
"id": "HyvqCiywiUfL"
},
"source": [
"plt.figure(figsize=(14,10))\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": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "vv5bKlSDnPP7"
},
"source": [
"The regularization loss associated with this is the sum of the squares of the values:"
]
},
{
"cell_type": "code",
"metadata": {
"id": "mP-92lXMIYPn"
},
"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": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "nTessd-DCdcC"
},
"source": [
"## Optimalizáció ujra futtatása\n",
"\n",
"Válasszon súlyt `total_variation_loss`:"
]
},
{
"cell_type": "code",
"metadata": {
"id": "BzmfcyyYUyWq"
},
"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": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "q3Cc3bLtoOWy"
},
"source": [
"import time\n",
"start = time.time()\n",
"\n",
"epochs = 10\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": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "KKox7K46tKxy"
},
"source": [
"---\n",
"\n",
"## végül mentsuk az eredményünket\n",
"\n",
"---"
]
},
{
"cell_type": "code",
"metadata": {
"id": "SSH6OpyyQn7w"
},
"source": [
"file_name = 'stylized-mokus.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": null,
"outputs": []
}
]
}