In [16]:
run draw_confetti.py tempconfetti 3 4 8
inkscape -e tempconfetti/0000_037_004.png temp.svg
inkscape -e tempconfetti/0001_031_003.png temp.svg
inkscape -e tempconfetti/0002_020_003.png temp.svg
inkscape -e tempconfetti/0003_027_004.png temp.svg
inkscape -e tempconfetti/0004_001_004.png temp.svg
inkscape -e tempconfetti/0005_035_004.png temp.svg
inkscape -e tempconfetti/0006_048_004.png temp.svg
inkscape -e tempconfetti/0007_027_003.png temp.svg
In [20]:
run draw_confetti.py tempconfetti 3 4 8
svg2png tempconfetti/0000_024_003.png
svg2png tempconfetti/0001_032_003.png
svg2png tempconfetti/0002_030_003.png
svg2png tempconfetti/0003_016_003.png
svg2png tempconfetti/0004_003_004.png
svg2png tempconfetti/0005_025_003.png
svg2png tempconfetti/0006_025_003.png
svg2png tempconfetti/0007_005_004.png
In [21]:
from IPython.display import Image as ipdimage
import glob
ipdimage(glob.glob('tempconfetti/*.png')[-1])
Out[21]:
In [19]:
# Adapted from Adrian Rosebrock https://www.pyimagesearch.com/2019/01/28/keras-regression-and-cnns/

# import the necessary packages
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import BatchNormalization
from tensorflow.keras.layers import Conv2D
from tensorflow.keras.layers import MaxPooling2D
from tensorflow.keras.layers import Activation
from tensorflow.keras.layers import Dropout
from tensorflow.keras.layers import Dense
from tensorflow.keras.layers import Flatten
from tensorflow.keras.layers import Input
from tensorflow.keras.models import Model

# build the network

def create_cnn(width, height, depth, nfilters=(16, 32, 64), regress=False):
    # initialize the input shape and channel dimension, assuming
    # TensorFlow/channels-last ordering
    inputShape = (height, width, depth)
    chanDim = -1

    # define the model input
    inputs = Input(shape=inputShape)

    # loop over the number of filters
    for (i, nf) in enumerate(nfilters):
        # if this is the first CONV layer then set the input
        # appropriately
        if i == 0:
            x = inputs

        # CONV => RELU => BN => POOL
        x = Conv2D(nf, (3, 3), padding="same")(x)
        x = Activation("relu")(x)
        x = BatchNormalization(axis=chanDim)(x)
        x = MaxPooling2D(pool_size=(2, 2))(x)

    # flatten the volume, then FC => RELU => BN => DROPOUT
    x = Flatten()(x)
    x = Dense(16)(x)
    x = Activation("relu")(x)
    x = BatchNormalization(axis=chanDim)(x)
    x = Dropout(0.5)(x)

    # apply another FC layer: JR not sure what the role of this is
    x = Dense(4)(x)
    x = Activation("relu")(x)

    x = Dense(2, activation="linear")(x)    ################  2D output

    # construct the CNN
    model = Model(inputs, x)

    # return the CNN
    return model

import glob
import cv2

from tensorflow.keras.optimizers import Adam
from sklearn.model_selection import train_test_split
import numpy as np
import os
import matplotlib.pyplot as plt
from os.path import join
from glob import glob
import pandas
from PIL import Image

def setup(datafolder, columns_to_use ):

    datafile   = join( datafolder , datafolder+'.txt' )
    # construct the path to the input .txt file that contains information
    # on each image in the dataset and then load the dataset
    print("Loading attributes...")
    
    #df = load_attributes(inputPath)  # replace with direct code to load attributes
    # df should be a numpy array with only the desired columns
    df = pandas.read_csv(datafile, sep=' ')[ columns_to_use ].copy()

    # load the images and then scale the pixel intensities to the
    # range [0, 1]
    print("Loading images...")
    #images = load_images(df, datafolder)#
    imagefiles = sorted( glob( join(datafolder,'*.png')   ))
    
    #images = np.array([cv2.imread(imagefile)[:,:,:3] for imagefile in imagefiles ])  # slice off opacity layer
    # Instead use PIL.Image to avoid problems some are having with installing opencv (cv2)
    images = np.array([np.array(Image.open(imagefile))[:,:,:3] for imagefile in imagefiles ])  # slice off opacity layer
    print(images.shape)
    images = images / 255.0

    # partition the data into training and testing splits using 75% of
    # the data for training and the remaining 25% for testing
    #split = train_test_split(df, images, test_size=0.25, random_state=42)   # can alternatively make your own function to do this
    #(trainAttrX, testAttrX, trainImagesX, testImagesX) = split
    
    # Trying to get rid of dependencies: I coded train/test split from scratch instead of using sklearn
    # partition the data into training and testing splits using 75% of
    # the data for training and the remaining 25% for testing
    nimages = len(images)
    ntest = int( nimages * 0.25 )
    intest = np.zeros(nimages,dtype=bool)
    intest[ np.random.choice( np.arange(nimages), ntest, replace=False ) ] = True
    intrain = ~intest
    testImagesX  = images[intest ,:,:,:].copy()
    trainImagesX = images[intrain,:,:,:].copy()
    testAttrX  = df.values[intest ,:]
    trainAttrX = df.values[intrain,:]
    
    # to rescale trainY and testY
    minAttr = trainAttrX.min(axis=0)
    maxAttr = trainAttrX.max(axis=0)
    rangeAttr = maxAttr - minAttr
    
    trainAttrX -= minAttr
    trainAttrX = (trainAttrX/rangeAttr)
    
    testAttrX -= minAttr
    testAttrX = (testAttrX/rangeAttr)
    
    # let's return minAttr and rangeAttr for use in interpretation of predictions
    return trainAttrX,testAttrX, trainImagesX, testImagesX, minAttr, rangeAttr
    

