from keras.models import Model
from keras.layers import Flatten, Dense, Input
from keras import backend as K
from keras.layers import Conv2D, MaxPooling2D,AveragePooling2D, GlobalAveragePooling2D,GlobalMaxPooling2D
from keras_applications.imagenet_utils import _obtain_input_shape
from keras.engine.topology import get_source_inputs
import cv2
import numpy as np
from keras.optimizers import SGD
from scipy.spatial.distance import correlation


def VGG16(include_top=True, weights='imagenet',
          input_tensor=None, input_shape=None,
          pooling=None,
          classes=1000):
    # Determine proper input shape
    input_shape = _obtain_input_shape(input_shape,
                                      default_size=48,
                                      min_size=48,
                                      data_format=K.image_data_format(),
                                      require_flatten=include_top)

    if input_tensor is None:
        img_input = Input(shape=input_shape)
    else:
        if not K.is_keras_tensor(input_tensor):
            img_input = Input(tensor=input_tensor, shape=input_shape)
        else:
            img_input = input_tensor
    # Block 1
    x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv1')(img_input)
    x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv2')(x)
    x = MaxPooling2D((2, 2), strides=(2, 2), name='block1_pool')(x)

    # Block 2
    x = Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv1')(x)
    x = Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv2')(x)
    x = MaxPooling2D((2, 2), strides=(2, 2), name='block2_pool')(x)

    # Block 3
    x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv1')(x)
    x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv2')(x)
    x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv3')(x)
    x = MaxPooling2D((2, 2), strides=(2, 2), name='block3_pool')(x)
    
#     x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv1')(x)
#     x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv2')(x)
#     x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv3')(x)
#     x = MaxPooling2D((2, 2), strides=(2, 2), name='block4_pool')(x)
    
    if input_tensor is not None:
        inputs = get_source_inputs(input_tensor)
    else:
        inputs = img_input
    # Create model.
    model = Model(inputs, x, name='vgg16')

    weights_path = '/home/icsl/CitywideFootprinting/CarCounting/utility/VGG/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5'
    model.load_weights(weights_path,by_name=True)
    
    return model

model = VGG16()
model._make_predict_function()

# Input is the list of bounding boxes
def feature_extract(img_array_list):
    feature_list = []
    for img in img_array_list:
        img = np.expand_dims(img, axis=0)
        out = model.predict(img).flatten()
        feature_list.append(out)

    return feature_list




from keras.models import Model
from keras.layers import Flatten, Dense, Input
from keras import backend as K
from keras.layers import Conv2D, MaxPooling2D,AveragePooling2D, GlobalAveragePooling2D,GlobalMaxPooling2D
from keras_applications.imagenet_utils import _obtain_input_shape
from keras.engine.topology import get_source_inputs
import cv2
import numpy as np
from keras.optimizers import SGD
from scipy.spatial.distance import correlation


def VGG16(include_top=True, weights='imagenet',
          input_tensor=None, input_shape=None,
          pooling=None,
          classes=1000):
    # Determine proper input shape
    input_shape = _obtain_input_shape(input_shape,
                                      default_size=48,
                                      min_size=48,
                                      data_format=K.image_data_format(),
                                      require_flatten=include_top)

    if input_tensor is None:
        img_input = Input(shape=input_shape)
    else:
        if not K.is_keras_tensor(input_tensor):
            img_input = Input(tensor=input_tensor, shape=input_shape)
        else:
            img_input = input_tensor
    # Block 1
    x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv1')(img_input)
    x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv2')(x)
    x = MaxPooling2D((2, 2), strides=(2, 2), name='block1_pool')(x)

    # Block 2
    x = Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv1')(x)
    x = Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv2')(x)
    x = MaxPooling2D((2, 2), strides=(2, 2), name='block2_pool')(x)

    # Block 3
    x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv1')(x)
    x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv2')(x)
    x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv3')(x)
    x = MaxPooling2D((2, 2), strides=(2, 2), name='block3_pool')(x)
    
#     x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv1')(x)
#     x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv2')(x)
#     x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv3')(x)
#     x = MaxPooling2D((2, 2), strides=(2, 2), name='block4_pool')(x)
    
    if input_tensor is not None:
        inputs = get_source_inputs(input_tensor)
    else:
        inputs = img_input
    # Create model.
    model = Model(inputs, x, name='vgg16')

    weights_path = '/home/icsl/CitywideFootprinting/CarCounting/utility/VGG/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5'
    model.load_weights(weights_path,by_name=True)
    
    return model

model = VGG16()
model._make_predict_function()

# Input is the list of bounding boxes
def feature_extract(img_array_list):
    feature_list = []
    for img in img_array_list:
        img = np.expand_dims(img, axis=0)
        out = model.predict(img).flatten()
        feature_list.append(out)

    return feature_list




# Determine proper input shape # Block 1 # Block 2 # Block 3 #     x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv1')(x) #     x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv2')(x) #     x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv3')(x) #     x = MaxPooling2D((2, 2), strides=(2, 2), name='block4_pool')(x) # Create model. # Input is the list of bounding boxes