In [1]:
import os
import subprocess as sub
import sys
from time import time

In [2]:
def convert_lmdb(txt_path=None, out_path=None, verbose=True):
    OUTDIR='/dev/shm'
    OUTNAME='aug_lmdb'
    DATA='/media/raid_arr/data/ndsb/folds'
    TXT='train0.txt'
    TOOLS='~/documents/caffe/build/tools'
    
    if not txt_path:
        txt_path = os.path.join(DATA, TXT)
    if not out_path:
        out_path = os.path.join(OUTDIR, OUTNAME)

    DATA_ROOT='/.'       # not important cuz I use abs path

    # Set RESIZE=true to resize the images to 256x256. Leave as false if images have
    # already been resized using another tool.
    RESIZE=True
    if RESIZE:
        RESIZE_HEIGHT=64
        RESIZE_WIDTH=64
    else:
        RESIZE_HEIGHT=0
        RESIZE_WIDTH=0

    if verbose:
        print "Creating lmdb..."
        tic = time()
    convert_cmd_list = ['GLOG_logtostderr=1', 
                       '%s/convert_imageset' % TOOLS, 
                       '--gray', 
                       '--resize_height=%s' % RESIZE_HEIGHT,
                       '--resize_width=%s' % RESIZE_WIDTH,
                       '--shuffle',
                       DATA_ROOT,
                       txt_path,
                       out_path,
                       ]
    if verbose:
        print convert_cmd_list
    
    os.system(' '.join(q + ['&']))
#     sub.Popen(convert_cmd_list, shell=True) # why doesnt this work
    
    if verbose:
        print 'Conversion to lmdb process spawned'

In [ ]:


In [9]:
import skimage
import skimage.transform

from skimage import data
import matplotlib.pyplot as plt
%matplotlib inline

img1 = skimage.transform.resize(data.camera(), (64, 64))
img2 = skimage.transform.resize(data.camera(), (64, 64))
# img2 = skimage.transform.resize(data.text(), (64, 64))
plt.imshow(img2, cmap='gray', interpolation='none')
im_list = [img1, img2]
img1.shape


Out[9]:
(64, 64)

In [10]:
"""
Taken from Sander Dieleman and mike1886
"""

import gzip
import itertools
import urllib
import pickle
from datetime import datetime
from time import time
import os
import sys
import copy
from matplotlib import pyplot
import numpy as np
from lasagne import layers
import lasagne.layers.cuda_convnet
from lasagne import nonlinearities
from lasagne import init
from nolearn.lasagne import BatchIterator
from nolearn.lasagne import NeuralNet
from pandas import DataFrame
from pandas.io.parsers import read_csv
from sklearn.utils import shuffle
import theano
from lasagne.updates import nesterov_momentum
from lasagne.updates import adagrad
from lasagne.updates import adadelta
from lasagne.updates import rmsprop
from collections import OrderedDict
from sklearn.base import clone

import skimage

import my_io as my_io


Using gpu device 0: GeForce GTX 580

