├── nnetart ├── __init__.py ├── network.py └── artgen.py ├── nn.png ├── .gitignore ├── results ├── deepRGB.png ├── verydeepRGB.png ├── BW_generated1.png ├── BW_generated2.png ├── BW_generated3.png ├── BW_generated4.png ├── BW_generated5.png ├── CMYK_generated1.png ├── CMYK_generated2.png ├── CMYK_generated3.png ├── CMYK_generated4.png ├── CMYK_generated5.png ├── HSL_generated1.png ├── HSL_generated2.png ├── HSL_generated3.png ├── HSL_generated4.png ├── HSL_generated5.png ├── HSV_generated1.png ├── HSV_generated2.png ├── HSV_generated3.png ├── HSV_generated4.png ├── HSV_generated5.png ├── RGB_generated1.png ├── RGB_generated10.png ├── RGB_generated2.png ├── RGB_generated3.png ├── RGB_generated4.png ├── RGB_generated5.png ├── RGB_generated6.png ├── RGB_generated7.png ├── RGB_generated8.png └── RGB_generated9.png ├── nb_output ├── generated_bw_3.png ├── generated_bw_6.png ├── generated_bw_7.png ├── generated_bw_9.png ├── generated_hsl_5.png ├── generated_hsl_8.png ├── generated_hsv_1.png ├── generated_rgb_2.png ├── generated_rgb_4.png └── generated_cmyk_10.png ├── setup.py ├── LICENSE ├── README.md └── random_art.py /nnetart/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /nn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/nn.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | nnetart.egg-info/* 2 | 3 | results/ 4 | 5 | .DS_Store 6 | .idea/* 7 | 8 | nnetart/__pycache__/* -------------------------------------------------------------------------------- /results/deepRGB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/results/deepRGB.png -------------------------------------------------------------------------------- /results/verydeepRGB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/results/verydeepRGB.png -------------------------------------------------------------------------------- /results/BW_generated1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/results/BW_generated1.png -------------------------------------------------------------------------------- /results/BW_generated2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/results/BW_generated2.png -------------------------------------------------------------------------------- /results/BW_generated3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/results/BW_generated3.png -------------------------------------------------------------------------------- /results/BW_generated4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/results/BW_generated4.png -------------------------------------------------------------------------------- /results/BW_generated5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/results/BW_generated5.png -------------------------------------------------------------------------------- /nb_output/generated_bw_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/nb_output/generated_bw_3.png -------------------------------------------------------------------------------- /nb_output/generated_bw_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/nb_output/generated_bw_6.png -------------------------------------------------------------------------------- /nb_output/generated_bw_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/nb_output/generated_bw_7.png -------------------------------------------------------------------------------- /nb_output/generated_bw_9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/nb_output/generated_bw_9.png -------------------------------------------------------------------------------- /results/CMYK_generated1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/results/CMYK_generated1.png -------------------------------------------------------------------------------- /results/CMYK_generated2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/results/CMYK_generated2.png -------------------------------------------------------------------------------- /results/CMYK_generated3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/results/CMYK_generated3.png -------------------------------------------------------------------------------- /results/CMYK_generated4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/results/CMYK_generated4.png -------------------------------------------------------------------------------- /results/CMYK_generated5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/results/CMYK_generated5.png -------------------------------------------------------------------------------- /results/HSL_generated1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/results/HSL_generated1.png -------------------------------------------------------------------------------- /results/HSL_generated2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/results/HSL_generated2.png -------------------------------------------------------------------------------- /results/HSL_generated3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/results/HSL_generated3.png -------------------------------------------------------------------------------- /results/HSL_generated4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/results/HSL_generated4.png -------------------------------------------------------------------------------- /results/HSL_generated5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/results/HSL_generated5.png -------------------------------------------------------------------------------- /results/HSV_generated1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/results/HSV_generated1.png -------------------------------------------------------------------------------- /results/HSV_generated2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/results/HSV_generated2.png -------------------------------------------------------------------------------- /results/HSV_generated3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/results/HSV_generated3.png -------------------------------------------------------------------------------- /results/HSV_generated4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/results/HSV_generated4.png -------------------------------------------------------------------------------- /results/HSV_generated5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/results/HSV_generated5.png -------------------------------------------------------------------------------- /results/RGB_generated1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/results/RGB_generated1.png -------------------------------------------------------------------------------- /results/RGB_generated10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/results/RGB_generated10.png -------------------------------------------------------------------------------- /results/RGB_generated2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/results/RGB_generated2.png -------------------------------------------------------------------------------- /results/RGB_generated3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/results/RGB_generated3.png -------------------------------------------------------------------------------- /results/RGB_generated4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/results/RGB_generated4.png -------------------------------------------------------------------------------- /results/RGB_generated5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/results/RGB_generated5.png -------------------------------------------------------------------------------- /results/RGB_generated6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/results/RGB_generated6.png -------------------------------------------------------------------------------- /results/RGB_generated7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/results/RGB_generated7.png -------------------------------------------------------------------------------- /results/RGB_generated8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/results/RGB_generated8.png -------------------------------------------------------------------------------- /results/RGB_generated9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/results/RGB_generated9.png -------------------------------------------------------------------------------- /nb_output/generated_hsl_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/nb_output/generated_hsl_5.png -------------------------------------------------------------------------------- /nb_output/generated_hsl_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/nb_output/generated_hsl_8.png -------------------------------------------------------------------------------- /nb_output/generated_hsv_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/nb_output/generated_hsv_1.png -------------------------------------------------------------------------------- /nb_output/generated_rgb_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/nb_output/generated_rgb_2.png -------------------------------------------------------------------------------- /nb_output/generated_rgb_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/nb_output/generated_rgb_4.png -------------------------------------------------------------------------------- /nb_output/generated_cmyk_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanle618/neural-net-random-art/HEAD/nb_output/generated_cmyk_10.png -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | 3 | setup( 4 | name='nnetart', 5 | version='0.1', 6 | description='Generate random art with neural networks', 7 | author='Tuan Le', 8 | author_email='tuanle@hotmail.de', 9 | packages=find_packages(), install_requires=['torch', 'numpy', 'matplotlib', 'typing', 'seaborn'] 10 | ) 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Tuan Le 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /nnetart/network.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @title: random_art.py 4 | @author: Tuan Le 5 | @email: tuanle@hotmail.de 6 | 7 | Implements a simple feed-forward neural network 8 | """ 9 | 10 | import torch 11 | import torch.nn as nn 12 | 13 | from typing import List 14 | 15 | 16 | def weights_init_normal(m: nn.Module): 17 | """ 18 | Change the standard deviations for the weight-attribute if you wanna experiment further. 19 | """ 20 | classname = m.__class__.__name__ 21 | if classname.find('Linear') != -1: 22 | m.weight.data.normal_(0.0, 1.0) 23 | m.bias.data.normal_(0.0, 0.1) 24 | return None 25 | 26 | 27 | def init_activation_fnc(a): 28 | if a == "tanh": 29 | return nn.Tanh() 30 | elif a == "sigmoid": 31 | return nn.Sigmoid() 32 | elif a == "relu": 33 | return nn.ReLU() 34 | elif a == "softsign": 35 | return nn.Softsign() 36 | elif a == "sin": 37 | return torch.sin 38 | elif a == "cos": 39 | return torch.cos 40 | else: 41 | print(f"Inserted activation function {a} not compatible. Using tanh.") 42 | return nn.Tanh() 43 | 44 | 45 | class FeedForwardNetwork(nn.Module): 46 | def __init__(self, 47 | layers_dims: List = [10, 10, 10, 10, 10], 48 | activation_fnc: str = "tanh", 49 | colormode: str = "rgb", 50 | alpha: bool = True): 51 | super(FeedForwardNetwork, self).__init__() 52 | colormode = colormode.lower() 53 | if colormode in ["rgb", "hsv", "hsl"]: 54 | if not alpha: 55 | out_nodes = 3 56 | else: 57 | out_nodes = 4 58 | elif colormode == "cmyk": 59 | if not alpha: 60 | out_nodes = 4 61 | else: 62 | out_nodes = 5 63 | elif colormode == "bw": 64 | if not alpha: 65 | out_nodes = 1 66 | else: 67 | out_nodes = 2 68 | else: 69 | print(f"wrong colormode {colormode} inserted in Neural Net. initialization.") 70 | raise ValueError 71 | input_layer = nn.Linear(in_features=5, out_features=layers_dims[0], bias=True) 72 | output_layer = nn.Linear(in_features=layers_dims[-1], out_features=out_nodes, bias=True) 73 | self.layers = nn.ModuleList([input_layer] + 74 | [nn.Linear(in_features=layers_dims[i], 75 | out_features=layers_dims[i+1], bias=True) 76 | for i in range(len(layers_dims)-1)] + 77 | [output_layer] 78 | ) 79 | self.activation = init_activation_fnc(activation_fnc.lower()) 80 | self.apply(weights_init_normal) 81 | 82 | def forward(self, x: torch.Tensor) -> torch.Tensor: 83 | out = x 84 | for i, m in enumerate(self.layers): 85 | out = m(out) 86 | if i < len(self.layers)-1: 87 | out = self.activation(out) 88 | else: 89 | out = torch.sigmoid(out) 90 | return out -------------------------------------------------------------------------------- /nnetart/artgen.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @title: random_art.py 4 | @author: Tuan Le 5 | @email: tuanle@hotmail.de 6 | 7 | Minimal image pre-processing script 8 | """ 9 | 10 | import numpy as np 11 | import torch 12 | import multiprocessing as mp 13 | from multiprocessing import Pool 14 | 15 | 16 | def process_xy_el_meshgrid(xv: np.ndarray, 17 | yv: np.ndarray, 18 | symmetry: bool, 19 | trig: bool, 20 | z1: float, 21 | z2: float) -> torch.Tensor: 22 | """ 23 | Transforms the input tuple (x,y) 24 | Args: 25 | xv: numpy array (width, height) 26 | yv: (width, height) 27 | symmetry: boolean, if x and y should be symmetric, i.e. squaring the tuple elements 28 | trig: if the input tuples should be transformed using the cosine and sine function. Note this returns more 29 | variability, for the z1 and z2 values, respectively. 30 | z1: deterministic factor z1, if trig is set to False. 31 | z2: deterministic factor z2, if trig is set to False. 32 | 33 | Returns: np.array with 5 columns, for the values x,y,r,z1,z2 34 | """ 35 | # radius part r 36 | if symmetry: 37 | xv = xv**2 38 | yv = yv**2 39 | r_ = np.sqrt(xv**2 + yv**2) 40 | # z1, z2 part 41 | if trig: 42 | z1_ = np.cos(z1*xv) 43 | z2_ = np.sin(z2*yv) 44 | else: 45 | z1_ = np.empty_like(xv, dtype=np.float32) 46 | z1_.fill(z1) 47 | z2_ = np.empty_like(yv, dtype=np.float32) 48 | z2_.fill(z2) 49 | 50 | x_ = np.expand_dims(xv.T.flatten(), axis=1) 51 | y_ = np.expand_dims(yv.T.flatten(), axis=1) 52 | r_ = np.expand_dims(r_.T.flatten(), axis=1) 53 | z1_ = np.expand_dims(z1_.T.flatten(), axis=1) 54 | z2_ = np.expand_dims(z2_.T.flatten(), axis=1) 55 | 56 | # create flattened image 57 | res = np.concatenate([x_, y_, r_, z1_, z2_], axis=1) 58 | return torch.from_numpy(res).float() 59 | 60 | 61 | def init_data(img_height: int = 500, 62 | img_width: int = 700, 63 | symmetry: bool = False, 64 | trig: bool = True, 65 | z1: float = -0.618, z2: float = 0.618, 66 | noise: float = False, 67 | noise_std: float = 0.01): 68 | factor = min(img_height, img_width) 69 | # get input: x,y,r,z_1,z_2 70 | x = [(i/factor-0.5)*2 for i in range(img_height)] 71 | y = [(j/factor-0.5)*2 for j in range(img_width)] 72 | 73 | xv, yv = np.meshgrid(x, y) 74 | in_data = process_xy_el_meshgrid(xv, yv, symmetry, trig, z1, z2) 75 | if noise: 76 | in_data += torch.zeros_like(in_data).normal_(mean=0, std=noise_std) 77 | return in_data 78 | 79 | 80 | def hsv_to_rgb(h, s, v): 81 | # hsw are between 0 and 1 82 | # returns rgb between 0 and 1 83 | # from: https://bgrins.github.io/TinyColor/docs/tinycolor.html 84 | h *= 6 85 | i = np.floor(h) 86 | f = h - i 87 | p = v * (1 - s) 88 | q = v * (1 - f * s) 89 | t = v * (1 - (1 - f) * s) 90 | mod = int(i % 6) 91 | r = [v, q, p, p, t, v][mod] 92 | g = [t, v, v, q, p, p][mod] 93 | b = [p, p, t, v, v, q][mod] 94 | return r, g, b 95 | 96 | 97 | def hsv_to_rgb_torch(img: torch.Tensor) -> torch.Tensor: 98 | # hsw are between 0 and 1 99 | # returns rgb between 0 and 1 100 | # from: https://bgrins.github.io/TinyColor/docs/tinycolor.html 101 | h_ = img[:, :, 0].view(img.size(0) * img.size(1)).detach().data.numpy() 102 | s_ = img[:, :, 1].view(img.size(0) * img.size(1)).detach().data.numpy() 103 | v_ = img[:, :, 2].view(img.size(0) * img.size(1)).detach().data.numpy() 104 | h = 6 * h_ 105 | i = np.floor(h) 106 | f = h - i 107 | p = (v_ * (1 - s_)) 108 | q = (v_ * (1 - f * s_)) 109 | t = (v_ * (1 - (1 - f) * s_)) 110 | mod = [int(a % 6) for a in i] 111 | r_select = torch.Tensor([[v_[i], q[i], p[i], p[i], t[i], v_[i]][m] for i, m in enumerate(mod)]).view(img.size(0), 112 | img.size( 113 | 1)).unsqueeze( 114 | -1) 115 | g_select = torch.Tensor([[t[i], v_[i], v_[i], q[i], p[i], p[i]][m] for i, m in enumerate(mod)]).view(img.size(0), 116 | img.size( 117 | 1)).unsqueeze( 118 | -1) 119 | b_select = torch.Tensor([[p[i], p[i], t[i], v_[i], v_[i], q[i]][m] for i, m in enumerate(mod)]).view(img.size(0), 120 | img.size( 121 | 1)).unsqueeze( 122 | -1) 123 | img = torch.cat([r_select, g_select, b_select], dim=-1) 124 | 125 | return img 126 | 127 | 128 | def hue_to_rgb(p, q, t): 129 | if t < 0 or t > 1: 130 | return p 131 | if t < 1 / 6: 132 | return p + (q - p) * 6 * t 133 | if t < 1 / 2: 134 | return q 135 | if t < 2 / 3: 136 | return p + (q - p) * (2 / 3 - t) * 6 137 | else: 138 | return p 139 | 140 | 141 | def hsl_to_rgb(h, s, l): 142 | # hsl are between 0 and 1 143 | # returns rgb between 0 and 1 144 | if s == 0: 145 | r = g = b = l # achromatic 146 | else: 147 | if l < 0.5: 148 | q = l * (1 + s) 149 | else: 150 | q = l + s - l * s 151 | 152 | p = 2 * l - q 153 | r = hue_to_rgb(p, q, h + 1 / 3) 154 | g = hue_to_rgb(p, q, h) 155 | b = hue_to_rgb(p, q, h - 1 / 3) 156 | 157 | return r, g, b 158 | 159 | 160 | def hsl_to_rgb_torch(h: torch.Tensor, s: torch.Tensor, l: torch.Tensor): 161 | h = h.cpu().data.numpy() 162 | s = s.cpu().data.numpy() 163 | l = l.cpu().data.numpy() 164 | with Pool(processes=2) as pool: 165 | proc_img = pool.starmap(hsl_to_rgb, zip(h, s, l)) 166 | proc_img = torch.Tensor(proc_img) 167 | return proc_img 168 | 169 | 170 | def transform_colors(img: torch.Tensor, colormode: str, alpha: bool): 171 | if alpha: 172 | alpha_tensor = img[:, :, -1] 173 | # Since non blackmode [rgb, cmyk, hsv, hsl] values are mapped onto [0,1] the alpha channel is also between [0,1]. 174 | # 0=transparency, 1=opaque wrt. to overlaying 175 | a = 1 - torch.abs(2 * alpha_tensor - 1) 176 | a = (0.25 + 0.75 * a).unsqueeze(-1) 177 | else: 178 | a = torch.ones(size=(img.size(0), img.size(1))).unsqueeze(-1) 179 | 180 | if colormode == "rgb": # Output via sigmoid activation mapped into range [0,1] 181 | proc_img = img[:, :, 0:2] 182 | elif colormode == "bw": 183 | proc_img = torch.cat([img[:, :, 0].unsqueeze(-1)] * 3, dim=-1) 184 | elif colormode == "cmyk": 185 | r = ((1 - img[:, :, 0]) * img[:, :, 3]).unsqueeze(-1) 186 | g = ((1 - img[:, :, 1]) * img[:, :, 3]).unsqueeze(-1) 187 | b = ((1 - img[:, :, 2]) * img[:, :, 3]).unsqueeze(-1) 188 | proc_img = torch.cat([r, g, b], dim=-1).to(img.device) 189 | elif colormode == "hsv": 190 | proc_img = hsv_to_rgb_torch(img) 191 | elif colormode == "hsl": 192 | h = img[:, :, 0].view(img.size(0) * img.size(1)) 193 | s = img[:, :, 1].view(img.size(0) * img.size(1)) 194 | l = img[:, :, 2].view(img.size(0) * img.size(1)) 195 | proc_img = hsl_to_rgb_torch(h, s, l).to(img.device) 196 | proc_img = proc_img.view(img.size(0), img.size(1), 3) 197 | else: 198 | print("Inserted colormode '{}' is not part ob supported ones: [rgb, bw, cmyk, hsv, hsl]".format(colormode)) 199 | raise Exception("Non-supported colormode {}".format(colormode)) 200 | 201 | res = torch.cat([proc_img, a], dim=-1) 202 | 203 | return res -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # neural-net-random-art 2 | Create a grayscale or colour image with predefined size `img_height` and `img_width` using fully connected neural networks. 3 | The generation of images only requires python `numpy`, `torch` and `matplotlib`. 4 | Medium article can be found [here](https://medium.com/@tuanle618/generate-abstract-random-art-with-a-neural-network-ecef26f3dd5f). 5 | # Usage 6 | You can either have a look at the jupyter notebook [nb_random_art.ipynb](https://github.com/tuanle618/neural-net-random-art/blob/master/nb_random_art.ipynb) if you want to understand the algorithm and check out several settings of the method. 7 | For fast image generation is is recommended to use the python main programm file [random_art.py](https://github.com/tuanle618/neural-net-random-art/blob/master/random_art.py) 8 | 9 | # Using Google Colab 10 | I've created a minimal working example on Google Colab here [here](https://colab.research.google.com/drive/1TFmQQOUHOPjSrB0dVeoYiD7d7FPidilW?usp=sharing) in case you want to experiment with this library a little bit, prior to installing it on your local machine. 11 | To generate an animation by applying small gradual changes in the neural net when generating consecutive new images, check out this [notebook](https://colab.research.google.com/drive/1Jdmvh72NsQlb0GdXdhgBDMfiNm5Q8WUe?usp=sharing). 12 | 13 | # Dependencies: Python 3 14 | ``` 15 | numpy 16 | matplotlib 17 | seaborn 18 | torch 19 | ``` 20 | 21 | # Installation 22 | ``` 23 | git clone https://github.com/tuanle618/neural-net-random-art.git 24 | cd neural-net-random-art 25 | pip install -e . 26 | ``` 27 | 28 | # Execution 29 | 30 | For the `random_art.py` program `argparse` is used to define several input parameters: 31 | ```python 3 32 | parser = argparse.ArgumentParser(description="Generate random art with a deep neural network") 33 | 34 | parser.add_argument("-img_height", metavar="", type=int, default=512, 35 | help="Image height of created random art. Default is 512") 36 | 37 | parser.add_argument("-img_width", metavar="", type=int, default=512, 38 | help="Image width of created random art. Default is 512") 39 | 40 | parser.add_argument("-colormode", metavar="", type=str, default="rgb", 41 | help="How image color should be generated. Options are ['bw', 'rgb', 'cmyk', 'hsv', 'hsl']." 42 | " By default this value is 'rgb'") 43 | 44 | parser.add_argument("-alpha", metavar="", type=str, default="False", 45 | help="Whether or not to add a alpha channel for the image. Default is False") 46 | 47 | parser.add_argument("-n_images", metavar="", type=int, default=1, 48 | help="Number of images to generate. Default is 1") 49 | 50 | parser.add_argument("-n_depth", metavar="", type=int, default=5, 51 | help="Number of layers for the neural network. Default is 5") 52 | 53 | parser.add_argument("-n_size", metavar="", type=int, default=10, 54 | help="Number of neurons in each hidden layer. Default is 10") 55 | 56 | parser.add_argument("-activation", metavar="", type=str, default="tanh", 57 | help="Activation function to apply on the hidden layers. Default is 'tanh'") 58 | 59 | parser.add_argument("-z1", metavar="", type=float, default=-0.618, 60 | help="Input variable 1 to insert determinism into the random art." 61 | " The value should be between -1 and 1. Default is -0.618") 62 | 63 | parser.add_argument("-z2", metavar="", type=float, default=+0.618, 64 | help="Input variable 2 to insert determinism into the random art." 65 | " The value should be between -1 and 1. Default is +0.618") 66 | 67 | parser.add_argument("-trig", metavar="", type=str, default="True", 68 | help="If the z1 and z2 values should be transformed with cosine and sine respectively. " 69 | "Defaults to True.") 70 | 71 | parser.add_argument("-noise", metavar="", type=str, default="False", 72 | help="If gaussian noise should be added for the generated image. Defaults to False") 73 | 74 | parser.add_argument("-noise_std", metavar="", type=float, default=0.01, 75 | help="Gaussian noise standard deviation if it should be added to the generated image. " 76 | " Defaults to 0.01.") 77 | 78 | parser.add_argument("-sym", metavar="", type=str, default="False", 79 | help="Use symmetry network. Default is False") 80 | 81 | parser.add_argument("-gpu", metavar="", type=str, default="False", 82 | help="Use GPU to generate (vectorized) image. Defaults to False") 83 | 84 | parser.add_argument("-format", metavar="", type=str, default="png", 85 | help="File format to save the images. Defaults to 'png'." 86 | "Choices are 'pnd', 'jpg', 'pdf' and 'svg'.", 87 | choices=['png', 'jpg', 'svg', 'pdf'] 88 | ) 89 | ``` 90 | 91 | So in order to create 1 RGB image of size 400x500, no alpha channel, a dense net with 15 layers, each laying having 15 neurons, type in following command in the shell: 92 | 93 | ` 94 | python random_art.py -img_height 400 -img_width 500 -colormode rgb -alpha False -n_images 1 -n_depth 15 -n_size 15 95 | ` 96 | 97 | # Examples 98 | Following commands were used [default params were used] to get the images stored in the [result subdirectory](https://github.com/tuanle618/neural-net-random-art/tree/master/results): 99 | ``` 100 | python random_art.py -img_height 512 -image_width 512 -colormode bw -alpha False -n_images 5 101 | ``` 102 | E.g, leading to following 2 random images (resized in order to have next to each other): 103 |
104 |
105 |
106 |
114 |
115 |
116 |
124 |
125 |
126 |
134 |
135 |
136 |
144 |
145 |
146 |
152 |
153 |
154 |