├── README.md ├── acwgangp.py ├── change_colors_to_words.py ├── environment.yml ├── get_colors.py ├── main.py ├── make_confusion_matrix.py ├── ops.py ├── read_images.py └── utils.py /README.md: -------------------------------------------------------------------------------- 1 | # LoGAN user guide 2 | 3 | This README will explain how to set-up and run the code for LoGAN: Generating Logos with a Generative Adversarial Neural Network Conditioned on Colour. 4 | 5 | # Getting the data and Training the model 6 | 7 | - Download LLD-Icons PNG files from: https://data.vision.ee.ethz.ch/sagea/lld/data/LLD-icon_PNG.zip 8 | - Set up a Python 3.5 environment with the packages mentioned below 9 | - Run get_colors.py (change the PATH variable to main directory) 10 | - In your current directory a file 'colors.csv' will be created with 3 columns (name of file, top 3 colors in file, amount of each of the top 3 colors) 11 | - Run change_colors_to_words.py (change path variable to main directory) 12 | - A one hot encoding of the colors extracetd previously will be created in the data folder 13 | - Change the path of the data and the one-hot-encoding csv on read_images.py 14 | - Run main.py 15 | 16 | # Overview of the files 17 | 18 | | File | Function | Parameters 19 | | ------ | ------ |------ | 20 | |get_colors.py| Uses the logos to find RGB centroids for the KMeans clusters for each image (output:colors.csv)| PATH - of working directory, TRAINING - true in training mode, VERBOSE - wether to print details | 21 | |change_colors_to_words.py | Uses colors.csv to create a one-hot-encoding for the labels (output:one_hot_encoding_color_icon.csv) | PATH - of working directory, TRAINING - true in training mode, VERBOSE - wether to print details 22 | | acgan.py | The class of the ACGAN | 23 | | main.py | The main class. Use this to start training the model and tweak the parameters. | gan_type - only ACWGANGP, dataset - only available dataset lld, epoch - number of epochs to train, batch_size - size of batch to train, z_dim - dimension of noise vector, checkpoint_dir-to save checkpoint, result_dir-directory to save results, log_dir-tensorboard log directory 24 | | ops.py | Defines the layers. | 25 | | utils.py| Defines useful functions. | 26 | | read_images.py| Defines two methods, to read images, and labels in one hot encoding format. | Data_PATH, label_csv_PATH, IMAGE_SIZE - size of the images, CATEGORIES - classes, BATCH_SIZE - size of batch, VERBOSE - wether to print details 27 | | make_confusion_matrix.py | Used to get the confusion matrix to get the results as in paper. | 28 | 29 | 30 | # Necessary packages 31 | Python 3.5 32 | tensorflow (1.4+) 33 | numpy (1.13.1 and 1.14.1) 34 | PIL (pillow) (5.1.0) 35 | pandas (0.20.3) 36 | webcolors (1.8.1) 37 | scikit-learn (0.19.0) 38 | matplotlib (2.12.2) 39 | cv2 (opencv-python) (3.4.0.12) 40 | 41 | -------------------------------------------------------------------------------- /acwgangp.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | ''' 4 | Most of the code from https://github.com/hwalsuklee/tensorflow-generative-model-collections/ 5 | ''' 6 | 7 | from __future__ import division 8 | import os 9 | import time 10 | import tensorflow as tf 11 | import numpy as np 12 | 13 | import sys 14 | 15 | from ops import * 16 | from utils import * 17 | 18 | class ACWGANGP(object): 19 | model_name = "ACWGANGP" # name for checkpoint 20 | 21 | def __init__(self, sess, epoch, batch_size, z_dim, dataset_name, checkpoint_dir, result_dir, log_dir): 22 | self.sess = sess 23 | self.dataset_name = dataset_name 24 | self.checkpoint_dir = checkpoint_dir 25 | self.result_dir = result_dir 26 | self.log_dir = log_dir 27 | self.epoch = epoch 28 | self.batch_size = batch_size 29 | 30 | # WGAN_GP parameters 31 | self.lambd = 0.25 # The higher value, the more stable, but the slower convergence 32 | self.disc_iters = 5 33 | 34 | if dataset_name == 'lld': 35 | # parameters 36 | self.input_height = 32 37 | self.input_width = 32 38 | self.output_height = 32 39 | self.output_width = 32 40 | 41 | self.z_dim = z_dim # dimension of noise-vector 42 | self.y_dim = 12 # dimension of code-vector (label) 43 | self.c_dim = 3 # number of channels 44 | 45 | # train with same parameters as paper 46 | self.learning_rate = 0.0001 47 | self.beta1 = 0.5 48 | self.beta2 = 0.9 49 | 50 | # test 51 | self.sample_num = 64 # number of generated images to be saved 52 | 53 | # code 54 | self.len_discrete_code = 12 # categorical distribution (i.e. label) 55 | self.len_continuous_code = 2 # gaussian distribution (e.g. rotation, thickness) 56 | 57 | # load data 58 | self.data_X, self.data_y = load_lld(self.dataset_name) 59 | 60 | # get number of batches for a single epoch 61 | self.num_batches = len(self.data_X) // self.batch_size 62 | else: 63 | raise NotImplementedError 64 | 65 | def classifier(self, x, is_training=True, reuse=False): 66 | # Network Architecture is exactly same as in infoGAN (https://arxiv.org/abs/1606.03657) 67 | # Architecture : (64)5c2s-(128)5c2s_BL-FC1024_BL-FC128_BL-FC12S’ 68 | # All layers except the last two layers are shared by discriminator 69 | with tf.variable_scope("classifier", reuse=reuse): 70 | 71 | net = lrelu(bn(linear(x, 128, scope='c_fc1'), is_training=is_training, scope='c_bn1')) 72 | out_logit = linear(net, self.y_dim, scope='c_fc2') 73 | out = tf.nn.softmax(out_logit) 74 | 75 | return out, out_logit 76 | 77 | def discriminator(self, x, is_training=True, reuse=False): 78 | # Network Architecture is exactly same as in infoGAN (https://arxiv.org/abs/1606.03657) 79 | # Architecture : (64)4c2s-(128)4c2s_BL-FC1024_BL-FC1_S 80 | with tf.variable_scope("discriminator", reuse=reuse): 81 | 82 | net = lrelu(conv2d(x, 64, 4, 4, 2, 2, name='d_conv1')) 83 | net = lrelu(bn(conv2d(net, 128, 4, 4, 2, 2, name='d_conv2'), is_training=is_training, scope='d_bn2')) 84 | net = tf.reshape(net, [self.batch_size, -1]) 85 | net = lrelu(bn(linear(net, 1024, scope='d_fc3'), is_training=is_training, scope='d_bn3')) 86 | out_logit = linear(net, 1, scope='d_fc4') 87 | out = tf.nn.sigmoid(out_logit) 88 | 89 | return out, out_logit, net 90 | 91 | def generator(self, z, y, is_training=True, reuse=False): 92 | # Network Architecture is exactly same as in infoGAN (https://arxiv.org/abs/1606.03657) 93 | # Architecture : FC1024_BR-FC7x7x128_BR-(64)4dc2s_BR-(1)4dc2s_S 94 | with tf.variable_scope("generator", reuse=reuse): 95 | 96 | # merge noise and code 97 | z = concat([z, y], 1) 98 | 99 | net = tf.nn.relu(bn(linear(z, 1024, scope='g_fc1'), is_training=is_training, scope='g_bn1')) 100 | net = tf.nn.relu(bn(linear(net, 128 * 8 * 8, scope='g_fc2'), is_training=is_training, scope='g_bn2')) 101 | net = tf.reshape(net, [self.batch_size, 8, 8, 128]) 102 | net = tf.nn.relu( 103 | bn(deconv2d(net, [self.batch_size, 16, 16, 64], 4, 4, 2, 2, name='g_dc3'), is_training=is_training, 104 | scope='g_bn3')) 105 | 106 | out = tf.nn.sigmoid(deconv2d(net, [self.batch_size, 32, 32, 3], 4, 4, 2, 2, name='g_dc4')) 107 | 108 | return out 109 | 110 | def build_model(self): 111 | # some parameters 112 | image_dims = [self.input_height, self.input_width, self.c_dim] 113 | bs = self.batch_size 114 | 115 | """ Graph Input """ 116 | # images 117 | self.inputs = tf.placeholder(tf.float32, [bs] + image_dims, name='real_images') 118 | 119 | # labels 120 | self.y = tf.placeholder(tf.float32, [bs, self.y_dim], name='y') 121 | 122 | # noises 123 | self.z = tf.placeholder(tf.float32, [bs, self.z_dim], name='z') 124 | 125 | """ Loss Function """ 126 | ## 1. GAN Loss 127 | # output of D for real images 128 | D_real, D_real_logits, input4classifier_real = self.discriminator(self.inputs, is_training=True, reuse=False) 129 | 130 | # output of D for fake images 131 | G = self.generator(self.z, self.y, is_training=True, reuse=False) 132 | D_fake, D_fake_logits, input4classifier_fake = self.discriminator(G, is_training=True, reuse=True) 133 | 134 | # get loss for discriminator 135 | d_loss_real = - tf.reduce_mean(D_real_logits) 136 | d_loss_fake = tf.reduce_mean(D_fake_logits) 137 | 138 | self.d_loss = d_loss_real + d_loss_fake 139 | 140 | # get loss for generator 141 | self.g_loss = - d_loss_fake 142 | 143 | ## 2. Information Loss 144 | code_fake, code_logit_fake = self.classifier(input4classifier_fake, is_training=True, reuse=False) 145 | code_real, code_logit_real = self.classifier(input4classifier_real, is_training=True, reuse=True) 146 | 147 | # For real samples 148 | q_real_loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=code_logit_real, labels=self.y)) 149 | 150 | # For fake samples 151 | q_fake_loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=code_logit_fake, labels=self.y)) 152 | 153 | # get information loss 154 | self.q_loss = q_fake_loss + q_real_loss 155 | 156 | 157 | """ Gradient Penalty """ 158 | # This is borrowed from https://github.com/kodalinaveen3/DRAGAN/blob/master/DRAGAN.ipynb 159 | alpha = tf.random_uniform(shape=self.inputs.get_shape(), minval=0.,maxval=1.) 160 | differences = G - self.inputs # This is different from MAGAN 161 | interpolates = self.inputs + (alpha * differences) 162 | _,D_inter,_=self.discriminator(interpolates, is_training=True, reuse=True) 163 | gradients = tf.gradients(D_inter, [interpolates])[0] 164 | slopes = tf.sqrt(tf.reduce_sum(tf.square(gradients), reduction_indices=[1])) 165 | gradient_penalty = tf.reduce_mean((slopes - 1.) ** 2) 166 | self.d_loss += self.lambd * gradient_penalty 167 | 168 | 169 | 170 | """ Training """ 171 | # divide trainable variables into a group for D and a group for G 172 | t_vars = tf.trainable_variables() 173 | d_vars = [var for var in t_vars if 'd_' in var.name] 174 | g_vars = [var for var in t_vars if 'g_' in var.name] 175 | q_vars = [var for var in t_vars if ('d_' in var.name) or ('c_' in var.name) or ('g_' in var.name)] 176 | 177 | # optimizers 178 | with tf.control_dependencies(tf.get_collection(tf.GraphKeys.UPDATE_OPS)): 179 | self.d_optim = tf.train.AdamOptimizer(learning_rate= self.learning_rate, beta1= self.beta1, beta2= self.beta2) \ 180 | .minimize(self.d_loss, var_list=d_vars) 181 | self.g_optim = tf.train.AdamOptimizer(learning_rate= self.learning_rate, beta1= self.beta1, beta2= self.beta2) \ 182 | .minimize(self.g_loss, var_list=g_vars) 183 | self.q_optim = tf.train.AdamOptimizer(learning_rate= self.learning_rate, beta1= self.beta1, beta2= self.beta2) \ 184 | .minimize(self.q_loss, var_list=q_vars) 185 | 186 | """" Testing """ 187 | # for test 188 | self.fake_images = self.generator(self.z, self.y, is_training=False, reuse=True) 189 | 190 | """ Summary """ 191 | d_loss_real_sum = tf.summary.scalar("d_loss_real", d_loss_real) 192 | d_loss_fake_sum = tf.summary.scalar("d_loss_fake", d_loss_fake) 193 | d_loss_sum = tf.summary.scalar("d_loss", self.d_loss) 194 | g_loss_sum = tf.summary.scalar("g_loss", self.g_loss) 195 | 196 | q_loss_sum = tf.summary.scalar("q_loss", self.q_loss) 197 | q_real_sum = tf.summary.scalar("q_real_loss", q_real_loss) 198 | q_fake_sum = tf.summary.scalar("q_fake_loss", q_fake_loss) 199 | 200 | # final summary operations 201 | self.g_sum = tf.summary.merge([d_loss_fake_sum, g_loss_sum]) 202 | self.d_sum = tf.summary.merge([d_loss_real_sum, d_loss_sum]) 203 | self.q_sum = tf.summary.merge([q_loss_sum, q_real_sum, q_fake_sum]) 204 | 205 | def train(self): 206 | 207 | # initialize all variables 208 | tf.global_variables_initializer().run() 209 | 210 | # graph inputs for visualize training results 211 | #self.sample_z = np.random.uniform(-1, 1, size=(self.batch_size, self.z_dim)) 212 | self.sample_z = np.random.normal(-1, 1, size=(self.batch_size, self.z_dim)) 213 | self.test_codes = self.data_y[0:self.batch_size] 214 | 215 | # saver to save model 216 | self.saver = tf.train.Saver() 217 | 218 | # summary writer 219 | self.writer = tf.summary.FileWriter(self.log_dir + '/' + self.model_name, self.sess.graph) 220 | 221 | # restore check-point if it exits 222 | could_load, checkpoint_counter = self.load(self.checkpoint_dir) 223 | if could_load: 224 | start_epoch = (int)(checkpoint_counter / self.num_batches) 225 | start_batch_id = checkpoint_counter - start_epoch * self.num_batches 226 | counter = checkpoint_counter 227 | print(" [*] Load SUCCESS") 228 | else: 229 | start_epoch = 0 230 | start_batch_id = 0 231 | counter = 1 232 | print(" [!] Load failed...") 233 | 234 | # loop for epoch 235 | start_time = time.time() 236 | for epoch in range(start_epoch, self.epoch): 237 | 238 | # get batch data 239 | for idx in range(start_batch_id, self.num_batches): 240 | batch_images = self.data_X[idx*self.batch_size:(idx+1)*self.batch_size] 241 | batch_codes = self.data_y[idx * self.batch_size:(idx + 1) * self.batch_size] 242 | 243 | #batch_z = np.random.uniform(-1, 1, [self.batch_size, self.z_dim]).astype(np.float32) 244 | batch_z = np.random.normal(-1, 1, [self.batch_size, self.z_dim]).astype(np.float32) 245 | 246 | # update D network 247 | _, summary_str, d_loss = self.sess.run([self.d_optim, self.d_sum, self.d_loss], 248 | feed_dict={self.inputs: batch_images, self.y: batch_codes, 249 | self.z: batch_z}) 250 | self.writer.add_summary(summary_str, counter) 251 | 252 | 253 | # update G & Q network 254 | if(counter-1) % self.disc_iters == 0: 255 | _, summary_str_g, g_loss, _, summary_str_q, q_loss = self.sess.run( 256 | [self.g_optim, self.g_sum, self.g_loss, self.q_optim, self.q_sum, self.q_loss], 257 | feed_dict={self.z: batch_z, self.y: batch_codes, self.inputs: batch_images}) 258 | self.writer.add_summary(summary_str_g, counter) 259 | self.writer.add_summary(summary_str_q, counter) 260 | sys.stdout.write("\rEpoch: [%2d] [%4d/%4d] time: %4.4f, d_loss: %.8f, g_loss: %.8f" \ 261 | % (epoch, idx, self.num_batches, time.time() - start_time, d_loss, g_loss)) 262 | sys.stdout.flush() 263 | # display training status 264 | counter += 1 265 | 266 | 267 | # save training results for every 2000 steps 268 | if np.mod(counter, 2000) == 0: 269 | samples = self.sess.run(self.fake_images, 270 | feed_dict={self.z: self.sample_z, self.y: self.test_codes}) 271 | tot_num_samples = min(self.sample_num, self.batch_size) 272 | manifold_h = int(np.floor(np.sqrt(tot_num_samples))) 273 | manifold_w = int(np.floor(np.sqrt(tot_num_samples))) 274 | save_images(samples[:manifold_h * manifold_w, :, :, :], [manifold_h, manifold_w], './' + check_folder( 275 | self.result_dir + '/' + self.model_dir) + '/' + self.model_name + '_train_{:02d}_{:04d}.png'.format( 276 | epoch, idx)) 277 | 278 | # After an epoch, start_batch_id is set to zero 279 | # non-zero value is only for the first epoch after loading pre-trained model 280 | start_batch_id = 0 281 | 282 | # save model 283 | self.save(self.checkpoint_dir, counter) 284 | 285 | # show temporal results 286 | self.visualize_results(epoch) 287 | 288 | # save model for final step 289 | self.save(self.checkpoint_dir, counter) 290 | 291 | def visualize_results(self, epoch): 292 | tot_num_samples = min(self.sample_num, self.batch_size) 293 | image_frame_dim = int(np.floor(np.sqrt(tot_num_samples))) 294 | 295 | # sample from a normal distribution 296 | z_sample = np.random.normal(-1, 1, size=(self.batch_size, self.z_dim)) 297 | 298 | # random noise, random discrete code, fixed continuous code 299 | y = np.random.choice(self.len_discrete_code, self.batch_size) 300 | y_one_hot = np.zeros((self.batch_size, self.y_dim)) 301 | y_one_hot[np.arange(self.batch_size), y] = 1 302 | 303 | samples = self.sess.run(self.fake_images, feed_dict={self.z: z_sample, self.y: y_one_hot}) 304 | 305 | save_images(samples[:image_frame_dim*image_frame_dim,:,:,:], [image_frame_dim, image_frame_dim], 306 | check_folder(self.result_dir + '/' + self.model_dir) + '/' + self.model_name + '_epoch%03d' % epoch + '_test_all_classes.png') 307 | 308 | """ specified condition, random noise """ 309 | n_styles = 10 # must be less than or equal to self.batch_size 310 | 311 | np.random.seed() 312 | si = np.random.choice(self.batch_size, n_styles) 313 | 314 | for l in range(self.len_discrete_code): 315 | y = np.zeros(self.batch_size, dtype=np.int64) + l 316 | y_one_hot = np.zeros((self.batch_size, self.y_dim)) 317 | y_one_hot[np.arange(self.batch_size), y] = 1 318 | 319 | samples = self.sess.run(self.fake_images, feed_dict={self.z: z_sample, self.y: y_one_hot}) 320 | save_images(samples[:image_frame_dim*image_frame_dim,:,:,:], [image_frame_dim, image_frame_dim], 321 | check_folder(self.result_dir + '/' + self.model_dir) + '/' + self.model_name + '_epoch%03d' % epoch + '_test_class_%d.png' % l) 322 | 323 | samples = samples[si, :, :, :] 324 | 325 | if l == 0: 326 | all_samples = samples 327 | else: 328 | all_samples = np.concatenate((all_samples, samples), axis=0) 329 | 330 | """ save merged images to check style-consistency """ 331 | canvas = np.zeros_like(all_samples) 332 | for s in range(n_styles): 333 | for c in range(self.len_discrete_code): 334 | canvas[s * self.len_discrete_code + c, :, :, :] = all_samples[c * n_styles + s, :, :, :] 335 | 336 | save_images(canvas, [n_styles, self.len_discrete_code], 337 | check_folder(self.result_dir + '/' + self.model_dir) + '/' + self.model_name + '_epoch%03d' % epoch + '_test_all_classes_style_by_style.png') 338 | 339 | @property 340 | def model_dir(self): 341 | return "{}_{}_{}_{}".format( 342 | self.model_name, self.dataset_name, 343 | self.batch_size, self.z_dim) 344 | 345 | def save(self, checkpoint_dir, step): 346 | checkpoint_dir = os.path.join(checkpoint_dir, self.model_dir, self.model_name) 347 | 348 | if not os.path.exists(checkpoint_dir): 349 | os.makedirs(checkpoint_dir) 350 | 351 | self.saver.save(self.sess,os.path.join(checkpoint_dir, self.model_name+'.model'), global_step=step) 352 | 353 | def load(self, checkpoint_dir): 354 | import re 355 | print(" [*] Reading checkpoints...") 356 | checkpoint_dir = os.path.join(checkpoint_dir, self.model_dir, self.model_name) 357 | 358 | ckpt = tf.train.get_checkpoint_state(checkpoint_dir) 359 | if ckpt and ckpt.model_checkpoint_path: 360 | ckpt_name = os.path.basename(ckpt.model_checkpoint_path) 361 | self.saver.restore(self.sess, os.path.join(checkpoint_dir, ckpt_name)) 362 | counter = int(next(re.finditer("(\d+)(?!.*\d)",ckpt_name)).group(0)) 363 | print(" [*] Success to read {}".format(ckpt_name)) 364 | return True, counter 365 | else: 366 | print(" [*] Failed to find a checkpoint") 367 | return False, 0 -------------------------------------------------------------------------------- /change_colors_to_words.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import os 3 | import sys 4 | import re 5 | import pandas as pd 6 | import webcolors 7 | 8 | PATH = 'C:\\Code\\Thesis\\LoGAN\\' 9 | TRAINING = True 10 | VERBOSE = True 11 | 12 | if TRAINING: 13 | folders = ['data'] 14 | else: 15 | folders = ['green', 'purple', 'white', 'brown', 'blue', 'cyan', 'yellow', 'gray', 'red', 'pink', 'orange', 'black'] 16 | PATH = PATH + 'results\\' 17 | 18 | 19 | os.chdir(PATH) 20 | 21 | def closest_colour(requested_colour): 22 | min_colours = {} 23 | for key, name in webcolors.css3_hex_to_names.items(): 24 | r_c, g_c, b_c = webcolors.hex_to_rgb(key) 25 | rd = (r_c - requested_colour[0]) ** 2 26 | gd = (g_c - requested_colour[1]) ** 2 27 | bd = (b_c - requested_colour[2]) ** 2 28 | min_colours[(rd + gd + bd)] = name 29 | return min_colours[min(min_colours.keys())] 30 | 31 | def get_colour_name(requested_colour): 32 | try: 33 | closest_name = webcolors.rgb_to_name(requested_colour) 34 | except ValueError: 35 | closest_name = closest_colour(requested_colour) 36 | return closest_name 37 | 38 | def get_shade(color_name): 39 | 40 | if color_name == 'darkolivegreen' or color_name == 'olive' or color_name == 'olivedrab' or color_name == 'yellowgreen' or color_name == 'limegreen' or color_name == 'lime' or color_name == 'lawngreen' or color_name == 'chartreuse' or color_name == 'greenyellow' or color_name == 'springgreen' or color_name == 'mediumspringgreen' or color_name == 'lightgreen' or color_name == 'palegreen' or color_name == 'darkseagreen' or color_name == 'mediumaquamarine' or color_name == 'mediumseagreen' or color_name == 'seagreen' or color_name == 'forestgreen' or color_name == 'green' or color_name == 'darkgreen': 41 | shade = 'green' 42 | 43 | elif color_name == 'lavender' or color_name == 'thistle' or color_name == 'plum' or color_name == 'violet' or color_name == 'orchid' or color_name == 'fuchsia' or color_name == 'magenta' or color_name == 'mediumorchid' or color_name == 'mediumpurple' or color_name == 'blueviolet' or color_name == 'darkviolet' or color_name == 'darkorchid' or color_name == 'darkmagenta' or color_name == 'purple' or color_name == 'indigo' or color_name == 'darkslateblue' or color_name == 'slateblue' or color_name == 'mediumslateblue': 44 | shade = 'purple' 45 | 46 | elif color_name == 'white' or color_name == 'snow' or color_name == 'honeydew' or color_name == 'mintcream' or color_name == 'azure' or color_name == 'aliceblue' or color_name == 'ghostwhite' or color_name == 'whitesmoke' or color_name == 'seashell' or color_name == 'beige' or color_name == 'oldlace' or color_name == 'floralwhite' or color_name == 'ivory' or color_name == 'aquawhite' or color_name == 'linen' or color_name == 'lavenderblush' or color_name == 'mistyrose' or color_name == 'antiquewhite': 47 | shade = 'white' 48 | 49 | elif color_name == 'cornsilk' or color_name == 'blanchedalmond' or color_name == 'bisque' or color_name == 'navajowhite' or color_name == 'wheat' or color_name == 'burlywood' or color_name == 'tan' or color_name == 'rosybrown' or color_name == 'sandybrown' or color_name == 'goldenrod' or color_name == 'darkgoldenrod' or color_name == 'peru' or color_name == 'chocolate' or color_name == 'saddlebrown' or color_name == 'sienna' or color_name == 'brown' or color_name == 'maroon': 50 | shade = 'brown' 51 | 52 | elif color_name == 'lightsteelblue' or color_name == 'powderblue' or color_name == 'lightblue' or color_name == 'skyblue' or color_name == 'lightskyblue' or color_name == 'deepskyblue' or color_name == 'dodgerblue' or color_name == 'cornflowerblue' or color_name == 'steelblue' or color_name == 'royalblue' or color_name == 'blue' or color_name == 'mediumblue' or color_name == 'darkblue' or color_name == 'navy' or color_name == 'midnightblue': 53 | shade = 'blue' 54 | 55 | elif color_name == 'aqua' or color_name == 'cyan' or color_name == 'lightcyan' or color_name == 'paleturquoise' or color_name == 'aquamarine' or color_name == 'turquoise' or color_name == 'mediumturquoise' or color_name == 'darkturquoise' or color_name == 'lightseagreen' or color_name == 'cadetblue' or color_name == 'darkcyan' or color_name == 'teal': 56 | shade = 'cyan' 57 | 58 | elif color_name == 'yellow' or color_name == 'lightyellow' or color_name == 'lemonchiffon' or color_name == 'lightgoldenrodyellow' or color_name == 'papayawhip' or color_name == 'moccasin' or color_name == 'peachpuff' or color_name == 'palegoldenrod' or color_name == 'khaki' or color_name == 'darkkhaki' or color_name == 'gold': 59 | shade = 'yellow' 60 | 61 | elif color_name == 'gainsboro' or color_name == 'lightgrey' or color_name == 'silver' or color_name == 'darkgrey' or color_name == 'grey' or color_name == 'dimgrey' or color_name == 'lightslategrey' or color_name == 'darkslategrey' or color_name == 'slategrey': 62 | shade = 'gray' 63 | 64 | elif color_name == 'lightgray' or color_name == 'darkgray' or color_name == 'gray' or color_name == 'dimgray' or color_name == 'lightslategray' or color_name == 'darkslategray' or color_name == 'slategray': 65 | shade = 'gray' 66 | 67 | elif color_name == 'lightsalmon' or color_name == 'salmon' or color_name == 'darksalmon' or color_name == 'lightcoral' or color_name == 'indianred' or color_name == 'crimson' or color_name == 'firebrick' or color_name == 'darkred' or color_name == 'red' : 68 | shade = 'red' 69 | 70 | elif color_name == 'pink' or color_name == 'lightpink' or color_name == 'hotpink' or color_name == 'deeppink' or color_name == 'palevioletred' or color_name == 'mediumvioletred': 71 | shade = 'pink' 72 | 73 | elif color_name == 'orangered' or color_name == 'tomato' or color_name == 'coral' or color_name == 'darkorange' or color_name == 'orange': 74 | shade = 'orange' 75 | 76 | elif color_name == 'black': 77 | shade = 'black' 78 | 79 | else: 80 | shade = 'unknown' 81 | 82 | return shade 83 | 84 | 85 | def one_hot_encode(data, folder): 86 | one_hot_encoding = pd.DataFrame(columns = ['image','green', 'purple', 'white', 'brown', 'blue', 'cyan', 'yellow', 'gray', 'red', 'pink', 'orange', 'black']) 87 | 88 | one_hot_encoding['image'] = data['file name'] 89 | 90 | for img in data.index: 91 | if data['compact most'][img] == 'green': 92 | one_hot_encoding['green'][img] = 1 93 | elif data['compact most'][img] == 'purple': 94 | one_hot_encoding['purple'][img] = 1 95 | elif data['compact most'][img] == 'white': 96 | one_hot_encoding['white'][img] = 1 97 | elif data['compact most'][img] == 'brown': 98 | one_hot_encoding['brown'][img] = 1 99 | elif data['compact most'][img] == 'blue': 100 | one_hot_encoding['blue'][img] = 1 101 | elif data['compact most'][img] == 'cyan': 102 | one_hot_encoding['cyan'][img] = 1 103 | elif data['compact most'][img] == 'yellow': 104 | one_hot_encoding['yellow'][img] = 1 105 | elif data['compact most'][img] == 'gray': 106 | one_hot_encoding['gray'][img] = 1 107 | elif data['compact most'][img] == 'red': 108 | one_hot_encoding['red'][img] = 1 109 | elif data['compact most'][img] == 'pink': 110 | one_hot_encoding['pink'][img] = 1 111 | elif data['compact most'][img] == 'orange': 112 | one_hot_encoding['orange'][img] = 1 113 | elif data['compact most'][img] == 'black': 114 | one_hot_encoding['black'][img] = 1 115 | 116 | one_hot_encoding.fillna(0, inplace=True) 117 | 118 | one_hot_encoding.drop(one_hot_encoding.columns[0], axis=1, inplace= True) 119 | one_hot_encoding.to_csv(folder +'\\one_hot_encoding_color_icon.csv', index = False, header = False) 120 | 121 | 122 | 123 | 124 | 125 | for folder in folders: 126 | os.chdir(PATH) 127 | 128 | if VERBOSE: 129 | print('\n' + folder) 130 | 131 | if TRAINING: 132 | colors = pd.read_csv('colors.csv', sep = ';') 133 | else: 134 | colors = pd.read_csv('color_'+folder+'.csv', sep = ';') 135 | 136 | #read the lists in the csv 137 | color_rgb = [] 138 | color_amount = [] 139 | cnt = 0 140 | for img in colors.index: 141 | color_rgb.append([[float(_.group(0)) for _ in re.finditer(r"\d{1,3}[.]\d{0,8}", i)] for i in colors['colors'].iloc[img].split(',')]) 142 | color_amount.append([float(_.group(0)) for _ in re.finditer(r"\d{1,3}[.]\d{0,8}", colors['amount color'].iloc[img])]) 143 | cnt+=1 144 | if VERBOSE: 145 | if TRAINING: 146 | sys.stdout.write("Progress: {:.2%}\r".format(cnt/485377)) 147 | sys.stdout.flush() 148 | else: 149 | sys.stdout.write("Progress: {:.2%}\r".format(cnt/26000)) 150 | sys.stdout.flush() 151 | 152 | colors['colors'] = color_rgb 153 | colors['amount color'] = color_amount 154 | 155 | if VERBOSE: 156 | print("\nFormat change complete.") 157 | 158 | 159 | #match color RGB to real word 160 | list_colors_3 = [] 161 | list_compact_3 = [] 162 | cnt = 0 163 | for color in colors['colors']: 164 | list_colors = [] 165 | list_colors_compact = [] 166 | for i in range(0,3): 167 | #get real name of color 168 | color_name = get_colour_name(color[i]) 169 | list_colors.append(color_name) 170 | #get one of 12 shades/classes 171 | list_colors_compact.append(get_shade(color_name)) 172 | list_colors_3.append(list_colors) 173 | list_compact_3.append(list_colors_compact) 174 | cnt+=1 175 | if VERBOSE: 176 | if TRAINING: 177 | sys.stdout.write("Progress: {:.2%}\r".format(cnt/485377)) 178 | sys.stdout.flush() 179 | else: 180 | sys.stdout.write("Progress: {:.2%}\r".format(cnt/26000)) 181 | sys.stdout.flush() 182 | colors['color word'] = list_colors_3 183 | colors['color word compact'] = list_compact_3 184 | 185 | if VERBOSE: 186 | print("\nColor word match complete.") 187 | 188 | ''' 189 | Sort the color list: 190 | ''' 191 | word_least = [] # 3rd place for actual color 192 | word_middle = [] # 2nd place for actual color 193 | word_most = [] # 1st place for actual color 194 | compact_least = [] # 3rd place for shace/class 195 | compact_middle = [] # 2nd place for shace/class 196 | compact_most = [] # 1st place for shace/class 197 | for img in colors.index: 198 | #sort according to amount of color 199 | color_word_sorted=[x for _,x in sorted(zip(colors['amount color'][img],colors['color word'][img]))] 200 | word_least.append(color_word_sorted[0]) 201 | word_middle.append(color_word_sorted[1]) 202 | word_most.append(color_word_sorted[2]) 203 | #sort according to amount of color 204 | color_word_compact_sorted = [x for _,x in sorted(zip(colors['amount color'][img],colors['color word compact'][img]))] 205 | compact_least.append(color_word_compact_sorted[0]) 206 | compact_middle.append(color_word_compact_sorted[1]) 207 | compact_most.append(color_word_compact_sorted[2]) 208 | 209 | colors.drop(colors.columns[[2,3]], axis=1, inplace= True ) 210 | colors['word least'] = word_least 211 | colors['word middle'] = word_middle 212 | colors['word most'] = word_most 213 | colors['compact least'] = compact_least 214 | colors['compact middle'] = compact_middle 215 | colors['compact most'] = compact_most 216 | 217 | 218 | 219 | if TRAINING: 220 | one_hot_encode(colors, folder) 221 | else: 222 | colors.to_csv('colors-sorted-english-'+folder+'.csv', sep=';') 223 | 224 | 225 | 226 | -------------------------------------------------------------------------------- /environment.yml: -------------------------------------------------------------------------------- 1 | name: logan 2 | channels: 3 | - defaults 4 | dependencies: 5 | - certifi=2016.2.28=py35_0 6 | - pip=9.0.1=py35_1 7 | - python=3.5.4=0 8 | - setuptools=36.4.0=py35_1 9 | - vc=14=0 10 | - vs2015_runtime=14.0.25420=0 11 | - wheel=0.29.0=py35_0 12 | - wincertstore=0.2=py35_0 13 | - pip: 14 | - cycler==0.10.0 15 | - gast==0.2.0 16 | - kiwisolver==1.0.1 17 | - matplotlib==2.2.2 18 | - numpy==1.14.0 19 | - opencv-contrib-python==3.4.1.15 20 | - pandas==0.23.1 21 | - pillow==5.1.0 22 | - pyparsing==2.2.0 23 | - python-dateutil==2.7.3 24 | - pytz==2018.4 25 | - scikit-learn==0.19.1 26 | - six==1.11.0 27 | - webcolors==1.8.1 28 | prefix: C:\Users\ami\AppData\Local\conda\conda\envs\logan 29 | 30 | -------------------------------------------------------------------------------- /get_colors.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import os 4 | import sys 5 | import cv2 6 | import numpy as np 7 | import matplotlib.pyplot as plt 8 | from sklearn.cluster import MiniBatchKMeans 9 | 10 | 11 | PATH = 'C:\\Code\\Thesis\\LoGAN\\' 12 | TRAINING = True 13 | VERBOSE = True 14 | 15 | if TRAINING: 16 | folders = ['data'] 17 | else: 18 | folders = ['green', 'purple', 'white', 'brown', 'blue', 'cyan', 'yellow', 'gray', 'red', 'pink', 'orange', 'black'] 19 | PATH = PATH + 'results\\' 20 | 21 | def find_histogram(clt): 22 | """ 23 | create a histogram with k clusters 24 | :param: clt 25 | :return:hist 26 | """ 27 | numLabels = np.arange(0, len(np.unique(clt.labels_)) + 1) 28 | (hist, _) = np.histogram(clt.labels_, bins=numLabels) 29 | 30 | hist = hist.astype("float") 31 | hist /= hist.sum() 32 | 33 | return hist 34 | 35 | def plot_colors2(hist, centroids): 36 | bar = np.zeros((50, 300, 3), dtype="uint8") 37 | startX = 0 38 | 39 | for (percent, color) in zip(hist, centroids): 40 | # plot the relative percentage of each cluster 41 | endX = startX + (percent * 300) 42 | cv2.rectangle(bar, (int(startX), 0), (int(endX), 50), 43 | color.astype("uint8").tolist(), -1) 44 | startX = endX 45 | 46 | # return the bar chart 47 | return bar 48 | 49 | 50 | cnt= 0 51 | for folder in folders: 52 | os.chdir(PATH + folder) 53 | 54 | if TRAINING: 55 | with open(PATH+'colors.csv', 'w') as the_file: 56 | the_file.write('file name;colors;amount color') 57 | else: 58 | with open(PATH+'results\\color_' + folder + '.csv', 'a') as the_file: 59 | the_file.write('file name;colors;amount color') 60 | 61 | 62 | if VERBOSE: 63 | print('\n' + folder) 64 | 65 | for fn in os.listdir('.'): 66 | if os.path.isfile(fn): 67 | if VERBOSE: 68 | if TRAINING: 69 | sys.stdout.write("Progress: {:.2%}\r".format(cnt/485377)) 70 | sys.stdout.flush() 71 | else: 72 | sys.stdout.write("Progress: {:.2%}\r".format(cnt/26000)) 73 | sys.stdout.flush() 74 | 75 | cnt += 1 76 | 77 | #read image 78 | img = cv2.imread(fn) 79 | img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) 80 | #represent as row*column,channel number 81 | img = img.reshape((img.shape[0] * img.shape[1],3)) 82 | 83 | #find 3 clusters 84 | clt = MiniBatchKMeans(n_clusters=3) 85 | clt.fit(img) 86 | 87 | hist = find_histogram(clt) 88 | 89 | #visualise colors of centroids 90 | # bar = plot_colors2(hist, clt.cluster_centers_) 91 | # plt.axis("off") 92 | # plt.imshow(bar) 93 | # plt.show() 94 | 95 | if TRAINING: 96 | with open(PATH+'colors.csv', 'a') as the_file: 97 | the_file.write('\n' + str(fn) + ';' + str(clt.cluster_centers_[0]) + ',' + str(clt.cluster_centers_[1]) + ',' + str(clt.cluster_centers_[2]) + ';' + str(hist)) 98 | else: 99 | with open(PATH+'results\\color_' + folder + '.csv', 'a') as the_file: 100 | the_file.write('\n' + str(fn) + ';' + str(clt.cluster_centers_[0]) + ',' + str(clt.cluster_centers_[1]) + ',' + str(clt.cluster_centers_[2]) + ';' + str(hist)) 101 | 102 | 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | ''' 4 | Most of the code from https://github.com/hwalsuklee/tensorflow-generative-model-collections/ 5 | ''' 6 | import os 7 | 8 | from acwgangp import ACWGANGP 9 | from utils import show_all_variables 10 | from utils import check_folder 11 | 12 | import tensorflow as tf 13 | import argparse 14 | 15 | """parsing and configuration""" 16 | def parse_args(): 17 | desc = "Tensorflow implementation of GAN collections" 18 | parser = argparse.ArgumentParser(description=desc) 19 | 20 | parser.add_argument('--gan_type', type=str, default='ACWGANGP', choices=['ACWGANGP'], help='The type of GAN', required=True) 21 | parser.add_argument('--dataset', type=str, default='lld', help='The name of dataset') 22 | parser.add_argument('--epoch', type=int, default=400, help='The number of epochs to run') 23 | parser.add_argument('--batch_size', type=int, default=64, help='The size of batch') 24 | parser.add_argument('--z_dim', type=int, default=100, help='Dimension of noise vector') 25 | parser.add_argument('--checkpoint_dir', type=str, default='checkpoint', help='Directory name to save the checkpoints') 26 | parser.add_argument('--result_dir', type=str, default='results', help='Directory name to save the generated images') 27 | parser.add_argument('--log_dir', type=str, default='logs', help='Directory name to save training logs') 28 | 29 | return check_args(parser.parse_args()) 30 | 31 | """checking arguments""" 32 | def check_args(args): 33 | # --checkpoint_dir 34 | check_folder(args.checkpoint_dir) 35 | 36 | # --result_dir 37 | check_folder(args.result_dir) 38 | 39 | # --result_dir 40 | check_folder(args.log_dir) 41 | 42 | # --epoch 43 | assert args.epoch >= 1, 'number of epochs must be larger than or equal to one' 44 | 45 | # --batch_size 46 | assert args.batch_size >= 1, 'batch size must be larger than or equal to one' 47 | 48 | # --z_dim 49 | assert args.z_dim >= 1, 'dimension of noise vector must be larger than or equal to one' 50 | 51 | return args 52 | 53 | """main""" 54 | def main(): 55 | # parse arguments 56 | args = parse_args() 57 | if args is None: 58 | exit() 59 | 60 | # open session 61 | models = [ACWGANGP] 62 | with tf.Session(config=tf.ConfigProto(allow_soft_placement=True)) as sess: 63 | # declare instance for GAN 64 | gan = None 65 | for model in models: 66 | if args.gan_type == model.model_name: 67 | gan = model(sess, 68 | epoch=args.epoch, 69 | batch_size=args.batch_size, 70 | z_dim=args.z_dim, 71 | dataset_name=args.dataset, 72 | checkpoint_dir=args.checkpoint_dir, 73 | result_dir=args.result_dir, 74 | log_dir=args.log_dir) 75 | if gan is None: 76 | raise Exception("[!] There is no option for " + args.gan_type) 77 | 78 | # build graph 79 | gan.build_model() 80 | 81 | # show network architecture 82 | show_all_variables() 83 | 84 | # launch the graph in a session 85 | gan.train() 86 | print(" [*] Training finished!") 87 | 88 | # visualize learned generator 89 | gan.visualize_results(args.epoch-1) 90 | print(" [*] Testing finished!") 91 | 92 | 93 | 94 | def main_no_args(): 95 | models = [ACWGANGP] 96 | with tf.Session(config=tf.ConfigProto(allow_soft_placement=True)) as sess: 97 | 98 | gan = None 99 | for model in models: 100 | if 'ACWGANGP' == model.model_name: 101 | gan = model(sess, 102 | epoch=400, 103 | batch_size=5, 104 | z_dim=100, 105 | dataset_name='lld', 106 | checkpoint_dir='checkpoint', 107 | result_dir='results', 108 | log_dir='logs') 109 | 110 | 111 | # build graph 112 | gan.build_model() 113 | 114 | # show network architecture 115 | show_all_variables() 116 | 117 | # launch the graph in a session 118 | gan.train() 119 | print(" [*] Training finished!") 120 | 121 | # visualize learned generator 122 | gan.visualize_results(args.epoch-1) 123 | print(" [*] Testing finished!") 124 | 125 | 126 | if __name__ == '__main__': 127 | main() 128 | #tf.reset_default_graph() 129 | 130 | -------------------------------------------------------------------------------- /make_confusion_matrix.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import os 4 | import pandas as pd 5 | 6 | PATH = 'C:\\Code\\Thesis\\LoGAN\\results\\' 7 | VERBOSE = True 8 | 9 | 10 | count = 0 11 | folders = ['black','blue','brown', 'cyan','gray', 'green','orange','pink','purple','red','white','yellow'] 12 | 13 | with open('confusion_matrix_second_color_epoch_400.csv', 'w') as the_file: 14 | the_file.write('Class;black;blue;brown;cyan;gray;green;orange;pink;purple;red;white;yellow') 15 | 16 | for folder in folders: 17 | os.chdir(PATH) 18 | if VERBOSE: 19 | print('\n' + folder) 20 | colors = pd.read_csv('colors-sorted-english-'+folder+'.csv', sep=';') 21 | 22 | color_count_1st = {'black': 0, 'blue': 0, 'brown': 0, 'cyan': 0, 'gray': 0, 'green':0, 'orange':0, 'pink':0, 'purple':0, 'red':0, 'white':0, 'yellow':0} 23 | 24 | for row in range(25936, 26000): 25 | color_count_1st[colors['compact middle'][row]] += 1 26 | 27 | 28 | with open('C:\\Code\\Thesis\\AC-WGAN-GP_from_vm\\results\\confusion_matrix_second_color_epoch_400.csv', 'a') as the_file: 29 | the_file.write('\n' + folder ) 30 | for i in range(0,12): 31 | the_file.write(';' + str(color_count_1st[folders[i]])) 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /ops.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | Most codes from https://github.com/carpedm20/DCGAN-tensorflow 5 | and 6 | from https://github.com/hwalsuklee/tensorflow-generative-model-collections/ 7 | """ 8 | import math 9 | import numpy as np 10 | import tensorflow as tf 11 | 12 | from tensorflow.python.framework import ops 13 | 14 | from utils import * 15 | 16 | if "concat_v2" in dir(tf): 17 | def concat(tensors, axis, *args, **kwargs): 18 | return tf.concat_v2(tensors, axis, *args, **kwargs) 19 | else: 20 | def concat(tensors, axis, *args, **kwargs): 21 | return tf.concat(tensors, axis, *args, **kwargs) 22 | 23 | def bn(x, is_training, scope): 24 | return tf.contrib.layers.batch_norm(x, 25 | decay=0.9, 26 | updates_collections=None, 27 | epsilon=1e-5, 28 | scale=True, 29 | is_training=is_training, 30 | scope=scope) 31 | 32 | def conv_out_size_same(size, stride): 33 | return int(math.ceil(float(size) / float(stride))) 34 | 35 | def conv_cond_concat(x, y): 36 | """Concatenate conditioning vector on feature map axis.""" 37 | x_shapes = x.get_shape() 38 | y_shapes = y.get_shape() 39 | return concat([x, y*tf.ones([x_shapes[0], x_shapes[1], x_shapes[2], y_shapes[3]])], 3) 40 | 41 | def conv2d(input_, output_dim, k_h=5, k_w=5, d_h=2, d_w=2, stddev=0.02, name="conv2d"): 42 | with tf.variable_scope(name): 43 | #print("var shape") 44 | #print(input_.get_shape()) 45 | w = tf.get_variable('w', [k_h, k_w, input_.get_shape()[-1], output_dim], 46 | initializer=tf.truncated_normal_initializer(stddev=stddev)) 47 | conv = tf.nn.conv2d(input_, w, strides=[1, d_h, d_w, 1], padding='SAME') 48 | 49 | biases = tf.get_variable('biases', [output_dim], initializer=tf.constant_initializer(0.0)) 50 | conv = tf.reshape(tf.nn.bias_add(conv, biases), conv.get_shape()) 51 | 52 | return conv 53 | 54 | def deconv2d(input_, output_shape, k_h=5, k_w=5, d_h=2, d_w=2, name="deconv2d", stddev=0.02, with_w=False): 55 | with tf.variable_scope(name): 56 | # filter : [height, width, output_channels, in_channels] 57 | w = tf.get_variable('w', [k_h, k_w, output_shape[-1], input_.get_shape()[-1]], 58 | initializer=tf.random_normal_initializer(stddev=stddev)) 59 | 60 | try: 61 | deconv = tf.nn.conv2d_transpose(input_, w, output_shape=output_shape, strides=[1, d_h, d_w, 1]) 62 | 63 | # Support for verisons of TensorFlow before 0.7.0 64 | except AttributeError: 65 | deconv = tf.nn.deconv2d(input_, w, output_shape=output_shape, strides=[1, d_h, d_w, 1]) 66 | 67 | biases = tf.get_variable('biases', [output_shape[-1]], initializer=tf.constant_initializer(0.0)) 68 | deconv = tf.reshape(tf.nn.bias_add(deconv, biases), deconv.get_shape()) 69 | 70 | if with_w: 71 | return deconv, w, biases 72 | else: 73 | return deconv 74 | 75 | def lrelu(x, leak=0.2, name="lrelu"): 76 | return tf.maximum(x, leak*x) 77 | 78 | def linear(input_, output_size, scope=None, stddev=0.02, bias_start=0.0, with_w=False): 79 | shape = input_.get_shape().as_list() 80 | 81 | with tf.variable_scope(scope or "Linear"): 82 | matrix = tf.get_variable("Matrix", [shape[1], output_size], tf.float32, 83 | tf.random_normal_initializer(stddev=stddev)) 84 | bias = tf.get_variable("bias", [output_size], 85 | initializer=tf.constant_initializer(bias_start)) 86 | if with_w: 87 | return tf.matmul(input_, matrix) + bias, matrix, bias 88 | else: 89 | return tf.matmul(input_, matrix) + bias -------------------------------------------------------------------------------- /read_images.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import csv 4 | import glob 5 | import os 6 | import sys 7 | 8 | import numpy as np 9 | import tensorflow as tf 10 | from PIL import Image 11 | 12 | Data_PATH = 'C:\\Code\\Thesis\\LoGAN\\data\\logos' 13 | label_csv_PATH = 'C:\\Code\\Thesis\\LoGAN\\data\\one_hot_encoding_color_icon.csv' 14 | 15 | 16 | # Parameters 17 | IMAGE_SIZE = 32 18 | IMAGE_SHAPE = [IMAGE_SIZE, IMAGE_SIZE, 3] # 3 is number of channels 19 | CATEGORIES = ['green', 'purple', 'white', 'brown', 'blue', 'cyan', 'yellow', 'gray', 'red', 'pink', 'orange', 'black'] # the different classes for the one-hot encoding 20 | num_classes = len(CATEGORIES) 21 | BATCH_SIZE = 64 # used in example in the end 22 | VERBOSE = True 23 | 24 | 25 | def read_labels_from(path=label_csv_PATH): 26 | if VERBOSE: 27 | print('Reading labels ...') 28 | with open(path, 'r') as label_file: 29 | data_iter = csv.reader(label_file) 30 | train_labels = [data for data in data_iter] 31 | 32 | # pre process labels to int 33 | train_labels = np.array(train_labels, dtype=np.uint32) 34 | 35 | return train_labels 36 | 37 | 38 | def read_images_from(path=Data_PATH): 39 | images = [] 40 | png_files_path = glob.glob(os.path.join(path, '*.[pP][nN][gG]')) # extract all png files 41 | 42 | if VERBOSE: 43 | print("Reading images ...") 44 | 45 | cnt=0 46 | for filename in png_files_path: 47 | im = Image.open(filename) 48 | im = np.asarray(im, np.uint8) 49 | 50 | # get image name, not path 51 | image_name = filename.split('\\')[-1].split('.')[0] 52 | images.append([int(image_name), im]) 53 | 54 | cnt+=1 55 | if VERBOSE: 56 | sys.stdout.write("Progress loading images: {:.2%}\r".format(cnt/485377)) 57 | sys.stdout.flush() 58 | 59 | images = sorted(images, key=lambda image: image[0]) 60 | 61 | images_only = [np.asarray(image[1], np.uint8) for image in images] 62 | images_only = np.array(images_only) 63 | 64 | return images_only 65 | 66 | ''' 67 | if '__main__': 68 | # Example usage for getting the next batch (together with Dataset) 69 | from util.dataset import Dataset 70 | 71 | images = read_images_from() 72 | labels = read_labels_from() 73 | 74 | dataset = Dataset(images, labels) 75 | 76 | next_batch_img, next_batch_label = dataset.next_batch(BATCH_SIZE) 77 | 78 | # test conversion to tensorflow tensor 79 | data_tf = [] 80 | for image in next_batch_img: 81 | data_tf.append(tf.convert_to_tensor(image)) 82 | 83 | sess = tf.InteractiveSession() 84 | print(data_tf[0].eval()) 85 | sess.close() 86 | ''' 87 | 88 | 89 | -------------------------------------------------------------------------------- /utils.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | ''' 4 | Most of the code from https://github.com/hwalsuklee/tensorflow-generative-model-collections/ 5 | ''' 6 | 7 | from __future__ import division 8 | import math 9 | import random 10 | import pprint 11 | import scipy.misc 12 | import numpy as np 13 | from time import gmtime, strftime 14 | from six.moves import xrange 15 | import matplotlib.pyplot as plt 16 | import os, gzip 17 | 18 | import read_images as read 19 | 20 | import tensorflow as tf 21 | import tensorflow.contrib.slim as slim 22 | 23 | def load_lld(dataset_name): 24 | data_dir = os.path.join("./data") 25 | 26 | def extract_data(filename, num_data, head_size, data_size): 27 | with gzip.open(filename) as bytestream: 28 | bytestream.read(head_size) 29 | buf = bytestream.read(data_size * num_data) 30 | data = np.frombuffer(buf, dtype=np.uint8).astype(np.float) 31 | return data 32 | 33 | 34 | X = read.read_images_from() 35 | y = read.read_labels_from() 36 | 37 | seed = 547 38 | np.random.seed(seed) 39 | np.random.shuffle(X) 40 | np.random.seed(seed) 41 | np.random.shuffle(y) 42 | 43 | y_vec = y 44 | 45 | return X / 255., y_vec 46 | 47 | def check_folder(log_dir): 48 | if not os.path.exists(log_dir): 49 | os.makedirs(log_dir) 50 | return log_dir 51 | 52 | def show_all_variables(): 53 | model_vars = tf.trainable_variables() 54 | slim.model_analyzer.analyze_vars(model_vars, print_info=True) 55 | 56 | def get_image(image_path, input_height, input_width, resize_height=64, resize_width=64, crop=True, grayscale=False): 57 | image = imread(image_path, grayscale) 58 | 59 | return transform(image, input_height, input_width, resize_height, resize_width, crop) 60 | 61 | def save_images(images, size, image_path): 62 | return imsave(inverse_transform(images), size, image_path) 63 | 64 | def imread(path, grayscale = False): 65 | #if (grayscale): 66 | if (False): 67 | return scipy.misc.imread(path, flatten = True).astype(np.float) 68 | else: 69 | return scipy.misc.imread(path).astype(np.float) 70 | 71 | def merge_images(images, size): 72 | return inverse_transform(images) 73 | 74 | def merge(images, size): 75 | h, w = images.shape[1], images.shape[2] 76 | if (images.shape[3] in (3,4)): 77 | c = images.shape[3] 78 | img = np.zeros((h * size[0], w * size[1], c)) 79 | for idx, image in enumerate(images): 80 | i = idx % size[1] 81 | j = idx // size[1] 82 | img[j * h:j * h + h, i * w:i * w + w, :] = image 83 | return img 84 | elif images.shape[3]==1: 85 | img = np.zeros((h * size[0], w * size[1])) 86 | for idx, image in enumerate(images): 87 | i = idx % size[1] 88 | j = idx // size[1] 89 | img[j * h:j * h + h, i * w:i * w + w] = image[:,:,0] 90 | return img 91 | else: 92 | raise ValueError('in merge(images,size) images parameter ''must have dimensions: HxW or HxWx3 or HxWx4') 93 | 94 | def imsave(images, size, path): 95 | image = np.squeeze(merge(images, size)) 96 | return scipy.misc.imsave(path, image) 97 | 98 | def center_crop(x, crop_h, crop_w, resize_h=64, resize_w=64): 99 | if crop_w is None: 100 | crop_w = crop_h 101 | h, w = x.shape[:2] 102 | j = int(round((h - crop_h)/2.)) 103 | i = int(round((w - crop_w)/2.)) 104 | return scipy.misc.imresize(x[j:j+crop_h, i:i+crop_w], [resize_h, resize_w]) 105 | 106 | def transform(image, input_height, input_width, resize_height=64, resize_width=64, crop=True): 107 | if crop: 108 | cropped_image = center_crop(image, input_height, input_width, resize_height, resize_width) 109 | else: 110 | cropped_image = scipy.misc.imresize(image, [resize_height, resize_width]) 111 | return np.array(cropped_image)/127.5 - 1. 112 | 113 | def inverse_transform(images): 114 | return (images+1.)/2. 115 | 116 | """ Drawing Tools """ 117 | # borrowed from https://github.com/ykwon0407/variational_autoencoder/blob/master/variational_bayes.ipynb 118 | def save_scattered_image(z, id, z_range_x, z_range_y, name='scattered_image.jpg'): 119 | N = 10 120 | plt.figure(figsize=(8, 6)) 121 | plt.scatter(z[:, 0], z[:, 1], c=np.argmax(id, 1), marker='o', edgecolor='none', cmap=discrete_cmap(N, 'jet')) 122 | plt.colorbar(ticks=range(N)) 123 | axes = plt.gca() 124 | axes.set_xlim([-z_range_x, z_range_x]) 125 | axes.set_ylim([-z_range_y, z_range_y]) 126 | plt.grid(True) 127 | plt.savefig(name) 128 | 129 | # borrowed from https://gist.github.com/jakevdp/91077b0cae40f8f8244a 130 | def discrete_cmap(N, base_cmap=None): 131 | """Create an N-bin discrete colormap from the specified input map""" 132 | 133 | # Note that if base_cmap is a string or None, you can simply do 134 | # return plt.cm.get_cmap(base_cmap, N) 135 | # The following works for string, None, or a colormap instance: 136 | 137 | base = plt.cm.get_cmap(base_cmap) 138 | color_list = base(np.linspace(0, 1, N)) 139 | cmap_name = base.name + str(N) 140 | return base.from_list(cmap_name, color_list, N) 141 | --------------------------------------------------------------------------------