In [11]:
PIXELS = 64
# def transform(Xb, yb):
def transform(im_list):
#     Xb, yb = super(DataAugmentationBatchIterator, self).transform(Xb, yb)
    augmentation_params = {
        'zoom_range': (0.9, 1.1),
        'rotation_range': (0, 360),
        'shear_range': (0, 10),
        'translation_range': (-4, 4),
    }

    IMAGE_WIDTH = PIXELS
    IMAGE_HEIGHT = PIXELS

    def fast_warp(img, tf, output_shape=(PIXELS,PIXELS), mode='nearest'):
        """
        This wrapper function is about five times faster than skimage.transform.warp, for our use case.
        """
        #m = tf._matrix
        m = tf.params
        img_wf = np.empty((output_shape[0], output_shape[1]), dtype='float32')
        #for k in xrange(1):
        #    img_wf[..., k] = skimage.transform._warps_cy._warp_fast(img[..., k], m, output_shape=output_shape, mode=mode)
        img_wf = skimage.transform._warps_cy._warp_fast(img, m, output_shape=output_shape, mode=mode)
        return img_wf

    def random_perturbation_transform(zoom_range, rotation_range, shear_range, translation_range, do_flip=True):
        shift_x = np.random.uniform(*translation_range)
        shift_y = np.random.uniform(*translation_range)
        translation = (shift_x, shift_y)

        # random rotation [0, 360]
        rotation = np.random.uniform(*rotation_range) # there is no post-augmentation, so full rotations here!

        # random shear [0, 20]
        shear = np.random.uniform(*shear_range)

        # random zoom [0.9, 1.1]
        # zoom = np.random.uniform(*zoom_range)
        log_zoom_range = [np.log(z) for z in zoom_range]
        zoom = np.exp(np.random.uniform(*log_zoom_range)) # for a zoom factor this sampling approach makes more sense.
        # the range should be multiplicatively symmetric, so [1/1.1, 1.1] instead of [0.9, 1.1] makes more sense.

        ## flip
        if do_flip and (np.random.randint(2) > 0): # flip half of the time
            shear += 180
            rotation += 180
            # shear by 180 degrees is equivalent to rotation by 180 degrees + flip.
            # So after that we rotate it another 180 degrees to get just the flip.            

        '''
        print "translation = ", translation
        print "rotation = ", rotation
        print "shear = ",shear
        print "zoom = ",zoom
        print ""
        '''

        return build_augmentation_transform(zoom, rotation, shear, translation)


    center_shift = np.array((IMAGE_HEIGHT, IMAGE_WIDTH)) / 2. - 0.5
    tform_center = skimage.transform.SimilarityTransform(translation=-center_shift)
    tform_uncenter = skimage.transform.SimilarityTransform(translation=center_shift)

    def build_augmentation_transform(zoom=1.0, rotation=0, shear=0, translation=(0, 0)):
        tform_augment = skimage.transform.AffineTransform(scale=(1/zoom, 1/zoom), 
                                                  rotation=np.deg2rad(rotation), 
                                                  shear=np.deg2rad(shear), 
                                                  translation=translation)
        tform = tform_center + tform_augment + tform_uncenter # shift to center, augment, shift back (for the rotation/shearing)
        return tform

#     tform_augment = random_perturbation_transform(**augmentation_params)
    tform_identity = skimage.transform.AffineTransform()
    tform_ds = skimage.transform.AffineTransform()

#     for i in range(Xb.shape[0]):
#         new = fast_warp(Xb[i][0], tform_ds + tform_augment + tform_identity, output_shape=(PIXELS,PIXELS), mode='nearest').astype('float32')
#         Xb[i,:] = new

    im_out_list = []
    for im in im_list:
        tform_augment = random_perturbation_transform(**augmentation_params) # different xform per image
        im_out_list.append(fast_warp(im, tform_ds + tform_augment + tform_identity, output_shape=(PIXELS,PIXELS), mode='nearest').astype('float32'))

    return im_out_list

In [324]:
im_list = [img1] *24000
tic = time()
transform(im_list)
toc = time() - tic
print toc


5.50422692299

In [327]:
plt.subplot(1, 2, 1)
plt.imshow(ret[0], cmap='gray', interpolation='none')

plt.subplot(1, 2, 2)
plt.imshow(ret[1], cmap='gray', interpolation='none')


Out[327]:
<matplotlib.image.AxesImage at 0x7f15175e0bd0>

In [307]:
plt.subplot(1, 2, 1)
plt.imshow(im_list[0], cmap='gray', interpolation='none')

plt.subplot(1, 2, 2)
plt.imshow(im_list[1], cmap='gray', interpolation='none')


Out[307]:
<matplotlib.image.AxesImage at 0x7f151c361210>
CAN WE MODIFY THE DB IN-PLACE?

In [12]:
import numpy as np
import sys
from PIL import Image
import matplotlib.pyplot as plt
from time import time
import lmdb
from caffe.proto import caffe_pb2
datum = caffe_pb2.Datum()

def bs_to_l(bs):
    """
    Grabs the label from the serialized binary
    """
    datum.ParseFromString(bs)
    return datum.label

def bs_to_im(bs, dtype=np.float32):
    """
    Converts serialized binary str from db into np.array image
    """
    datum.ParseFromString(bs)
    image_dims = (datum.height, datum.width)
