Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed the errors and added the missing files #4

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
484 changes: 452 additions & 32 deletions Cat DCGAN.ipynb

Large diffs are not rendered by default.

165 changes: 165 additions & 0 deletions dcgan.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Reshape
from keras.initializers import RandomNormal
from keras.layers.core import Activation
from keras.layers.normalization import BatchNormalization
from keras.layers.convolutional import UpSampling2D
from keras.layers.convolutional import Conv2D, MaxPooling2D
from keras.layers.core import Flatten
from keras.optimizers import SGD
from keras.datasets import mnist
import numpy as np
from PIL import Image
import argparse
import math


def generator_model():
conv_initial_weight = RandomNormal(mean=0.0, stddev=0.02, seed=None)
batch_norm_weight = RandomNormal(mean=1.0, stddev=0.05, seed=None)
model = Sequential()
model.add(Dense(input_dim=100, output_dim=1024))
model.add(Activation('tanh'))
model.add(Dense(128*7*7))
model.add(BatchNormalization(kernel_initializer=batch_norm_weight))
model.add(Activation('tanh'))
model.add(Reshape((7, 7, 128), input_shape=(128*7*7,)))
model.add(UpSampling2D(size=(2, 2)))
model.add(Conv2D(64, (5, 5), padding='same',kernel_initializer=conv_initial_weight))
model.add(Activation('tanh'))
model.add(UpSampling2D(size=(2, 2)))
model.add(Conv2D(1, (5, 5), padding='same',kernel_initializer=conv_initial_weight))
model.add(Activation('tanh'))
return model