tra,testa,tri,testi, mina,rangea = setup('triangles_squares_pentagons',['npolygons', 'nv'])
print(mina,rangea)

# create our Convolutional Neural Network and then compile the model
# using mean squared error as our loss

#print(tri.shape)
nimages,h,w,depth = tri.shape

model = create_cnn(w,h, 3, regress=True)
opt = Adam(lr=1e-3, decay=1e-3 / 200)  # more sophisticated than plain gradient descent
model.compile(loss="mean_squared_error", optimizer=opt)

# train the model
print("Training model...")
model.fit(tri,tra, validation_data=(testi, testa),
        epochs=20, batch_size=8)

#model.save('model.h5')  # in case we want to take up training from were we left off

# make predictions on the testing data
print("Predicting")
preds = model.predict(testi)
# undo rescaling and shifting of data
preds = preds*rangea + mina  # predictions of network
testa = testa*rangea + mina  # actual values
# next: compare (graphically) predictions with actual values
Loading attributes...
Loading images...
(2000, 50, 75, 3)
[0 3] [50  2]
Training model...
Train on 1500 samples, validate on 500 samples
Epoch 1/20
1500/1500 [==============================] - 4s 3ms/sample - loss: 0.3626 - val_loss: 0.3610
Epoch 2/20
1500/1500 [==============================] - 3s 2ms/sample - loss: 0.1956 - val_loss: 0.2660
Epoch 3/20
1500/1500 [==============================] - 4s 2ms/sample - loss: 0.1558 - val_loss: 0.1495
Epoch 4/20
1500/1500 [==============================] - 4s 2ms/sample - loss: 0.1434 - val_loss: 0.1121
Epoch 5/20
1500/1500 [==============================] - 4s 2ms/sample - loss: 0.1267 - val_loss: 0.1059
Epoch 6/20
1500/1500 [==============================] - 3s 2ms/sample - loss: 0.1215 - val_loss: 0.1033
Epoch 7/20
1500/1500 [==============================] - 4s 2ms/sample - loss: 0.1145 - val_loss: 0.1025
Epoch 8/20
1500/1500 [==============================] - 4s 2ms/sample - loss: 0.1135 - val_loss: 0.1003
Epoch 9/20
1500/1500 [==============================] - 4s 2ms/sample - loss: 0.1087 - val_loss: 0.1002
Epoch 10/20
1500/1500 [==============================] - 4s 2ms/sample - loss: 0.1095 - val_loss: 0.0975
Epoch 11/20
1500/1500 [==============================] - 4s 2ms/sample - loss: 0.1048 - val_loss: 0.1002
Epoch 12/20
1500/1500 [==============================] - 4s 2ms/sample - loss: 0.1024 - val_loss: 0.1116
Epoch 13/20
1500/1500 [==============================] - 4s 2ms/sample - loss: 0.1026 - val_loss: 0.1646
Epoch 14/20
1500/1500 [==============================] - 4s 2ms/sample - loss: 0.0999 - val_loss: 0.1036
Epoch 15/20
1500/1500 [==============================] - 4s 2ms/sample - loss: 0.0985 - val_loss: 0.0975
Epoch 16/20
1500/1500 [==============================] - 3s 2ms/sample - loss: 0.0978 - val_loss: 0.0981
Epoch 17/20
1500/1500 [==============================] - 4s 2ms/sample - loss: 0.0973 - val_loss: 0.0977
Epoch 18/20
1500/1500 [==============================] - 3s 2ms/sample - loss: 0.0966 - val_loss: 0.0938
Epoch 19/20
1500/1500 [==============================] - 3s 2ms/sample - loss: 0.0932 - val_loss: 0.1059
Epoch 20/20
1500/1500 [==============================] - 3s 2ms/sample - loss: 0.0904 - val_loss: 2.5121
Predicting

NOTE TO SELF: do testing on the actual laptop I will be using in class!

In [ ]: