LCA Textures

Michael Teti

Machine Perception and Cognitive Robotics Lab

FAU Center for Complex Systems and Brain Sciences

3/31/2017

%matplotlib inline
import tensorflow as tf
import numpy as np
import scipy.io
import matplotlib.pyplot as plt
from scipy.cluster.vq import whiten
from sklearn.preprocessing import scale
from scipy.misc import *
import os
import glob
from scipy import ndimage as ndi
from skimage import color
from skimage.util import view_as_windows as vaw
import sys
from scipy.stats import mode

Initialize some useful parameters…

learning_rate = 10
subsample=8
LCAiters=20
imsz=200
ps=16
training_iterations = 20001
num_classes=25
display_step = 5000
k=100 #number of receptive fields to learn
batch_sz=300 #batch_size
testing_iters=1000

This is the image reader function. It will read all of the images in the directory given and make labels too.

def read_ims(directory, imsz):
  ''' Reads in images in subdirectories located in directory and 
      assigns a unique one-hot vector to each image in the respective
      folder.
      
      args:
           directory: the location of all the folders containing
                      each image class.
           imsz: resizes the width and height of each image to 
                 imsz. '''
 
  main_dir=os.getcwd()
  os.chdir(directory)
  num_channels=1

  num_ims=sum([len(files) for r, d, files in os.walk(directory)])
  imgs=np.zeros([num_ims, imsz, imsz, num_channels])
  labels=np.zeros([num_ims, len(os.listdir(os.getcwd()))])
  im_num=0
  class_num=0

  for f in os.listdir(os.getcwd()):
    if os.path.isdir(f):
        print('Folder name: %s'%(f))
        os.chdir(f)
        r0=np.argmin(np.sum(labels, axis=1))
        labels[r0:r0+len(glob.glob1(os.getcwd(), '*')), class_num]=1
        class_num+=1

        for filename in os.listdir(os.getcwd()):
          im=imresize(imread(filename), [imsz, imsz])
          im=im[:, :, np.newaxis]
          imgs[im_num, :, :, :]=im
          im_num+=1
            
        os.chdir(directory)
        
  os.chdir(main_dir)
  return imgs, labels

This function describes the network dynamics. It takes in some input data and some dictionary and returns the sparse code needed to reconstruct the data from the dictionary. It operates on local inhibition between patches.

def LCA(x, D, num_iters):
    
    D=tf.matmul(D, tf.diag(1/(tf.sqrt(tf.reduce_sum(D**2, 0))+1e-6)))
    u=tf.zeros([k, batch_sz])
    
    for iters in range(num_iters):
        a=(u-tf.sign(u)*.049)*(tf.cast(tf.abs(u)>.049, tf.float32)) 
        u=u+.01*(tf.matmul(tf.transpose(D), (x-tf.matmul(D, a)))-u-a)
        
        #D=D+(1/batch_sz)*tf.matmul(x-tf.matmul(D, a), tf.transpose(a))
    
    return a

This function allows us to display a bunch of patches at the same time. The argument X should consist of the patches tiled in the 2nd axis.

def montage(X):    
    m, n, count = np.shape(X)    
    mm = int(np.ceil(np.sqrt(count)))
    nn = mm
    M = np.zeros((mm * m, nn * n))

    image_id = 0
    for j in range(mm):
        for k in range(nn):
            if image_id >= count: 
                break
            sliceM, sliceN = j * m, k * n
            M[sliceN:sliceN + n, sliceM:sliceM + m] = X[:, :, image_id]
            image_id += 1
    return M
def mat2ten(X):
    zs=[int(np.sqrt(X.shape[0])),int(np.sqrt(X.shape[0])),X.shape[1]]
    Z=np.zeros(zs)
    for i in range(X.shape[1]):
        Z[:,:,i]=np.reshape(X[:,i],[zs[0],zs[1]])
    return Z
def plot(*args, **kwargs):
    fig=plt.figure()
    kwargs['plotsize']=kwargs.get('plotsize', [15, 15])
    plot_size=kwargs['plotsize']
    for i in range(len(args)):
        ax=fig.add_subplot(1, len(args), i+1)
        ax.imshow(args[i], cmap='gray')
    fig.set_size_inches(plot_size[0], plot_size[1])
    plt.show()

Read the images in and get the labels.

os.chdir('textures')
X, Y=read_ims(os.getcwd(), imsz)

Plot the labels to make sure they were loaded correctly.

plot(Y, plotsize=[50, 50])

Split the data into training and validation sets.

rand=np.random.randint(0, X.shape[0], size=X.shape[0])
num_test=np.int32(X.shape[0]*0.1)
X=X[rand, :, :, :]
Y=Y[rand, :]
testx=X[:num_test, :, :, :]
X=X[num_test:, :, :, :]
testy=Y[:num_test, :]
Y=Y[num_test:, :]

Create a matrix to store the dictionary from each class.

Dicts=np.zeros([ps**2, k*num_classes])

Create the data placeholder and the weight variable.

x=tf.placeholder("float", [ps**2, None])
w=tf.Variable(tf.random_normal([ps**2, k]))

Get the sparse code.

a=LCA(x, w, LCAiters)

This is the cost function and the optimizer we will use to train the dictionary.

cost=tf.norm(x-tf.matmul(w, a), ord=2)+0.01*tf.norm(a, ord=1)
optimizer=tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)
init=tf.global_variables_initializer()

For each class, get patches from images in that class and learn a dictionary.

for class_num in range(num_classes):
    class_=(Y[:, class_num]==1)
    #ims=X[class_, :, :, :]
    #ims=ims.reshape([ims.shape[0], -1]).transpose()
    #ims=scale(ims, axis=0, with_mean=True, with_std=True, copy=True)
    patches=vaw(X[class_, :, :, :], (1, ps, ps, X.shape[3]))
    patches=patches[:, ::subsample, ::subsample, :, :, :, :, :]
    patches=patches.reshape([patches.shape[0]*
                                patches.shape[1]*
                                patches.shape[2]*
                                patches.shape[3]*
                                patches.shape[4], -1]).transpose()
    #print(patches.shape)
    patches=0.1*scale(patches, axis=0, with_mean=True, with_std=True, copy=True)
    #labels=Y[class_, :]
    print('Training Patches')
    plot(montage(mat2ten(patches[:, :200])))
    

    
    with tf.Session() as sess:
        sess.run(init)
        
        for iters in range(training_iterations):
            batch=patches[:, np.random.randint(0, patches.shape[1], size=batch_sz)]
            _, c = sess.run([optimizer, cost], feed_dict={x: batch})

            if iters%display_step==0:
                print('Class: %d, Iteration: %d, Cost: %f'%(class_num, iters, c))
                wp=w.eval()
                plot(montage(mat2ten(wp)))
                A=sess.run(a, feed_dict={x:batch})
                A=np.sum(np.int32(A!=0.0), axis=0)
                plt.plot(np.arange(300), A)
        
    Dicts[:, class_num*k:class_num*k+k]=wp
np.save('texture_dict.npy', Dicts)