def discriminator_model():
model = Sequential()
model.add(
Conv2D(64, (5, 5),
padding='same',
input_shape=(28, 28, 1))
)
model.add(Activation('tanh'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(128, (5, 5)))
model.add(Activation('tanh'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(1024))
model.add(Activation('tanh'))
model.add(Dense(1))
model.add(Activation('sigmoid'))
return model


def generator_containing_discriminator(g, d):
model = Sequential()
model.add(g)
d.trainable = False
model.add(d)
return model


def combine_images(generated_images):
num = generated_images.shape[0]
width = int(math.sqrt(num))
height = int(math.ceil(float(num)/width))
shape = generated_images.shape[1:3]
image = np.zeros((height*shape[0], width*shape[1]),
dtype=generated_images.dtype)
for index, img in enumerate(generated_images):
i = int(index/width)
j = index % width
image[i*shape[0]:(i+1)*shape[0], j*shape[1]:(j+1)*shape[1]] = \
img[:, :, 0]
return image


def train(BATCH_SIZE):
(X_train, y_train), (X_test, y_test) = mnist.load_data()
X_train = (X_train.astype(np.float32) - 127.5)/127.5
X_train = X_train[:, :, :, None]
X_test = X_test[:, :, :, None]
# X_train = X_train.reshape((X_train.shape, 1) + X_train.shape[1:])
d = discriminator_model()
g = generator_model()
d_on_g = generator_containing_discriminator(g, d)
d_optim = SGD(lr=0.0005, momentum=0.9, nesterov=True)
g_optim = SGD(lr=0.0005, momentum=0.9, nesterov=True)
g.compile(loss='binary_crossentropy', optimizer="SGD")
d_on_g.compile(loss='binary_crossentropy', optimizer=g_optim)
d.trainable = True
d.compile(loss='binary_crossentropy', optimizer=d_optim)
for epoch in range(100):
print("Epoch is", epoch)
print("Number of batches", int(X_train.shape[0]/BATCH_SIZE))
for index in range(int(X_train.shape[0]/BATCH_SIZE)):
noise = np.random.uniform(-1, 1, size=(BATCH_SIZE, 100))
image_batch = X_train[index*BATCH_SIZE:(index+1)*BATCH_SIZE]
generated_images = g.predict(noise, verbose=0)
if index % 20 == 0:
image = combine_images(generated_images)
image = image*127.5+127.5
Image.fromarray(image.astype(np.uint8)).save(
str(epoch)+"_"+str(index)+".png")
X = np.concatenate((image_batch, generated_images))
y = [1] * BATCH_SIZE + [0] * BATCH_SIZE
d_loss = d.train_on_batch(X, y)
print("batch %d d_loss : %f" % (index, d_loss))
noise = np.random.uniform(-1, 1, (BATCH_SIZE, 100))
d.trainable = False
g_loss = d_on_g.train_on_batch(noise, [1] * BATCH_SIZE)
d.trainable = True
print("batch %d g_loss : %f" % (index, g_loss))
if index % 10 == 9:
g.save_weights('generator', True)
d.save_weights('discriminator', True)


def generate(BATCH_SIZE, nice=False):
g = generator_model()
g.compile(loss='binary_crossentropy', optimizer="SGD")
g.load_weights('generator')
if nice:
d = discriminator_model()
d.compile(loss='binary_crossentropy', optimizer="SGD")
d.load_weights('discriminator')
noise = np.random.uniform(-1, 1, (BATCH_SIZE*20, 100))
generated_images = g.predict(noise, verbose=1)
d_pret = d.predict(generated_images, verbose=1)
index = np.arange(0, BATCH_SIZE*20)
index.resize((BATCH_SIZE*20, 1))
pre_with_index = list(np.append(d_pret, index, axis=1))
pre_with_index.sort(key=lambda x: x[0], reverse=True)
nice_images = np.zeros((BATCH_SIZE,) + generated_images.shape[1:3], dtype=np.float32)
nice_images = nice_images[:, :, :, None]
for i in range(BATCH_SIZE):
idx = int(pre_with_index[i][1])
nice_images[i, :, :, 0] = generated_images[idx, :, :, 0]
image = combine_images(nice_images)
else:
noise = np.random.uniform(-1, 1, (BATCH_SIZE, 100))
generated_images = g.predict(noise, verbose=1)
image = combine_images(generated_images)
image = image*127.5+127.5
Image.fromarray(image.astype(np.uint8)).save(
"generated_image.png")


def get_args():
parser = argparse.ArgumentParser()
parser.add_argument("--mode", type=str)
parser.add_argument("--batch_size", type=int, default=128)
parser.add_argument("--nice", dest="nice", action="store_true")
parser.set_defaults(nice=False)
args = parser.parse_args()
return args

if __name__ == "__main__":
args = get_args()
if args.mode == "train":
train(BATCH_SIZE=args.batch_size)
elif args.mode == "generate":
generate(BATCH_SIZE=args.batch_size, nice=args.nice)
Empty file added log.txt
Empty file.
120 changes: 120 additions & 0 deletions preprocess_cat_dataset.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
## Modified version of https://github.com/microe/angora-blue/blob/master/cascade_training/describe.py by Erik Hovland
##### I modified it to work with Python 3, changed the paths and made it output a folder for images bigger than 64x64 and a folder for images bigger than 128x128

import cv2
import glob
import math
import sys, os
from tqdm import tqdm
def rotateCoords(coords, center, angleRadians):
# Positive y is down so reverse the angle, too.
angleRadians = -angleRadians
xs, ys = coords[::2], coords[1::2]
newCoords = []
n = min(len(xs), len(ys))
i = 0
centerX = center[0]
centerY = center[1]
cosAngle = math.cos(angleRadians)
sinAngle = math.sin(angleRadians)
while i < n:
xOffset = xs[i] - centerX
yOffset = ys[i] - centerY
newX = xOffset * cosAngle - yOffset * sinAngle + centerX
newY = xOffset * sinAngle + yOffset * cosAngle + centerY
newCoords += [newX, newY]
i += 1
return newCoords

def preprocessCatFace(coords, image):

leftEyeX, leftEyeY = coords[0], coords[1]
rightEyeX, rightEyeY = coords[2], coords[3]
mouthX = coords[4]
if leftEyeX > rightEyeX and leftEyeY < rightEyeY and \
mouthX > rightEyeX:
# The "right eye" is in the second quadrant of the face,
# while the "left eye" is in the fourth quadrant (from the
# viewer's perspective.) Swap the eyes' labels in order to
# simplify the rotation logic.
leftEyeX, rightEyeX = rightEyeX, leftEyeX
leftEyeY, rightEyeY = rightEyeY, leftEyeY

eyesCenter = (0.5 * (leftEyeX + rightEyeX),
0.5 * (leftEyeY + rightEyeY))

eyesDeltaX = rightEyeX - leftEyeX
eyesDeltaY = rightEyeY - leftEyeY
eyesAngleRadians = math.atan2(eyesDeltaY, eyesDeltaX)
eyesAngleDegrees = eyesAngleRadians * 180.0 / math.pi

# Straighten the image and fill in gray for blank borders.
rotation = cv2.getRotationMatrix2D(
eyesCenter, eyesAngleDegrees, 1.0)
imageSize = image.shape[1::-1]
straight = cv2.warpAffine(image, rotation, imageSize,
borderValue=(128, 128, 128))

# Straighten the coordinates of the features.
newCoords = rotateCoords(
coords, eyesCenter, eyesAngleRadians)

# Make the face as wide as the space between the ear bases.
w = abs(newCoords[16] - newCoords[6])
# Make the face square.
h = w
# Put the center point between the eyes at (0.5, 0.4) in
# proportion to the entire face.
minX = eyesCenter[0] - w/2
if minX < 0:
w += minX
minX = 0
minY = eyesCenter[1] - h*2/5
if minY < 0:
h += minY
minY = 0

# Crop the face.
crop = straight[int(minY):int(minY+h), int(minX):int(minX+w)]
# Return the crop.
return crop

def describePositive():
output = open('log.txt', 'w')
length = len(os.listdir("cat_dataset/"))
with tqdm(total=length) as pbar:
for c,imagePath in enumerate(glob.glob('cat_dataset/*.jpg')):
# Open the '.cat' annotation file associated with this
# image.
input = open('%s.cat' % imagePath, 'r')
# Read the coordinates of the cat features from the
# file. Discard the first number, which is the number
# of features.
coords = [int(i) for i in input.readline().split()[1:]]
# Read the image.
image = cv2.imread(imagePath)
# Straighten and crop the cat face.
crop = preprocessCatFace(coords, image)
if crop is None:
print('Failed to preprocess image at {}'.format(imagePath), file=sys.stderr)
continue
# Save the crop to folders based on size
h, w, colors = crop.shape
if min(h,w) >= 64:
Path1 = imagePath.replace("cat_dataset","cats_bigger_than_64x64")
cv2.imwrite(Path1, crop)
if min(h,w) >= 128:
Path2 = imagePath.replace("cat_dataset","cats_bigger_than_128x128")
cv2.imwrite(Path2, crop)
pbar.update(1)
# Append the cropped face and its bounds to the
# positive description.
#h, w = crop.shape[:2]
#print (cropPath, 1, 0, 0, w, h, file=output)


def main():
describePositive()

if __name__ == '__main__':
main()
42 changes: 42 additions & 0 deletions requirements-gpu.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
backports.weakref==1.0rc1
bleach==1.5.0
boto==2.48.0
bz2file==0.98
certifi==2017.7.27.1
chardet==3.0.4
cycler==0.10.0
decorator==4.1.2
h5py==2.7.0
html5lib==0.9999999
idna==2.6
imgaug==0.2.4
Keras==2.0.8
Markdown==2.2.0
matplotlib==2.0.2
networkx==1.11
numpy==1.13.1
olefile==0.44
opencv-python==3.3.0.10
pandas==0.20.3
Pillow==4.2.1
progressbar2==3.34.2
protobuf==3.4.0
pyemd==0.4.4
pyparsing==2.2.0
python-dateutil==2.6.1
python-utils==2.2.0
pytz==2017.2
PyWavelets==0.5.2
PyYAML==3.12
requests==2.18.4
scikit-image==0.13.0
scikit-learn==0.19.0
scipy==0.19.1
six==1.10.0
sklearn==0.0
smart-open==1.5.3
tensorflow-gpu==1.2.0
Theano==0.9.0
tqdm==4.18.0
urllib3==1.22
Werkzeug==0.12.2
33 changes: 17 additions & 16 deletions start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,23 @@
# wget -nc http://www.simoninithomas.com/data/cats.zip

## Setting up folder
unzip cats-dataset.zip -d cat_dataset
mkdir cat_dataset
#unzip cats-dataset.zip -d cat_dataset
unzip cats.zip
mv cat_dataset/CAT_00/* cat_dataset
rmdir cat_dataset/CAT_00
mv cat_dataset/CAT_01/* cat_dataset
rmdir cat_dataset/CAT_01
mv cat_dataset/CAT_02/* cat_dataset
rmdir cat_dataset/CAT_02
mv cat_dataset/CAT_03/* cat_dataset
rmdir cat_dataset/CAT_03
mv cat_dataset/CAT_04/* cat_dataset
rmdir cat_dataset/CAT_04
mv cat_dataset/CAT_05/* cat_dataset
rmdir cat_dataset/CAT_05
mv cat_dataset/CAT_06/* cat_dataset
rmdir cat_dataset/CAT_06
mv CAT_00/* cat_dataset
rmdir CAT_00
mv CAT_01/* cat_dataset
rmdir CAT_01
mv CAT_02/* cat_dataset
rmdir CAT_02
mv CAT_03/* cat_dataset
rmdir CAT_03
mv CAT_04/* cat_dataset
rmdir CAT_04
mv CAT_05/* cat_dataset
rmdir CAT_05
mv CAT_06/* cat_dataset
rmdir CAT_06

## Error correction
rm cat_dataset/00000003_019.jpg.cat
Expand All @@ -36,7 +37,7 @@ cd ..
## Preprocessing and putting in folders for different image sizes
mkdir cats_bigger_than_64x64
mkdir cats_bigger_than_128x128
python preprocess_cat_dataset.py
python3 preprocess_cat_dataset.py

## Removing cat_dataset
rm -r cat_dataset
Expand Down