{"cells":[{"metadata":{},"cell_type":"markdown","source":"The Network architecture code taken from https://github.com/mitchelljy/DCGAN-Keras","execution_count":null},{"metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","trusted":true},"cell_type":"code","source":"import os\nos.listdir('../input')\n\n# Any results you write to the current directory are saved as output.","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"crop, resize images and save them to folder","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"DogsOnly = True\n\nimport numpy as np, pandas as pd, os\nimport xml.etree.ElementTree as ET \nimport matplotlib.pyplot as plt, zipfile \nfrom PIL import Image \nfrom glob import glob\n\nROOT = '../input/'\nIMAGES = os.listdir(ROOT + 'all-dogs/all-dogs')\nprint(len(IMAGES))\nbreeds = os.listdir(ROOT + 'annotation/Annotation') \nprint(len(breeds))\n\nidxIn = 0; namesIn = []\nimagesIn = np.zeros((25000,64,64,3))\n\n# CROP WITH BOUNDING BOXES TO GET DOGS ONLY\n# https://www.kaggle.com/paulorzp/show-annotations-and-breeds\nif DogsOnly:\n    for breed in breeds:\n        for dog in os.listdir(ROOT+'annotation/Annotation/'+breed):\n            try: img = Image.open(ROOT+'all-dogs/all-dogs/'+dog+'.jpg') \n            except: continue           \n            tree = ET.parse(ROOT+'annotation/Annotation/'+breed+'/'+dog)\n            root = tree.getroot()\n            objects = root.findall('object')\n            for o in objects:\n                bndbox = o.find('bndbox') \n                xmin = int(bndbox.find('xmin').text)\n                ymin = int(bndbox.find('ymin').text)\n                xmax = int(bndbox.find('xmax').text)\n                ymax = int(bndbox.find('ymax').text)\n                w = np.min((xmax - xmin, ymax - ymin))\n                img2 = img.crop((xmin, ymin, xmin+w, ymin+w))\n                img2 = img2.resize((64,64), Image.ANTIALIAS)\n                imagesIn[idxIn,:,:,:] = np.asarray(img2)\n                #if idxIn%1000==0: print(idxIn)\n                namesIn.append(breed)\n                idxIn += 1\n                \n                #if not os.path.exists(f\"temp/cropped_images\"):\n                #  os.makedirs(f\"temp/cropped_images\")\n                #img2.save(f\"temp/cropped_images/{dog}.png\")\n    idx = np.arange(idxIn)\n    np.random.shuffle(idx)\n    imagesIn = imagesIn[idx,:,:,:]\n    namesIn = np.array(namesIn)[idx]\n    \n# RANDOMLY CROP FULL IMAGES\nelse:\n    x = np.random.choice(np.arange(20579),10000)\n    for k in range(len(x)):\n        img = Image.open(ROOT + 'all-dogs/all-dogs/' + IMAGES[x[k]])\n        w = img.size[0]\n        h = img.size[1]\n        sz = np.min((w,h))\n        a=0; b=0\n        if w<h: b = (h-sz)//2\n        else: a = (w-sz)//2\n        img = img.crop((0+a, 0+b, sz+a, sz+b))  \n        img = img.resize((64,64), Image.ANTIALIAS)   \n        imagesIn[idxIn,:,:,:] = np.asarray(img)\n        namesIn.append(IMAGES[x[k]])\n        if idxIn%1000==0: print(idxIn)\n        idxIn += 1\n    \n# DISPLAY CROPPED IMAGES\nx = np.random.randint(0,idxIn,25)\nfor k in range(5):\n    plt.figure(figsize=(15,3))\n    for j in range(5):\n        plt.subplot(1,5,j+1)\n        img = Image.fromarray( imagesIn[x[k*5+j],:,:,:].astype('uint8') )\n        plt.axis('off')\n        if not DogsOnly: plt.title(namesIn[x[k*5+j]],fontsize=11)\n        else: plt.title(namesIn[x[k*5+j]].split('-')[1],fontsize=11)\n        plt.imshow(img)\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"model building\nreference: https://github.com/DataSnaek/DCGAN-Keras","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.models import Sequential, Model, load_model\nfrom keras.layers import UpSampling2D, Conv2D, Activation, BatchNormalization, Reshape, Dense, Input, LeakyReLU, Dropout, Flatten, ZeroPadding2D\nfrom keras.optimizers import Adam\n\nimport glob\nfrom PIL import Image\nimport numpy as np\nimport os\nimport argparse\nfrom ast import literal_eval\n\n#from scipy.misc import imsave\nimport matplotlib.image as mpimg\n\nclass DCGAN:\n    def __init__(self, discriminator_path, generator_path, output_directory, img_size):\n        self.img_size = img_size\n        self.upsample_layers = 5\n        self.starting_filters = 64\n        self.kernel_size = 3\n        self.channels = 3\n        self.discriminator_path = discriminator_path\n        self.generator_path = generator_path\n        self.output_directory = output_directory\n\n    def build_generator(self):\n        noise_shape = (100,)\n\n        # This block of code can be a little daunting, but essentially it automatically calculates the required starting\n        # array size that will be correctly upscaled to our desired image size.\n        #\n        # We have 5 Upsample2D layers which each double the images width and height, so we can determine the starting\n        # x size by taking (x / 2^upsample_count) So for our target image size, 256x192, we do the following:\n        # x = (192 / 2^5), y = (256 / 2^5) [x and y are reversed within the model]\n        # We also need a 3rd dimension which is chosen relatively arbitrarily, in this case it's 64.\n        model = Sequential()\n        model.add(\n            Dense(self.starting_filters * (self.img_size[0] // (2 ** self.upsample_layers))  *  (self.img_size[1] // (2 ** self.upsample_layers)),\n                  activation=\"relu\", input_shape=noise_shape))\n        model.add(Reshape(((self.img_size[0] // (2 ** self.upsample_layers)),\n                           (self.img_size[1] // (2 ** self.upsample_layers)),\n                           self.starting_filters)))\n        model.add(BatchNormalization(momentum=0.8))\n\n        model.add(UpSampling2D())  # 6x8 -> 12x16\n        model.add(Conv2D(1024, kernel_size=self.kernel_size, padding=\"same\"))\n        model.add(Activation(\"relu\"))\n        model.add(BatchNormalization(momentum=0.8))\n\n        model.add(UpSampling2D())  # 12x16 -> 24x32\n        model.add(Conv2D(512, kernel_size=self.kernel_size, padding=\"same\"))\n        model.add(Activation(\"relu\"))\n        model.add(BatchNormalization(momentum=0.8))\n\n        model.add(UpSampling2D())  # 24x32 -> 48x64\n        model.add(Conv2D(256, kernel_size=self.kernel_size, padding=\"same\"))\n        model.add(Activation(\"relu\"))\n        model.add(BatchNormalization(momentum=0.8))\n\n        model.add(UpSampling2D())  # 48x64 -> 96x128\n        model.add(Conv2D(128, kernel_size=self.kernel_size, padding=\"same\"))\n        model.add(Activation(\"relu\"))\n        model.add(BatchNormalization(momentum=0.8))\n\n        model.add(UpSampling2D())  # 96x128 -> 192x256\n        model.add(Conv2D(64, kernel_size=self.kernel_size, padding=\"same\"))\n        model.add(Activation(\"relu\"))\n        model.add(BatchNormalization(momentum=0.8))\n\n        model.add(Conv2D(32, kernel_size=self.kernel_size, padding=\"same\"))\n        model.add(Activation(\"relu\"))\n        model.add(BatchNormalization(momentum=0.8))\n\n        model.add(Conv2D(self.channels, kernel_size=self.kernel_size, padding=\"same\"))\n        model.add(Activation(\"tanh\"))\n\n        model.summary()\n\n        noise = Input(shape=noise_shape)\n        img = model(noise)\n\n        return Model(noise, img)\n\n    def build_discriminator(self):\n\n        img_shape = (self.img_size[0], self.img_size[1], self.channels)\n\n        model = Sequential()\n\n        model.add(Conv2D(32, kernel_size=self.kernel_size, strides=2, input_shape=img_shape, padding=\"same\"))  # 192x256 -> 96x128\n        model.add(LeakyReLU(alpha=0.2))\n        model.add(Dropout(0.25))\n\n        model.add(Conv2D(64, kernel_size=self.kernel_size, strides=2, padding=\"same\"))  # 96x128 -> 48x64\n        model.add(ZeroPadding2D(padding=((0, 1), (0, 1))))\n        model.add(LeakyReLU(alpha=0.2))\n        model.add(Dropout(0.25))\n        model.add(BatchNormalization(momentum=0.8))\n\n        model.add(Conv2D(128, kernel_size=self.kernel_size, strides=2, padding=\"same\"))  # 48x64 -> 24x32\n        model.add(LeakyReLU(alpha=0.2))\n        model.add(Dropout(0.25))\n        model.add(BatchNormalization(momentum=0.8))\n\n        model.add(Conv2D(256, kernel_size=self.kernel_size, strides=1, padding=\"same\"))  # 24x32 -> 12x16\n        model.add(LeakyReLU(alpha=0.2))\n        model.add(Dropout(0.25))\n\n        model.add(Conv2D(512, kernel_size=self.kernel_size, strides=1, padding=\"same\"))  # 12x16 -> 6x8\n        model.add(LeakyReLU(alpha=0.2))\n        model.add(Dropout(0.25))\n\n        model.add(Flatten())\n        model.add(Dense(1, activation='sigmoid'))\n\n        model.summary()\n\n        img = Input(shape=img_shape)\n        validity = model(img)\n\n        return Model(img, validity)\n\n    def build_gan(self):\n        optimizer = Adam(0.0002, 0.5)\n\n        # See if the specified model paths exist, if they don't then we start training new models\n\n        if os.path.exists(self.discriminator_path) and os.path.exists(self.generator_path):\n            self.discriminator = load_model(self.discriminator_path)\n            self.generator = load_model(self.generator_path)\n            print(\"Loaded models...\")\n        else:\n            self.discriminator = self.build_discriminator()\n            self.discriminator.compile(loss='binary_crossentropy',\n                                       optimizer=optimizer,\n                                       metrics=['accuracy'])\n\n            self.generator = self.build_generator()\n            self.generator.compile(loss='binary_crossentropy', optimizer=optimizer)\n\n        # These next few lines setup the training for the GAN model\n        z = Input(shape=(100,))\n        img = self.generator(z)\n\n        self.discriminator.trainable = False\n\n        valid = self.discriminator(img)\n\n        self.combined = Model(z, valid)\n        self.combined.compile(loss='binary_crossentropy', optimizer=optimizer)\n\n    def load_imgs(self, image_path):\n        X_train = []\n        for i in glob.glob(image_path):\n            img = Image.open(i)\n            img = np.asarray(img)\n            X_train.append(img)\n        return np.asarray(X_train)\n\n    def train(self, epochs, X_train, batch_size=32, save_interval=50):\n        self.build_gan()\n        #X_train = self.load_imgs(image_path)\n        print(\"Training Data Shape: \", X_train.shape)\n\n        # Rescale images from -1 to 1\n        X_train = (X_train.astype(np.float32) - 127.5) / 127.5\n\n        half_batch = batch_size // 2\n\n        for epoch in range(epochs):\n\n\n            # Train Generator\n            noise = np.random.normal(0, 1, (batch_size, 100))\n            g_loss = self.combined.train_on_batch(noise, np.ones((batch_size, 1)))\n\n\n\n            # Train Discriminator\n            idx = np.random.randint(0, X_train.shape[0], half_batch)\n            imgs = X_train[idx]\n\n            # Sample noise and generate a half batch of new images\n            noise = np.random.normal(0, 1, (half_batch, 100))\n            gen_imgs = self.generator.predict(noise)\n\n            # Train the discriminator (real classified as ones and generated as zeros)\n            d_loss_real = self.discriminator.train_on_batch(imgs, np.ones((half_batch, 1)))\n            d_loss_fake = self.discriminator.train_on_batch(gen_imgs, np.zeros((half_batch, 1)))\n            d_loss = 0.5 * np.add(d_loss_real, d_loss_fake)\n\n            # Print progress\n            #print(f\"{epoch} [D loss: {d_loss[0]} | D Accuracy: {100 * d_loss[1]}] [G loss: {g_loss}]\")\n\n            # If at save interval => save generated image samples, save model files\n            #if epoch % (save_interval) == 0:\n\n            #    self.save_imgs(epoch)\n\n            #    save_path = self.output_directory + \"/models\"\n            #    if not os.path.exists(save_path):\n            #        os.makedirs(save_path)\n            #    self.discriminator.save(save_path + \"/discrim.h5\")\n            #    self.generator.save(save_path + \"/generat.h5\")\n\n    def gene_imgs(self, count):\n        # Generate images from the currently loaded model\n        noise = np.random.normal(0, 1, (count, 100))\n        return self.generator.predict(noise)\n\n    def save_imgs(self, epoch):\n        r, c = 5, 5\n\n        # Generates r*c images from the model, saves them individually and as a gallery\n\n        imgs = self.gene_imgs(r*c)\n        imgs = 0.5 * imgs + 0.5\n\n        for i, img_array in enumerate(imgs):\n            path = f\"{self.output_directory}/generated_{self.img_size[0]}x{self.img_size[1]}\"\n            if not os.path.exists(path):\n                os.makedirs(path)\n            mpimg.imsave(path + f\"/{epoch}_{i}.png\", img_array)\n\n        nindex, height, width, intensity = imgs.shape\n        nrows = nindex // c\n        assert nindex == nrows * c\n        # want result.shape = (height*nrows, width*ncols, intensity)\n        gallery = (imgs.reshape(nrows, c, height, width, intensity)\n                  .swapaxes(1, 2)\n                  .reshape(height * nrows, width * c, intensity))\n\n        path = f\"{self.output_directory}/gallery_generated_{self.img_size[0]}x{self.img_size[1]}\"\n        if not os.path.exists(path):\n            os.makedirs(path)\n        mpimg.imsave(path + f\"/{epoch}.png\", gallery)\n\n    def generate_imgs(self, count, threshold, modifier):\n        #self.build_gan()\n\n        # Generates (count) images from the model ensuring the discriminator scores them between the threshold values\n        # and saves them\n\n        imgs = []\n        for i in range(count):\n            #score = [0]\n            #while not(threshold[0] < score[0] < threshold[1]):\n            img = self.gene_imgs(1)\n            #score = self.discriminator.predict(img)    \n            #print(\"Image found: \", score[0])\n            imgs.append(img)\n\n        imgs = np.asarray(imgs).squeeze()\n        imgs = 0.5 * imgs + 0.5\n\n        print(imgs.shape)\n        for i, img_array in enumerate(imgs):\n            path = f\"{self.output_directory}/images\"\n            if not os.path.exists(path):\n                os.makedirs(path)\n            image = Image.fromarray(img_array )\n            image.save(path + f\"/{i}.png\")\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"training step","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"load_discriminator=''\nload_generator=''\noutput_directory = '../tmp'\nimage_size = (64,64)\nepochs = 1000\ndata = 'temp/cropped_images/*.png'\nbatch_size = 32\nsave_interval = 1000000\n\n\ndcgan = DCGAN(load_discriminator, load_generator, output_directory, image_size)\ndcgan.train(epochs=int(epochs), X_train=imagesIn, batch_size=int(batch_size), save_interval=int(save_interval))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"generating step","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"#print((imagesIn[0,:,:,1]-127.5)/127.5)\n\nsample=10000\nsample_thresholds = (0.0, 1.0)\n\ndcgan.generate_imgs(sample, sample_thresholds, \"\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"create zip file","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"import shutil\n\n#print(os.listdir('output/gallery_generated_64x64'))\nprint(len(os.listdir('../tmp/images/')))\nshutil.make_archive('images', 'zip', '../tmp/images')\n!ls","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#print(len(os.listdir('output/gallery_generated_64x64/')))\n#print(os.listdir('output/gallery_generated_64x64/')[0])\n\n#im = Image.open(f\"output/gallery_generated_64x64/{os.listdir('output/gallery_generated_64x64/')[0]}\")\n\n#plt.clf()\n#plt.figure()\n#plt.imshow(im)\n#plt.show()","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":4}