#     im = np.array(Image.frombytes('L', image_dims, datum.data))[:, :, None].astype(dtype)
    im = np.array(Image.frombytes('L', image_dims, datum.data, 'raw', 'L', 0, 1))[:, :, None].astype(dtype)
    return im

In [28]:
db.close()

In [73]:
ORIG_DB_PATH = '/dev/shm/train0_lmdb'
AUG_DB_PATH = '/dev/shm/train0_aug_lmdb'

def create_aug_db(orig_db=ORIG_DB_PATH, aug_db=AUG_DB_PATH, verbose=True):
    tic = time ()
    db = lmdb.open(orig_db)
    new_db = lmdb.open(aug_db, map_size=1e12)
    with db.begin() as txn:
        with new_db.begin(write=True) as txn2:
            cursor1 = txn.cursor()
            for ii, (k, v) in enumerate(cursor1):
                datum.ParseFromString(v)  # not needed if the global `datum` is modified in fn elsewhere
                im = bs_to_im(v)
                new_im = transform([im.squeeze()])[0]
                datum.data = new_im.astype('uint8').tobytes()
        #         datum.label = datum.label
                new_bs = datum.SerializeToString()
                txn2.replace(k, new_bs)
                if ii % 5000 == 0:
                    if verbose:
                        print 'Processed:', ii
    toc = time() - tic
    if verbose:
        print 'Conversion of images from %s to %s took %s sec' % (orig_db, aug_db, toc)

In [74]:
create_aug_db()


Processed: 0
Processed: 5000
Processed: 10000
Processed: 15000
Processed: 20000
Conversion of images from /dev/shm/train0_lmdb to /dev/shm/train0_aug_lmdb took 12.6397800446 sec

In [72]:
with lmdb.open(AUG_DB_PATH).begin() as txn:
    c = txn.cursor()
    k, v = iter(c).next()
    im = bs_to_im(v)

In [71]:
# plt.imshow(im.squeeze(), cmap='gray')
plt.imshow(im.squeeze(), cmap='gray')


Out[71]:
<matplotlib.image.AxesImage at 0x7f8ed191f890>

In [533]:
print len(datum.data)
print len(new_im.astype('uint8').tobytes())
print len(v)
print len(datum.SerializeToString())
print db.max_key_size()


4096
4096
4109
4109
511

In [456]:
q = np.array(Image.frombytes('L', (64,64), datum.data, 'raw', 'L', 0, 1))[:, :, None]

In [512]:
# plt.imshow(im.squeeze())
qq = transform([im.squeeze()])[0]
plt.imshow(qq)


Out[512]:
<matplotlib.image.AxesImage at 0x7f15161e83d0>

In [77]:
from subprocess import Popen, PIPE, STDOUT

p = Popen('df -h', stdout = PIPE, 
        stderr = STDOUT, shell = True)
while True:
    line = p.stdout.readline()
    if not line: break
    print line


Filesystem      Size  Used Avail Use% Mounted on

/dev/sda1       222G  199G   13G  95% /

dev             5.9G     0  5.9G   0% /dev

run             5.9G  1.4M  5.9G   1% /run

tmpfs           5.9G  1.2G  4.8G  20% /dev/shm

tmpfs           5.9G     0  5.9G   0% /sys/fs/cgroup

/dev/sdg1       2.7T  106G  2.5T   5% /media/raid_arr

tmpfs           1.2G     0  1.2G   0% /run/user/10136

AFS             2.0T     0  2.0T   0% /afs

none            5.9G     0  5.9G   0% /ram


In [111]:
import re
s1 = 'I0301 18:22:24.630357 31254 solver.cpp:470] Iteration 3000, lr = 0.01'
s2 = 'I0301 18:22:56.391988 31254 solver.cpp:189] Iteration 3000, loss = 1.26269'
s3 = 'I0301 18:21:41.947240 31254 solver.cpp:266] Iteration 3000, Testing net (#0)'
s4 = 'I0301 18:22:56.391988 31254 solver.cpp:189] Iteration 3050, loss = 1.26269'

q = re.search(r'Iteration (\d+), loss', s1)
if q and int(q.groups()[0]) % 75 == 0:
    print iter_n, 'ok'


0 ok

In [ ]: