from __future__ import division
import os

CAFFE_ROOT = '/home/kashefy/src/caffe/'
BASE_WEIGHTS='/home/kashefy/data/models/vgg-16/VGG_ILSVRC_16_layers_fcn.caffemodel'
PATH_SOLVER='/home/kashefy/data/models/fcn_segm/fcn-32s-Pascal-context/t2/solver2.prototxt'

if CAFFE_ROOT is not None:
    import sys
    sys.path.insert(0,  os.path.join(CAFFE_ROOT, 'python'))
import caffe
import numpy as np

# make a bilinear interpolation kernel
# credit @longjon
def upsample_filt(size):
    factor = (size + 1) // 2
    if size % 2 == 1:
        center = factor - 1
    else:
        center = factor - 0.5
    og = np.ogrid[:size, :size]
    return (1 - abs(og[0] - center) / factor) * \
           (1 - abs(og[1] - center) / factor)

# set parameters s.t. deconvolutional layers compute bilinear interpolation
# N.B. this is for deconvolution without groups
def interp_surgery(net, layers):
    for l in layers:
        m, k, h, w = net.params[l][0].data.shape
        if m != k:
            print 'input + output channels need to be the same'
            raise
        if h != w:
            print 'filters need to be square'
            raise
        filt = upsample_filt(h)
        net.params[l][0].data[range(m), range(k), :, :] = filt

# base net -- follow the editing model parameters example to make
# a fully convolutional VGG16 net.
# http://nbviewer.ipython.org/github/BVLC/caffe/blob/master/examples/net_surgery.ipynb

# init
caffe.set_mode_cpu()

solver = caffe.SGDSolver(PATH_SOLVER)

# do net surgery to set the deconvolution weights for bilinear interpolation
interp_layers = [k for k in solver.net.params.keys() if 'up' in k]
interp_surgery(solver.net, interp_layers)

# copy base weights for fine-tuning
solver.net.copy_from(BASE_WEIGHTS)




@@ -1,397 +1,45 @@
-from __future__ import division%0Aimport os%0A%0ACAFFE_ROOT = '/home/kashefy/src/caffe/'%0ABASE_WEIGHTS='/home/kashefy/data/models/vgg-16/VGG_ILSVRC_16_layers_fcn.caffemodel'%0APATH_SOLVER='/home/kashefy/data/models/fcn_segm/fcn-32s-Pascal-context/t2/solver2.prototxt'%0A%0Aif CAFFE_ROOT is not None:%0A    import sys%0A    sys.path.insert(0,  os.path.join(CAFFE_ROOT, 'python'))%0Aimport caffe%0Aimport numpy as np
+import os%0Aimport numpy as np%0Aimport caffe
 %0A%0A# 
@@ -873,17 +873,84 @@
 = filt%0A%0A
-#
+%0Adef init_up_bilinear(net, path_base_weights, key='up'):%0A    %22%22%22%0A   
  base ne
@@ -1005,18 +1005,16 @@
  to make
-%0A#
  a fully
@@ -1039,17 +1039,19 @@
 16 net.%0A
-#
+   
  http://
@@ -1132,77 +1132,25 @@
 ynb%0A
-%0A# init%0Acaffe.set_mode_cpu()%0A%0Asolver = caffe.SGDSolver(PATH_SOLVER)%0A%0A
+    %22%22%22%0A    %0A    
 # do
@@ -1222,16 +1222,20 @@
 olation%0A
+    
 interp_l
@@ -1254,23 +1254,16 @@
 or k in 
-solver.
 net.para
@@ -1279,19 +1279,22 @@
  if 
-'up'
+key
  in k%5D%0A
+    
 inte
@@ -1304,23 +1304,16 @@
 surgery(
-solver.
 net, int
@@ -1324,17 +1324,25 @@
 layers)%0A
-%0A
+    %0A    
 # copy b
@@ -1373,42 +1373,459 @@
 ing%0A
-solver.net.copy_from(BASE_WEIGHTS)%0A%0A
+    net.copy_from(path_base_weights)%0A    %0A    return%0A%0Aif __name__ == '__main__':%0A    %0A    caffe.set_mode_cpu()%0A    %0A    solver = caffe.SGDSolver(os.path.expanduser('~/models/fcn_segm/fcn-32s-Pascal-context/tx3/solver.prototxt'))%0A    init_up_bilinear(solver.net, os.path.expanduser('~/models/vgg-16/VGG_ILSVRC_16_layers_fcn.caffemodel'))%0A    solver.net.save(os.path.expanduser('~/models/fcn_segm/fcn-32s-Pascal-context/tx3/fcn.caffemodel'))%0A    %0A    pass
 %0A%0A

clean up deconv net surgery