├── Phase-III ├── prediction │ ├── data_gen_test_for_4_class.py │ ├── prediction_for_4_classes.py │ └── convolutional.py └── training │ ├── data_gen_train_4_classes.py │ └── densenet_201_for_4_classes.py ├── Phase-I ├── prediction │ ├── data_gen_test.py │ ├── submission.py │ ├── prediction_custom.py │ ├── convolutional.py │ └── dense_all_keras.py ├── training │ ├── data_gen_train_all_data.py │ ├── gen_dense_201_feature.py │ ├── scale_layers.py │ ├── Camera_Model_Identification.py │ ├── convolutional.py │ └── dense_all_keras.py ├── L2_network │ └── l2_network.py └── create_feature_for_L2 │ └── dense_net_201_L2.py ├── Phase-II ├── training │ ├── data_gen_train_all_data.py │ └── densenet_201_dresden.py └── prediction │ └── prediction_custom.py └── Data_Augmentation ├── processMain_block.m ├── emd ├── emd_patchcreator_manip_just_extract_1st _residue.py ├── emd_patchcreator_just_extract_1st _residue.py └── emd_patchcreator_just_extract_1st _residue_png.py ├── best_patch_creator.py └── dirProc.m /Phase-III/prediction/data_gen_test_for_4_class.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Tue Nov 21 10:05:13 2017 5 | 6 | @author: RR 7 | """ 8 | 9 | test_dir = '' 10 | 11 | 12 | 13 | import random 14 | import cv2, glob, numpy as np, os 15 | from sklearn.feature_extraction import image 16 | 17 | test_imdir=[] 18 | test_label=[] 19 | 20 | images = glob.glob(test_dir +'/*') 21 | 22 | test_imdir=test_imdir+images -------------------------------------------------------------------------------- /Phase-I/prediction/data_gen_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Tue Nov 21 10:05:13 2017 5 | 6 | @author: root 7 | """ 8 | test_dir='' 9 | 10 | 11 | 12 | import random 13 | import glob, numpy as np, os 14 | from sklearn.feature_extraction import image 15 | # 16 | 17 | # 18 | test_imdir=[] 19 | test_label=[] 20 | 21 | images = glob.glob(test_dir +'/*') 22 | 23 | # 24 | test_imdir=test_imdir+images 25 | 26 | -------------------------------------------------------------------------------- /Phase-I/prediction/submission.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pandas as pd 3 | import os 4 | names = {1:'HTC-1-M7', 5 | 2:'iPhone-4s', 6 | 3:'iPhone-6', 7 | 4:'LG-Nexus-5x', 8 | 5:'Motorola-Droid-Maxx', 9 | 6:'Motorola-Nexus-6', 10 | 7:'Motorola-X', 11 | 8:'Samsung-Galaxy-Note3', 12 | 9:'Samsung-Galaxy-S4', 13 | 10:'Sony-NEX-7'} 14 | predicted_rakib =[] 15 | for i in range(len(y_gen2)): 16 | # predicted_rakib.append(names[y_gen2[i][0].astype(int)]) 17 | predicted_rakib.append(names[y_gen2[i]]) 18 | 19 | rafi = test_imdir 20 | main_rafi =[] 21 | 22 | ''' 23 | for windows 24 | ''' 25 | #for k in range(len(rafi)): 26 | # path = os.path.normpath(rafi[k]) 27 | # rafi2 = path.split(os.sep) 28 | # main_rafi.append(rafi2[3]) 29 | ''' 30 | for linux 31 | ''' 32 | for k in range(len(rafi)): 33 | path = os.path.normpath(rafi[k]) 34 | rafi2 = path.split(os.sep) 35 | main_rafi.append(rafi2[3]) 36 | df = pd.DataFrame(columns=['fname', 'camera']) 37 | df['fname'] = main_rafi 38 | df['camera'] = predicted_rakib 39 | df.to_csv("64.csv", index=False) -------------------------------------------------------------------------------- /Phase-II/training/data_gen_train_all_data.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Tue Nov 21 04:17:01 2017 5 | 6 | @author: root 7 | """ 8 | 9 | 10 | 11 | train_dir = '' 12 | 13 | model = [] #list of models 14 | 15 | import random 16 | import glob 17 | import numpy as np 18 | #import cv2, glob, numpy as np, os 19 | from sklearn.feature_extraction import image 20 | # 21 | 22 | val_imdir=[] 23 | val_label=[] 24 | 25 | 26 | 27 | train_imdir=[] 28 | train_label=[] 29 | 30 | 31 | 32 | 33 | for i in range(len(model)): 34 | 35 | images_all = glob.glob(train_dir + model[i] + '\\*') 36 | 37 | random.shuffle(images_all) 38 | 39 | a = len(images_all) * 0.85 40 | a = np.floor(len(images_all) * 0.85) 41 | a = int(a) 42 | b = a %64 43 | a = a - b 44 | c = len(images_all) 45 | d = c %64 46 | c = c - d 47 | 48 | images_all_train = images_all[0:a] 49 | images_all_val = images_all[a:c] 50 | 51 | 52 | label_train=[i]*len(images_all_train) 53 | label_val = [i]*len(images_all_val) 54 | 55 | train_imdir=train_imdir+images_all_train 56 | train_label=train_label+label_train 57 | 58 | val_imdir=val_imdir+images_all_val 59 | val_label=val_label+label_val 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /Phase-I/training/data_gen_train_all_data.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Tue Nov 21 04:17:01 2017 5 | 6 | @author: root 7 | """ 8 | 9 | train_dir = '' 10 | 11 | model = ['htc', 'iphone4', 'iphone6', 'lg', 'motodroid', 'motonex', 'motox', 'samsung_galaxynote', 'samsung_galaxys', 'sony'] 12 | 13 | import random 14 | import glob 15 | import numpy as np 16 | #import cv2, glob, numpy as np, os 17 | from sklearn.feature_extraction import image 18 | # 19 | 20 | val_imdir=[] 21 | val_label=[] 22 | 23 | # 24 | 25 | train_imdir=[] 26 | train_label=[] 27 | 28 | 29 | 30 | for i in range(len(model)): 31 | 32 | images_all = glob.glob(train_dir + model[i] + '\\*') 33 | 34 | random.shuffle(images_all) 35 | 36 | a = len(images_all) * 0.85 37 | a = np.floor(len(images_all) * 0.85) 38 | a = int(a) 39 | b = a %64 40 | a = a - b 41 | c = len(images_all) 42 | d = c %64 43 | c = c - d 44 | 45 | images_all_train = images_all[0:a] 46 | images_all_val = images_all[a:c] 47 | 48 | label_train=[i]*len(images_all_train) 49 | label_val = [i]*len(images_all_val) 50 | # 51 | train_imdir=train_imdir+images_all_train 52 | train_label=train_label+label_train 53 | 54 | val_imdir=val_imdir+images_all_val 55 | val_label=val_label+label_val 56 | ## 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /Phase-III/training/data_gen_train_4_classes.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Tue Nov 21 04:17:01 2017 5 | @author: root 6 | """ 7 | 8 | 9 | 10 | train_dir = '' 11 | 12 | model = ['*gamma*', '*jpeg*', '*resize*', '*unalt'] 13 | 14 | import random 15 | import glob 16 | import numpy as np 17 | #import cv2, glob, numpy as np, os 18 | from sklearn.feature_extraction import image 19 | # 20 | 21 | val_imdir=[] 22 | val_label=[] 23 | 24 | # 25 | 26 | train_imdir=[] 27 | train_label=[] 28 | 29 | 30 | 31 | for i in range(len(model)): 32 | 33 | images_all = glob.glob(train_dir + model[i] + '\\*\\*') 34 | 35 | random.shuffle(images_all) 36 | 37 | a = len(images_all) * 0.85 38 | a = np.floor(len(images_all) * 0.85) 39 | a = int(a) 40 | b = a %64 41 | a = a - b 42 | c = len(images_all) 43 | d = c %64 44 | c = c - d 45 | 46 | images_all_train = images_all[0:a] 47 | images_all_val = images_all[a:c] 48 | 49 | 50 | label_train=[i]*len(images_all_train) 51 | label_val = [i]*len(images_all_val) 52 | 53 | 54 | # 55 | train_imdir=train_imdir+images_all_train 56 | train_label=train_label+label_train 57 | 58 | 59 | val_imdir=val_imdir+images_all_val 60 | val_label=val_label+label_val 61 | 62 | ## 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /Phase-I/training/gen_dense_201_feature.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Sat Apr 14 20:56:08 2018 4 | 5 | @author: User 6 | """ 7 | from keras.layers.core import Dense, Dropout, Activation 8 | from keras.layers.convolutional import Convolution2D 9 | from keras.layers.pooling import AveragePooling2D, GlobalAveragePooling2D, MaxPooling2D, GlobalMaxPooling2D 10 | from keras.layers.normalization import BatchNormalization 11 | from keras.models import Model 12 | import keras.backend as K 13 | import numpy as np 14 | from keras.applications.densenet import DenseNet201 15 | from imageio import imread 16 | 17 | img_rows = 256 18 | img_cols = 256 19 | channel = 3 20 | 21 | all_feature = np.zeros((len(train_imdir),1920)) 22 | 23 | def get_model(): 24 | 25 | base_model = DenseNet201(include_top=False, weights='imagenet', input_shape= (img_rows, img_cols, channel), pooling=None, classes=None) 26 | x = base_model.output 27 | x = GlobalAveragePooling2D()(x) 28 | zz = Dense(10, activation = 'softmax')(x) 29 | 30 | model = Model(inputs = base_model.input, outputs= zz) 31 | return model 32 | 33 | model =get_model() 34 | model.load_weights('') 35 | model.summary() 36 | 37 | intermediate_layer_model = Model(inputs=model.input, 38 | outputs=model.get_layer(index = -2).output) 39 | 40 | for i in range(len(train_imdir)): 41 | img = np.expand_dims(imread(train_imdir[i]), axis = 0) 42 | all_feature[i] = intermediate_layer_model.predict(img)[0] 43 | if(i%10==0): 44 | print(i) -------------------------------------------------------------------------------- /Data_Augmentation/processMain_block.m: -------------------------------------------------------------------------------- 1 | close all;clear;clc 2 | % NAVIGATE IT TO THE DATASET FOLDER (UPON 3 | % RUNNING THE PROGRAM YOU WILL BE PROMPTED 4 | % TO SELECT A FOLDER). e.g. IF 'D:\DATASET' 5 | % FOLDER IS SELECTED, A NEW FOLDER WITH THE 6 | % NAME 'D:\DATASET Processed' WILL BE CREATED 7 | % WITH ALL SUBFOLDERS CONTAING FIRST 50 8 | % PROCESSED IMAGES 9 | 10 | % select folder to process 11 | topFolder = uigetdir(cd,'Select a Folder to Process'); 12 | if topFolder == 0 13 | return 14 | end 15 | 16 | destFolder = uigetdir(cd,'Select a Destination Folder'); 17 | if destFolder == 0 18 | error('Select a destination folder location'); 19 | end 20 | destFolderName = 'Data (Processed)'; 21 | [~,name] = fileparts(destFolder); 22 | if ~strcmp(destFolderName, name) 23 | destFolder = fullfile(destFolder, destFolderName); 24 | end 25 | 26 | 27 | disp('running...'); 28 | 29 | folders = split(genpath(topFolder), pathsep); 30 | folders = folders(1:end-1); 31 | 32 | % loop through each folder 33 | for param = [512] 34 | operation = 'block'; 35 | writeFmt = 'png'; 36 | qf = 100; 37 | 38 | for i = 1:length(folders) 39 | thisFolder = folders{i}; 40 | pattern = fullfile(thisFolder, '*.jpg'); 41 | files = dir(pattern); 42 | if isempty(files) 43 | continue 44 | end 45 | 46 | if floor(param) == param % if isInteger(param) 47 | loc = sprintf('%s_%d_%s',operation,param,writeFmt); 48 | else 49 | loc = sprintf('%s_%0.1f_%s',operation,param,writeFmt); 50 | end 51 | loc = replace(loc, '.', '_'); 52 | loc = replace(thisFolder, topFolder, fullfile(destFolder, loc)); 53 | if ~exist(loc,'dir') 54 | mkdir(loc); 55 | end 56 | disp(loc); 57 | delete(fullfile(thisFolder,'Thumbs.db')); 58 | dirProc(thisFolder,loc,operation,param,writeFmt,qf); 59 | end 60 | end 61 | disp('complete.'); -------------------------------------------------------------------------------- /Phase-I/L2_network/l2_network.py: -------------------------------------------------------------------------------- 1 | # Create your first MLP in Keras 2 | from __future__ import print_function 3 | 4 | import keras 5 | from keras.datasets import mnist 6 | from keras.models import Sequential 7 | from keras.layers import Dense, Dropout, Flatten 8 | from keras.layers import Conv2D, MaxPooling2D,GlobalMaxPooling2D 9 | from keras import backend as K 10 | import numpy as np 11 | from keras.engine.topology import Input 12 | from keras.models import Model 13 | from keras.optimizers import SGD 14 | 15 | batch_size = 64 16 | num_classes = 10 17 | epochs = 50 18 | 19 | # input image dimensions 20 | img_rows, img_cols = 3, 1920 21 | 22 | # the data, split between train and test sets 23 | x_train = np.load('model_64_128_256_feat.npy', 'r') 24 | y_train = np.load('l2_model_label.npy', 'r') 25 | 26 | if K.image_data_format() == 'channels_first': 27 | x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols) 28 | input_shape = (1, img_rows, img_cols) 29 | else: 30 | x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1) 31 | # x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1) 32 | input_shape = (img_rows, img_cols, 1) 33 | 34 | 35 | print('x_train shape:', x_train.shape) 36 | print(x_train.shape[0], 'train samples') 37 | # 38 | # convert class vectors to binary class matrices 39 | y_train = keras.utils.to_categorical(y_train, num_classes) 40 | 41 | 42 | 43 | inp = Input(shape = input_shape) 44 | 45 | x =Conv2D(1,(3,1),strides = (3,1),activation = 'relu')(inp) 46 | x = Flatten()(x) 47 | 48 | x = Dense(512, activation = 'relu')(x) 49 | 50 | x = Dense(256, activation = 'relu')(x) 51 | 52 | zz = Dense(10, activation = 'softmax')(x) 53 | model = Model(inputs = inp, outputs= zz) 54 | model.summary() 55 | 56 | 57 | sgd = SGD(lr=1e-03, decay=1e-6, momentum=0.9, nesterov=True) 58 | model.compile(optimizer=sgd , loss='categorical_crossentropy', metrics=['accuracy']) 59 | 60 | model.fit(x_train, y_train, 61 | batch_size=batch_size, 62 | epochs=epochs) -------------------------------------------------------------------------------- /Data_Augmentation/emd/emd_patchcreator_manip_just_extract_1st _residue.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import math 3 | import time 4 | from PIL import Image 5 | from imageio import imwrite 6 | import glob 7 | import os 8 | from pyemd.EMD2d import EMD2D 9 | import time 10 | from scipy.misc import imread 11 | from scipy.stats import mode 12 | import random 13 | import numpy as np 14 | from sklearn.utils import shuffle 15 | from skimage.restoration import denoise_wavelet 16 | from skimage import img_as_float,img_as_uint 17 | import matplotlib.pyplot as plt 18 | import pickle 19 | import matplotlib.pyplot as plt 20 | from imageio import imwrite 21 | from PIL import Image 22 | 23 | imreadpath = '' 24 | imwritepath = '' 25 | 26 | model = ['htc', 'iphone4', 'iphone6', 'lg', 'motodroid', 'motonex', 'motox', 'samsung_galaxynote', 'samsung_galaxys', 'sony'] 27 | #list of all models 28 | 29 | num_row = 256 30 | num_col = 256 31 | 32 | 33 | for m in range(len(model)): 34 | start = time.time() 35 | images = glob.glob(imreadpath + model[m] + '/*') 36 | 37 | os.makedirs(imwritepath+model[m]) 38 | img_no = 0 39 | for img_name in images: 40 | img_no += 1 41 | 42 | im = Image.open(img_name) 43 | single_image = np.array(im) 44 | 45 | red = single_image[:,:,0] 46 | green = single_image[:,:,1] 47 | blue = single_image[:,:,2] 48 | 49 | img_emd_parts = np.zeros((num_row,num_col,3)) 50 | 51 | emd2d = EMD2D() 52 | try: 53 | IMFred = emd2d.emd(red, max_imf = -1) 54 | except: 55 | continue 56 | try: 57 | IMFgreen = emd2d.emd(green, max_imf = -1) 58 | except: 59 | continue 60 | try: 61 | IMFblue = emd2d.emd(blue, max_imf = -1) 62 | except: 63 | continue 64 | try: 65 | img_emd_parts[:,:,0] = IMFred[0] 66 | except: 67 | continue 68 | try: 69 | img_emd_parts[:,:,1] = IMFgreen[0] 70 | except: 71 | continue 72 | try: 73 | img_emd_parts[:,:,2] = IMFblue[0] 74 | except: 75 | continue 76 | 77 | 78 | img_emd_parts = img_emd_parts.astype('float32') 79 | image_wrt_dir = imwritepath+ model[m] +'\\emd_{}.dat'.format(img_name.split(os.sep)[-1].split('.')[0]) 80 | img_emd_parts.dump(image_wrt_dir) 81 | print(img_no) 82 | print(time.time()-start) 83 | 84 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /Data_Augmentation/emd/emd_patchcreator_just_extract_1st _residue.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import math 3 | import time 4 | from PIL import Image 5 | from imageio import imwrite 6 | import glob 7 | import os 8 | from pyemd.EMD2d import EMD2D 9 | import time 10 | from scipy.misc import imread 11 | from scipy.stats import mode 12 | import random 13 | import numpy as np 14 | from sklearn.utils import shuffle 15 | from skimage.restoration import denoise_wavelet 16 | from skimage import img_as_float,img_as_uint 17 | import matplotlib.pyplot as plt 18 | import pickle 19 | import matplotlib.pyplot as plt 20 | from imageio import imwrite 21 | from PIL import Image 22 | imreadpath = '' 23 | imwritepath = '' 24 | 25 | model = ['htc', 'iphone4', 'iphone6', 'lg', 'motodroid', 'motonex', 'motox', 'samsung_galaxynote', 'samsung_galaxys', 'sony'] 26 | #list of all models 27 | 28 | num_row = 256 29 | num_col = 256 30 | 31 | 32 | for m in range(len(model)): 33 | start = time.time() 34 | images = glob.glob(imreadpath + model[m] + '/*') 35 | os.makedirs(imwritepath+model[m]) 36 | img_no = 0 37 | for img_name in images: 38 | img_no += 1 39 | 40 | im = Image.open(img_name) 41 | single_image = np.array(im) 42 | 43 | red = single_image[:,:,0] 44 | green = single_image[:,:,1] 45 | blue = single_image[:,:,2] 46 | 47 | img_emd_parts = np.zeros((num_row,num_col,3)) 48 | 49 | emd2d = EMD2D() 50 | try: 51 | IMFred = emd2d.emd(red, max_imf = -1) 52 | except: 53 | continue 54 | try: 55 | IMFgreen = emd2d.emd(green, max_imf = -1) 56 | except: 57 | continue 58 | try: 59 | IMFblue = emd2d.emd(blue, max_imf = -1) 60 | except: 61 | continue 62 | try: 63 | img_emd_parts[:,:,0] = IMFred[0] 64 | except: 65 | continue 66 | try: 67 | img_emd_parts[:,:,1] = IMFgreen[0] 68 | except: 69 | continue 70 | try: 71 | img_emd_parts[:,:,2] = IMFblue[0] 72 | except: 73 | continue 74 | 75 | img_emd_parts = img_emd_parts.astype('float32') 76 | image_wrt_dir = imwritepath+ model[m] +'\\emd_{}.dat'.format(img_name.split(os.sep)[-1].split('.')[0]) 77 | img_emd_parts.dump(image_wrt_dir) 78 | # imwrite(image_wrt_dir,sub_1st_imf5) 79 | print(img_no) 80 | print(time.time()-start) 81 | 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /Data_Augmentation/emd/emd_patchcreator_just_extract_1st _residue_png.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import math 3 | import time 4 | from PIL import Image 5 | from imageio import imwrite 6 | import glob 7 | import os 8 | from pyemd.EMD2d import EMD2D 9 | import time 10 | from scipy.misc import imread 11 | from scipy.stats import mode 12 | import random 13 | import numpy as np 14 | from sklearn.utils import shuffle 15 | from skimage.restoration import denoise_wavelet 16 | from skimage import img_as_float,img_as_uint 17 | import matplotlib.pyplot as plt 18 | import pickle 19 | from imageio import imwrite 20 | from PIL import Image 21 | imreadpath = '' 22 | imwritepath = '' 23 | 24 | model = ['htc', 'iphone4', 'iphone6', 'lg', 'motodroid', 'motonex', 'motox', 'samsung_galaxynote', 'samsung_galaxys', 'sony'] 25 | #list of all models 26 | 27 | num_row = 256 28 | num_col = 256 29 | 30 | 31 | for m in range(len(model)): 32 | start = time.time() 33 | images = glob.glob(imreadpath + model[m] + '/*') 34 | 35 | os.makedirs(imwritepath+model[m]) 36 | img_no = 0 37 | for img_name in images: 38 | img_no += 1 39 | 40 | im = Image.open(img_name) 41 | single_image = np.array(im) 42 | # single_image = np.load(img_name) 43 | red = single_image[:,:,0] 44 | green = single_image[:,:,1] 45 | blue = single_image[:,:,2] 46 | 47 | img_emd_parts = np.zeros((num_row,num_col,3)) 48 | 49 | emd2d = EMD2D() 50 | try: 51 | IMFred = emd2d.emd(red, max_imf = -1) 52 | except: 53 | continue 54 | try: 55 | IMFgreen = emd2d.emd(green, max_imf = -1) 56 | except: 57 | continue 58 | try: 59 | IMFblue = emd2d.emd(blue, max_imf = -1) 60 | except: 61 | continue 62 | try: 63 | img_emd_parts[:,:,0] = IMFred[0] 64 | except: 65 | continue 66 | try: 67 | img_emd_parts[:,:,1] = IMFgreen[0] 68 | except: 69 | continue 70 | try: 71 | img_emd_parts[:,:,2] = IMFblue[0] 72 | except: 73 | continue 74 | 75 | sub_1st_imf = img_emd_parts.astype('float32') 76 | 77 | sub_1st_imf2 = sub_1st_imf - np.min(sub_1st_imf)*np.ones(sub_1st_imf.shape) 78 | sub_1st_imf3 = sub_1st_imf2/np.max(sub_1st_imf2) 79 | sub_1st_imf4 = sub_1st_imf3*255 80 | sub_1st_imf5 = np.around(sub_1st_imf4).astype('uint8') 81 | image_wrt_dir = imwritepath+ model[m] +'\\kaggle_emd_{}.png'.format(img_name.split(os.sep)[-1].split('.')[0]) 82 | # sub_1st_imf.dump(image_wrt_dir) 83 | imwrite(image_wrt_dir,sub_1st_imf5) 84 | print(img_no) 85 | print(time.time()-start) 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /Data_Augmentation/best_patch_creator.py: -------------------------------------------------------------------------------- 1 | """ 2 | Created on Sat Dec 30 15:41:11 2017 3 | 4 | @author: DSP 5 | """ 6 | import math 7 | import numpy as np 8 | import os 9 | import glob 10 | import time 11 | from imageio import imwrite 12 | from PIL import Image 13 | from operator import itemgetter 14 | import matplotlib.pyplot as plt 15 | start = time.time() 16 | 17 | 18 | def patch_creator(single_image_dir,num_row = 128,num_col = 128): 19 | im = Image.open(single_image_dir) 20 | single_image = np.array(im) 21 | a , b = single_image.shape[0], single_image.shape[1] 22 | k , m = a//num_row, b//num_col 23 | ind_row = np.repeat(range(0,k*num_row,num_row), m) 24 | ind_col = np.tile(range(0,m*num_col,num_col), k) 25 | image_patches = [single_image[a1:a1+num_row,a2:a2+num_col,:] for (a1,a2) in zip(ind_row,ind_col)] 26 | return image_patches 27 | 28 | def find_quality(patches, sel_no = 3): 29 | alpha = 0.7 30 | beta = 4 31 | gamma = math.log(0.01) 32 | Constant_1 = np.repeat(np.array([alpha]),3)*np.repeat(np.array([beta]),3) 33 | Constant_2 = np.repeat(np.array([1]),3)-np.repeat(np.array([alpha]),3) 34 | Constant_3 = np.repeat(np.array([1]),3) 35 | zipped = [] 36 | quality = [] 37 | for i in patches: 38 | img = i/255.0 39 | chnl_mean = np.mean(img, axis=(0,1)) 40 | chnl_std = np.std(img, axis=(0,1), ddof = 1) 41 | part_1 = Constant_1*(chnl_mean - chnl_mean*chnl_mean) 42 | part_2 = Constant_2*(Constant_3 - np.exp(np.repeat(np.array([gamma]),3)*chnl_std)) 43 | img_qulty = np.mean(part_1 + part_2) 44 | quality.append(img_qulty) 45 | zipped = zip(quality, patches) 46 | zipped = sorted(zipped,key=itemgetter(0)) 47 | best_patches = zipped[-sel_no:] 48 | return best_patches 49 | 50 | 51 | def saveimg(wrt_dir, img_counter, zipped_patches): 52 | k = 0 53 | for i in zipped_patches: 54 | image_wrt_dir = wrt_dir +'//{}_{}.tif'.format(img_counter, k) 55 | imwrite(image_wrt_dir,i[1]) 56 | k += 1 57 | 58 | 59 | folders = ['resize_0.5','resize_0.8','resize_1.5','resize_2.0','gamma_0.8','gamma_1.2','jpeg_70','jpeg_90','unalt'] 60 | model = ['htc', 'iphone4', 'iphone6', 'lg', 'motodroid', 'motonex', 'motox', 'samsung_galaxynote', 'samsung_galaxys', 'sony'] 61 | 62 | imreadpath = '' 63 | imwritepath = '' 64 | 65 | num_row = 256 66 | num_col = 256 67 | sel_no = 20 68 | folder = 8 69 | 70 | for m in range(len(model)): 71 | images = glob.glob(imreadpath + folders[folder] + '\\'+ model[m] + '\\' +'/*') 72 | os.makedirs(imwritepath+folders[folder]+'\\'+model[m]+'\\') 73 | img_no = 0 74 | for img_name in images: 75 | img_no += 1 76 | patches = patch_creator(img_name,num_row = num_row,num_col = num_col) 77 | selected_patches = find_quality(patches,sel_no = sel_no) 78 | k = 0 79 | for img in selected_patches: 80 | k += 1 81 | image_wrt_dir = imwritepath +folders[folder]+'\\'+model[m] +'/{}_{}_{}.png'.format(model[m],img_name.split(os.sep)[-1].split('.')[0],k) 82 | # img[1].dump(image_wrt_dir) 83 | imwrite(image_wrt_dir,img[1]) 84 | print(model[m]+"_"+str(img_no)) 85 | -------------------------------------------------------------------------------- /Phase-II/prediction/prediction_custom.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Sat Dec 30 02:54:56 2017 5 | 6 | @author: root 7 | """ 8 | import tensorflow as tf 9 | from keras.optimizers import SGD 10 | from keras.layers import Input, merge, ZeroPadding2D, concatenate 11 | from keras.layers.core import Dense, Dropout, Activation 12 | from keras.layers.convolutional import Convolution2D 13 | from keras.layers.pooling import AveragePooling2D, GlobalAveragePooling2D, MaxPooling2D, GlobalMaxPooling2D 14 | from keras.layers.normalization import BatchNormalization 15 | from keras.models import Model 16 | import keras.backend as Kyyfffffffff 17 | from keras.callbacks import ModelCheckpoint, EarlyStopping, ReduceLROnPlateau 18 | from dense_all_keras import DenseNetImageNet201 19 | from sklearn.metrics import log_loss 20 | #from scale_layers import Scale 21 | import keras 22 | from keras.callbacks import LearningRateScheduler 23 | from skimage.restoration import denoise_wavelet 24 | from skimage import img_as_float,img_as_uint 25 | from keras.utils import np_utils 26 | import numpy as np 27 | from scipy.misc import imread 28 | #from imageio import imread 29 | import math 30 | from scipy import signal 31 | from statistics import mode 32 | import random 33 | from dense_all_keras import DenseNetImageNet201 34 | from keras.applications.densenet import DenseNet201 35 | 36 | img_rows = 256 37 | img_cols = 256 38 | num_classes = 27 39 | channel = 3 40 | batch_size=16 41 | 42 | base_model = DenseNetImageNet201(input_shape = None, 43 | bottleneck=True, 44 | reduction=0.5, 45 | dropout_rate=0.0, 46 | weight_decay=1e-4, 47 | include_top=False, 48 | weights=None, 49 | input_tensor=None, 50 | pooling=None, 51 | classes=None 52 | ) 53 | x = base_model.output 54 | x= GlobalAveragePooling2D()(x) 55 | 56 | zz = Dense(10, activation = 'softmax')(x) 57 | 58 | 59 | final_model = Model(inputs = base_model.input, outputs = zz) 60 | 61 | final_model.load_weights('') 62 | 63 | 64 | def patch_creator(img): 65 | 66 | p=0; 67 | img_in = imread(img) 68 | 69 | m, n = img_in.shape[0:2] 70 | a, b = 512//img_rows, 512//img_cols 71 | all_patch = np.zeros((a*b, img_rows, img_cols, 3)) 72 | for k in range(a): 73 | for l in range (b): 74 | all_patch[p,:,:,:] = img_in[(k*img_rows):(k+1)*img_rows, (l*img_cols):(l+1)*img_cols, :] 75 | p+=1 76 | 77 | return all_patch 78 | 79 | y_gen2 = np.zeros((len(test_imdir),1)) 80 | y_pred_2 = np.zeros((len(test_imdir),batch_size,10)) 81 | for i in range(len(test_imdir)): 82 | 83 | patch = patch_creator(test_imdir[i]) 84 | y_pred_2[i] = final_model.predict(patch, batch_size = batch_size) 85 | 86 | print(i) 87 | y_pred2 = np.average(y_pred_2,axis = 1) 88 | y_gen2 = y_pred2.argmax(axis=1)+1 89 | 90 | -------------------------------------------------------------------------------- /Phase-III/prediction/prediction_for_4_classes.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Sat Dec 30 02:54:56 2017 5 | 6 | @author: RR 7 | """ 8 | import tensorflow as tf 9 | from keras.optimizers import SGD 10 | from keras.layers import Input, merge, ZeroPadding2D, concatenate 11 | from keras.layers.core import Dense, Dropout, Activation 12 | from keras.layers.convolutional import Convolution2D 13 | from keras.layers.pooling import AveragePooling2D, GlobalAveragePooling2D, MaxPooling2D, GlobalMaxPooling2D 14 | from keras.layers.normalization import BatchNormalization 15 | from keras.models import Model 16 | import keras.backend as K 17 | from keras.callbacks import ModelCheckpoint, EarlyStopping, ReduceLROnPlateau 18 | from sklearn.metrics import log_loss 19 | import keras 20 | from keras.callbacks import LearningRateScheduler 21 | from skimage.restoration import denoise_wavelet 22 | from skimage import img_as_float,img_as_uint 23 | from keras.utils import np_utils 24 | import numpy as np 25 | from scipy.misc import imread 26 | #from imageio import imread 27 | import math 28 | from scipy import signal 29 | import random 30 | from dense_all_keras import DenseNetImageNet201 31 | from keras.applications.densenet import DenseNet201 32 | 33 | 34 | img_rows = 256 35 | img_cols = 256 36 | num_classes = 4 37 | channel = 3 38 | batch_size= 4 #change batch size according to the size of the image 39 | 40 | base_model = DenseNetImageNet201(input_shape = None, 41 | bottleneck=True, 42 | reduction=0.5, 43 | dropout_rate=0.0, 44 | weight_decay=1e-4, 45 | include_top=False, 46 | weights=None, 47 | input_tensor=None, 48 | pooling=None, 49 | classes=None 50 | ) 51 | x = base_model.output 52 | x= GlobalAveragePooling2D()(x) 53 | 54 | zz = Dense(4, activation = 'softmax')(x) 55 | model = Model(inputs = base_model.input, outputs= zz) 56 | 57 | 58 | model_final = Model(inputs = base_model.input, outputs = x) 59 | 60 | rr = model_final.output 61 | 62 | oo = Dense(4, activation = 'softmax')(rr) 63 | 64 | final_model = Model(inputs = model_final.input, outputs= oo) 65 | final_model.load_weights('phase_3_128_weight.h5') 66 | 67 | 68 | '''1=gamma, 2=jpeg, 3=resize, 4=unalt''' 69 | def patch_creator(img): 70 | 71 | p=0; 72 | img_in = imread(img) 73 | 74 | m, n = img_in.shape[0:2] 75 | a, b = m//img_rows, n//img_cols 76 | all_patch = np.zeros((a*b, img_rows, img_cols, 3)) 77 | for k in range(a): 78 | for l in range (b): 79 | all_patch[p,:,:,:] = img_in[(k*img_rows):(k+1)*img_rows, (l*img_cols):(l+1)*img_cols, :] 80 | p+=1 81 | 82 | return all_patch 83 | y_gen2 = np.zeros((len(test_imdir),1)) 84 | y_pred_2 = np.zeros((len(test_imdir),batch_size,4)) 85 | 86 | for i in range(len(test_imdir)): 87 | patch = patch_creator(test_imdir[i]) 88 | y_pred_2[i] = final_model.predict(patch, batch_size = batch_size) 89 | print(i) 90 | y_pred2 = np.average(y_pred_2,axis = 1) 91 | y_gen2 = y_pred2.argmax(axis=1)+1 92 | result = np.bincount(y_gen2) 93 | 94 | -------------------------------------------------------------------------------- /Phase-I/prediction/prediction_custom.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Sat Dec 30 02:54:56 2017 5 | 6 | @author: root 7 | """ 8 | import tensorflow as tf 9 | from keras.optimizers import SGD 10 | from keras.layers import Input, merge, ZeroPadding2D, concatenate 11 | from keras.layers.core import Dense, Dropout, Activation 12 | from keras.layers.convolutional import Convolution2D 13 | from keras.layers.pooling import AveragePooling2D, GlobalAveragePooling2D, MaxPooling2D, GlobalMaxPooling2D 14 | from keras.layers.normalization import BatchNormalization 15 | from keras.models import Model 16 | import keras.backend as Kyyfffffffff 17 | from keras.callbacks import ModelCheckpoint, EarlyStopping, ReduceLROnPlateau 18 | from dense_all_keras import DenseNetImageNet201 19 | from sklearn.metrics import log_loss 20 | #from scale_layers import Scale 21 | import keras 22 | from keras.callbacks import LearningRateScheduler 23 | from skimage.restoration import denoise_wavelet 24 | from skimage import img_as_float,img_as_uint 25 | from keras.utils import np_utils 26 | import numpy as np 27 | from scipy.misc import imread 28 | #from imageio import imread 29 | import math 30 | from scipy import signal 31 | from statistics import mode 32 | import random 33 | #from dense_all_keras import DenseNetImageNet201 34 | from keras.applications.densenet import DenseNet201 35 | 36 | img_rows = 64 37 | img_cols = 64 38 | num_classes = 10 39 | channel = 3 40 | batch_size=64 41 | 42 | base_model = DenseNetImageNet201(input_shape = None, 43 | bottleneck=True, 44 | reduction=0.5, 45 | dropout_rate=0.0, 46 | weight_decay=1e-4, 47 | include_top=False, 48 | weights=None, 49 | input_tensor=None, 50 | pooling=None, 51 | classes=None 52 | ) 53 | x = base_model.output 54 | x= GlobalAveragePooling2D()(x) 55 | 56 | zz = Dense(10, activation = 'softmax')(x) 57 | 58 | 59 | model_final = Model(inputs = base_model.input, outputs = x) 60 | 61 | rr = model_final.output 62 | 63 | oo = Dense(10, activation = 'softmax')(rr) 64 | 65 | final_model = Model(inputs = model_final.input, outputs= oo) 66 | 67 | final_model.load_weights('') 68 | 69 | def patch_creator(img): 70 | 71 | p=0; 72 | img_in = imread(img) 73 | m, n = img_in.shape[0:2] 74 | a, b = 512//img_rows, 512//img_cols 75 | all_patch = np.zeros((a*b, img_rows, img_cols, 3)) 76 | for k in range(a): 77 | for l in range (b): 78 | all_patch[p,:,:,:] = img_in[(k*img_rows):(k+1)*img_rows, (l*img_cols):(l+1)*img_cols, :] 79 | p+=1 80 | 81 | return all_patch 82 | 83 | y_gen2 = np.zeros((len(test_imdir),1)) 84 | y_pred_2 = np.zeros((len(test_imdir),batch_size,10)) 85 | for i in range(len(test_imdir)): 86 | 87 | patch = patch_creator(test_imdir[i]) 88 | y_pred_2[i] = final_model.predict(patch, batch_size = batch_size) 89 | 90 | print(i) 91 | y_pred2 = np.average(y_pred_2,axis = 1) 92 | y_gen2 = y_pred2.argmax(axis=1)+1 93 | 94 | -------------------------------------------------------------------------------- /Phase-I/training/scale_layers.py: -------------------------------------------------------------------------------- 1 | from keras.layers.core import Layer 2 | from keras.engine import InputSpec 3 | from keras import backend as K 4 | try: 5 | from keras import initializations 6 | except ImportError: 7 | from keras import initializers as initializations 8 | 9 | class Scale(Layer): 10 | '''Learns a set of weights and biases used for scaling the input data. 11 | the output consists simply in an element-wise multiplication of the input 12 | and a sum of a set of constants: 13 | 14 | out = in * gamma + beta, 15 | 16 | where 'gamma' and 'beta' are the weights and biases larned. 17 | 18 | # Arguments 19 | axis: integer, axis along which to normalize in mode 0. For instance, 20 | if your input tensor has shape (samples, channels, rows, cols), 21 | set axis to 1 to normalize per feature map (channels axis). 22 | momentum: momentum in the computation of the 23 | exponential average of the mean and standard deviation 24 | of the data, for feature-wise normalization. 25 | weights: Initialization weights. 26 | List of 2 Numpy arrays, with shapes: 27 | `[(input_shape,), (input_shape,)]` 28 | beta_init: name of initialization function for shift parameter 29 | (see [initializations](../initializations.md)), or alternatively, 30 | Theano/TensorFlow function to use for weights initialization. 31 | This parameter is only relevant if you don't pass a `weights` argument. 32 | gamma_init: name of initialization function for scale parameter (see 33 | [initializations](../initializations.md)), or alternatively, 34 | Theano/TensorFlow function to use for weights initialization. 35 | This parameter is only relevant if you don't pass a `weights` argument. 36 | ''' 37 | def __init__(self, weights=None, axis=-1, momentum = 0.9, beta_init='zero', gamma_init='one', **kwargs): 38 | self.momentum = momentum 39 | self.axis = axis 40 | self.beta_init = initializations.get(beta_init) 41 | self.gamma_init = initializations.get(gamma_init) 42 | self.initial_weights = weights 43 | super(Scale, self).__init__(**kwargs) 44 | 45 | def build(self, input_shape): 46 | self.input_spec = [InputSpec(shape=input_shape)] 47 | shape = (int(input_shape[self.axis]),) 48 | 49 | # Compatibility with TensorFlow >= 1.0.0 50 | self.gamma = K.variable(self.gamma_init(shape), name='{}_gamma'.format(self.name)) 51 | self.beta = K.variable(self.beta_init(shape), name='{}_beta'.format(self.name)) 52 | #self.gamma = self.gamma_init(shape, name='{}_gamma'.format(self.name)) 53 | #self.beta = self.beta_init(shape, name='{}_beta'.format(self.name)) 54 | self.trainable_weights = [self.gamma, self.beta] 55 | 56 | if self.initial_weights is not None: 57 | self.set_weights(self.initial_weights) 58 | del self.initial_weights 59 | 60 | def call(self, x, mask=None): 61 | input_shape = self.input_spec[0].shape 62 | broadcast_shape = [1] * len(input_shape) 63 | broadcast_shape[self.axis] = input_shape[self.axis] 64 | 65 | out = K.reshape(self.gamma, broadcast_shape) * x + K.reshape(self.beta, broadcast_shape) 66 | return out 67 | 68 | def get_config(self): 69 | config = {"momentum": self.momentum, "axis": self.axis} 70 | base_config = super(Scale, self).get_config() 71 | return dict(list(base_config.items()) + list(config.items())) 72 | -------------------------------------------------------------------------------- /Phase-I/create_feature_for_L2/dense_net_201_L2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Fri Dec 29 23:58:15 2017 5 | 6 | @author: root 7 | """ 8 | 9 | import tensorflow as tf 10 | from keras.optimizers import SGD 11 | from keras.layers import Input, merge, ZeroPadding2D, concatenate 12 | from keras.layers.core import Dense, Dropout, Activation 13 | from keras.layers.convolutional import Convolution2D 14 | from keras.layers.pooling import AveragePooling2D, GlobalAveragePooling2D, MaxPooling2D, GlobalMaxPooling2D 15 | from keras.layers.normalization import BatchNormalization 16 | from keras.models import Model 17 | import keras.backend as K 18 | from keras.callbacks import ModelCheckpoint, EarlyStopping, ReduceLROnPlateau 19 | 20 | from sklearn.metrics import log_loss 21 | #from scale_layers import Scale 22 | import keras 23 | from keras.callbacks import LearningRateScheduler 24 | from skimage.restoration import denoise_wavelet 25 | from skimage import img_as_float,img_as_uint 26 | from keras.utils import np_utils 27 | import numpy as np 28 | #from scipy.misc import imread 29 | from imageio import imread 30 | import math 31 | from scipy import signal 32 | import random 33 | from dense_all_keras import DenseNetImageNet201 34 | from densenet_201_new import get_model 35 | 36 | # 37 | #img_cols1 = 256 38 | 39 | img_rows = 256 40 | img_cols = 256 41 | 42 | #img_rows2 = 128 43 | #img_cols2 = 128 44 | 45 | def get_all_patch(img, size): 46 | num = int(256//size) 47 | all_patch = np.zeros((num*num, size, size, 3)) 48 | p=0 49 | for i in range(num): 50 | for j in range(num): 51 | all_patch[p]=img[i+size,j+size,:] 52 | p+=1 53 | return all_patch 54 | 55 | combined_train = list(zip(train_imdir, train_label)) 56 | random.shuffle(combined_train) 57 | 58 | train_imdir[:], train_label[:] = zip(*combined_train) 59 | 60 | combined_val= list(zip(val_imdir, val_label)) 61 | random.shuffle(combined_val) 62 | 63 | val_imdir[:], val_label[:] = zip(*combined_val) 64 | 65 | def augment(src, choice): 66 | 67 | if choice == 0: 68 | src = np.rot90(src, 1) 69 | 70 | if choice == 1: 71 | src = src 72 | 73 | if choice == 2: 74 | src = np.rot90(src, 2) 75 | 76 | if choice == 3: 77 | src = np.rot90(src, 3) 78 | return src 79 | 80 | from tqdm import tqdm 81 | 82 | def generate_processed_batch(inp_data,label,batch_size = 50): 83 | 84 | batch_images = np.zeros((batch_size, img_rows, img_cols, 3)) 85 | batch_label = np.zeros((batch_size, 10)) 86 | while 1: 87 | for i_data in range(0,len(inp_data),batch_size): 88 | for i_batch in range(batch_size): 89 | print(i_data+i_batch) 90 | img = imread(inp_data[i_data+i_batch]) 91 | img = augment(img, np.random.randint(4)) 92 | 93 | a = 256 - img_rows 94 | d = np.random.randint(0,a) 95 | img = img[d:d+img_rows,d:d+img_rows,:] 96 | 97 | lab = np_utils.to_categorical(label[i_data+i_batch],10) 98 | 99 | batch_images[i_batch] = img 100 | batch_label[i_batch] = lab 101 | 102 | yield batch_images, batch_label 103 | 104 | 105 | 106 | batchsize = 16 107 | 108 | 109 | 110 | model_64_path = '' #model trained on 256X256 patches 111 | model_64 = get_model(model_64_path) 112 | model_128_path = '' #same model 113 | model_128 = get_model(model_128_path) 114 | model_256_path = '' #same model 115 | model_256 = purana_model(model_256_path) 116 | 117 | model_256_feat = np.zeros((200000,1920)) 118 | model_128_feat = np.zeros((200000,1920)) 119 | model_64_feat = np.zeros((200000,1920)) 120 | 121 | print('start') 122 | 123 | for i in tqdm(range(200000)): 124 | img = imread(train_imdir[i]) 125 | img_128 = get_all_patch(img,128) 126 | img_64 = get_all_patch(img, 64) 127 | img_256 = np.expand_dims(img, axis= 0) 128 | model_256_feat[i] = model_256.predict(img_256) 129 | model_128_feat[i] = np.average(model_128.predict_on_batch(img_128), axis = 0) 130 | model_64_feat[i] = np.average(model_64.predict_on_batch(img_64), axis = 0) 131 | 132 | np.save('model_128_feat', model_128_feat) 133 | np.save('model_64_feat', model_64_feat) 134 | np.save('model_256_feat', model_256_feat) 135 | np.save('l2_model_label', train_label) 136 | 137 | -------------------------------------------------------------------------------- /Phase-III/training/densenet_201_for_4_classes.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Fri Dec 29 23:58:15 2017 5 | 6 | @author: root 7 | """ 8 | import tensorflow as tf 9 | from keras.optimizers import SGD 10 | from keras.layers import Input, merge, ZeroPadding2D, concatenate 11 | from keras.layers.core import Dense, Dropout, Activation 12 | from keras.layers.convolutional import Convolution2D 13 | from keras.layers.pooling import AveragePooling2D, GlobalAveragePooling2D, MaxPooling2D, GlobalMaxPooling2D 14 | from keras.layers.normalization import BatchNormalization 15 | from keras.models import Model 16 | import keras.backend as K 17 | from keras.callbacks import ModelCheckpoint, EarlyStopping, ReduceLROnPlateau 18 | 19 | from sklearn.metrics import log_loss 20 | #from scale_layers import Scale 21 | import keras 22 | from keras.callbacks import LearningRateScheduler 23 | from skimage.restoration import denoise_wavelet 24 | from skimage import img_as_float,img_as_uint 25 | from keras.utils import np_utils 26 | import numpy as np 27 | #from scipy.misc import imread 28 | from imageio import imread 29 | import math 30 | from scipy import signal 31 | import random 32 | 33 | img_rows = 128 34 | img_cols = 128 35 | 36 | combined_train = list(zip(train_imdir, train_label)) 37 | random.shuffle(combined_train) 38 | 39 | train_imdir[:], train_label[:] = zip(*combined_train) 40 | 41 | 42 | combined_val= list(zip(val_imdir, val_label)) 43 | random.shuffle(combined_val) 44 | 45 | val_imdir[:], val_label[:] = zip(*combined_val) 46 | 47 | def augment(src, choice): 48 | 49 | if choice == 0: 50 | src = np.rot90(src, 1) 51 | 52 | if choice == 1: 53 | src = src 54 | 55 | if choice == 2: 56 | src = np.rot90(src, 2) 57 | 58 | if choice == 3: 59 | src = np.rot90(src, 3) 60 | return src 61 | 62 | def generate_processed_batch(inp_data,label,batch_size = 50): 63 | 64 | batch_images = np.zeros((batch_size, img_rows, img_cols, 3)) 65 | batch_label = np.zeros((batch_size, 4)) 66 | while 1: 67 | for i_data in range(0,len(inp_data),batch_size): 68 | for i_batch in range(batch_size): 69 | if i_data + i_batch >= len(inp_data): 70 | continue 71 | 72 | 73 | img = imread(inp_data[i_data+i_batch]) 74 | 75 | a = 256 - img_rows 76 | d = np.random.randint(0,a) 77 | img = img[d:d+img_rows,d:d+img_rows,:] 78 | img = augment(img, np.random.randint(4)) 79 | 80 | lab = np_utils.to_categorical(label[i_data+i_batch],4) 81 | 82 | batch_images[i_batch] = img 83 | batch_label[i_batch] = lab 84 | 85 | yield batch_images, batch_label 86 | 87 | callbacks_list= [ 88 | keras.callbacks.ModelCheckpoint( 89 | filepath='desne_process_re.h5', 90 | mode='min', 91 | monitor='val_loss', 92 | save_best_only=True, 93 | verbose = 1 94 | ), 95 | EarlyStopping(monitor='val_loss', patience=3, verbose=1, min_delta=1e-3), 96 | ReduceLROnPlateau(monitor='val_loss', factor=0.1, patience=2, cooldown=1, 97 | verbose=1, min_lr=1e-7) 98 | ] 99 | 100 | batchsize = 16 101 | 102 | training_gen = generate_processed_batch(train_imdir, train_label, batchsize) 103 | val_gen = generate_processed_batch(val_imdir,val_label, batchsize) 104 | 105 | from keras.applications.densenet import DenseNet201 106 | 107 | 108 | img_rows, img_cols = img_rows, img_rows # Resolution of inputs 109 | channel = 3 110 | num_classes = 4 111 | batch_size = batchsize 112 | nb_epoch = 50 113 | 114 | n = batchsize 115 | # Load our model 116 | base_model = DenseNet201(include_top=False, weights='imagenet', input_shape= (img_rows, img_cols, channel), pooling=None, classes=None) 117 | 118 | x = base_model.output 119 | x_avg= GlobalAveragePooling2D()(x) 120 | zz = Dense(10, activation = 'softmax')(x_avg) 121 | 122 | model = Model(inputs = base_model.input, outputs= zz) 123 | 124 | 125 | xx = Dense(4, activation = 'softmax')(x_avg) 126 | model_new = Model(inputs = base_model.input, outputs= xx) 127 | 128 | model_new.summary() 129 | sgd = SGD(lr=1e-03, decay=1e-6, momentum=0.9, nesterov=True) 130 | model_new.compile(optimizer=sgd, loss='categorical_crossentropy', metrics=['accuracy']) 131 | 132 | model_new.fit_generator(training_gen,steps_per_epoch=int(len(train_imdir)/n),nb_epoch=nb_epoch,validation_data=val_gen, 133 | validation_steps=int(len(val_imdir)/n),callbacks=callbacks_list) 134 | -------------------------------------------------------------------------------- /Phase-II/training/densenet_201_dresden.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Fri Dec 29 23:58:15 2017 5 | 6 | @author: root 7 | """ 8 | import tensorflow as tf 9 | from keras.optimizers import SGD 10 | from keras.layers import Input, merge, ZeroPadding2D, concatenate, Reshape, multiply 11 | from keras.layers.core import Dense, Dropout, Activation 12 | from keras.layers.convolutional import Convolution2D 13 | from keras.layers.pooling import AveragePooling2D, GlobalAveragePooling2D, GlobalAveragePooling1D, MaxPooling2D 14 | from keras.layers.normalization import BatchNormalization 15 | from keras.models import Model 16 | import keras.backend as K 17 | 18 | from sklearn.metrics import log_loss 19 | #from scale_layers import Scale 20 | import keras 21 | from keras.callbacks import LearningRateScheduler 22 | from skimage.restoration import denoise_wavelet 23 | from skimage import img_as_float,img_as_uint 24 | from keras.utils import np_utils 25 | import numpy as np 26 | from scipy.misc import imread 27 | #from imageio import imread 28 | import math 29 | from scipy import signal 30 | import random 31 | from dense_all_keras import DenseNetImageNet201 32 | 33 | img_rows = 256 34 | img_cols = 256 35 | num_classes = 27 36 | 37 | combined_train = list(zip(train_imdir, train_label)) 38 | random.shuffle(combined_train) 39 | 40 | train_imdir[:], train_label[:] = zip(*combined_train) 41 | 42 | 43 | combined_val= list(zip(val_imdir, val_label)) 44 | random.shuffle(combined_val) 45 | 46 | val_imdir[:], val_label[:] = zip(*combined_val) 47 | 48 | def augment(src, choice): 49 | 50 | if choice == 0: 51 | src = np.rot90(src, 1) 52 | 53 | if choice == 1: 54 | src = src 55 | 56 | if choice == 2: 57 | src = np.rot90(src, 2) 58 | 59 | if choice == 3: 60 | src = np.rot90(src, 3) 61 | return src 62 | 63 | 64 | 65 | 66 | def generate_processed_batch(inp_data,label,batch_size = 50): 67 | 68 | batch_images = np.zeros((batch_size, img_rows, img_cols, 3)) 69 | batch_label = np.zeros((batch_size, num_classes)) 70 | while 1: 71 | for i_data in range(0,len(inp_data),batch_size): 72 | for i_batch in range(batch_size): 73 | if i_data + i_batch >= len(inp_data): 74 | continue 75 | try: 76 | img = imread(inp_data[i_data+i_batch]) 77 | except Exception: 78 | img = imread(inp_data[i_data+i_batch+1]) 79 | 80 | try: 81 | img = augment(img, np.random.randint(4)) 82 | except Exception: 83 | pass 84 | 85 | lab = np_utils.to_categorical(label[i_data+i_batch],num_classes) 86 | 87 | try: 88 | batch_images[i_batch] = img 89 | except Exception: 90 | print(i_data+i_batch) 91 | batch_label[i_batch] = lab 92 | 93 | yield batch_images, batch_label 94 | 95 | 96 | callbacks_list= [ 97 | keras.callbacks.ModelCheckpoint( 98 | filepath='', 99 | mode='min', 100 | monitor='val_loss', 101 | save_best_only=True, 102 | verbose = 1 103 | ), 104 | EarlyStopping(monitor='val_loss', patience=3, verbose=1, min_delta=1e-3), 105 | ReduceLROnPlateau(monitor='val_loss', factor=0.1, patience=2, cooldown=1, 106 | verbose=1, min_lr=1e-7) 107 | ] 108 | 109 | batchsize = 16 110 | # 111 | training_gen = generate_processed_batch(train_imdir, train_label, batchsize) 112 | val_gen = generate_processed_batch(val_imdir,val_label, batchsize) 113 | 114 | def get_model(): 115 | base_model = DenseNetImageNet201(input_shape = None, 116 | bottleneck=True, 117 | reduction=0.5, 118 | dropout_rate=0.0, 119 | weight_decay=1e-4, 120 | include_top=False, 121 | weights=None, 122 | input_tensor=None, 123 | pooling=None, 124 | classes=None, 125 | ) 126 | x = base_model.output 127 | x= GlobalAveragePooling2D()(x) 128 | 129 | zz = Dense(10, activation = 'softmax')(x) 130 | model = Model(inputs = base_model.input, outputs= zz) 131 | model.load_weights('') #weight of model trained in Phase I 132 | 133 | 134 | model_dresden = Model(inputs = base_model.input, outputs = x) 135 | p = model_dresden.output 136 | q = Dense(num_classes, activation = 'softmax')(p) 137 | 138 | model_final = Model(inputs = model_dresden.input, outputs= q) 139 | 140 | return model_final 141 | 142 | 143 | img_rows, img_cols = img_rows, img_rows # Resolution of inputs 144 | channel = 3 145 | num_classes = num_classes 146 | nb_epoch = 50 147 | 148 | 149 | batch_size=16 150 | model = get_model() 151 | model.summary() 152 | sgd = SGD(lr=1e-3, decay=1e-6, momentum=0.9, nesterov=True) 153 | model.compile(optimizer=sgd, loss='categorical_crossentropy', metrics=['accuracy']) 154 | 155 | model.fit_generator(training_gen,steps_per_epoch= len(train_imdir)/batch_size,nb_epoch=nb_epoch,validation_data=val_gen, 156 | validation_steps=len(val_imdir)/batch_size,callbacks=callbacks_list,initial_epoch = 1) 157 | -------------------------------------------------------------------------------- /Phase-I/training/Camera_Model_Identification.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Mon Oct 15 13:05:52 2018 4 | 5 | @author: DSP 6 | """ 7 | import numpy as np 8 | import random, glob, os 9 | from tqdm import tqdm 10 | 11 | # directory of the input image 12 | core_dir = "" 13 | 14 | processings = [ name.split(os.sep)[-1] for name in glob.glob(core_dir)] 15 | camera_models = [ name.split(os.sep)[-1] for name in glob.glob(glob.glob(core_dir)[0]+'\\*')] 16 | 17 | train_dir, train_label, val_dir, val_label = [],[],[],[] 18 | 19 | split_ratio = np.array([0.85, 0.15]); #train, valid, test; sum must be 1.0 20 | 21 | batch_size = 4 22 | 23 | for label in tqdm(range(len(camera_models))): 24 | model_images = glob.glob(core_dir + '\\' + camera_models[label] +'\\*') 25 | splt = np.cumsum(batch_size*((len(model_images)*split_ratio).astype(int)//batch_size)) 26 | train_dir = train_dir + model_images[0:splt[0]] 27 | train_label = train_label + [label]*len(model_images[0:splt[0]]) 28 | val_dir = val_dir + model_images[splt[0]:splt[1]] 29 | val_label = val_label + [label]*len(model_images[splt[0]:splt[1]]) 30 | test_dir = test_dir + model_images[splt[1]:splt[2]] 31 | test_label = test_label + [label]*len(model_images[splt[1]:splt[2]]) 32 | label += 1 33 | 34 | train_data = list(zip(train_dir, train_label)) 35 | valid_data = list(zip(val_dir, val_label)) 36 | test_data = list(zip(test_dir, test_label)) 37 | 38 | del train_dir, train_label, val_dir, val_label, test_dir, test_label 39 | del label, model_images, split_ratio, splt 40 | 41 | #%% 42 | import tensorflow as tf 43 | import keras 44 | import keras.backend as K 45 | from keras.layers import Input, merge, ZeroPadding2D, concatenate 46 | from keras.layers.core import Dense, Dropout, Activation 47 | from keras.layers.convolutional import Convolution2D 48 | from keras.layers.pooling import AveragePooling2D, GlobalAveragePooling2D, MaxPooling2D, GlobalMaxPooling2D 49 | from keras.layers.normalization import BatchNormalization 50 | from keras.models import Model 51 | from keras.optimizers import SGD 52 | from keras.callbacks import LearningRateScheduler, ModelCheckpoint, EarlyStopping, ReduceLROnPlateau 53 | from keras.utils import np_utils 54 | from dense_all_keras import DenseNetImageNet201 55 | from sklearn.metrics import log_loss 56 | from imageio import imread 57 | #%% 58 | random.shuffle(train_data) 59 | random.shuffle(valid_data) 60 | 61 | img_rows = 256 62 | img_cols = 256 63 | n_cls = len(camera_models) 64 | nb_epoch = 50 65 | 66 | def augment(src, choice): 67 | 68 | if choice == 0: 69 | src = np.rot90(src, 1) 70 | 71 | if choice == 1: 72 | src = src 73 | 74 | if choice == 2: 75 | src = np.rot90(src, 2) 76 | 77 | if choice == 3: 78 | src = np.rot90(src, 3) 79 | return src 80 | 81 | 82 | def generate_processed_batch(data,batch_size = 16): 83 | batch_images = np.zeros((batch_size, img_rows, img_cols, 3)) 84 | batch_label = np.zeros((batch_size, n_cls)) 85 | 86 | while 1: 87 | random.shuffle(data) 88 | for i_data in range(0,len(data),batch_size): 89 | for i_batch in range(batch_size): 90 | img = imread(data[i_data+i_batch][0]) 91 | img = augment(img, np.random.randint(4)) 92 | limit = 256 - img_rows 93 | corner = np.random.randint(0,limit) 94 | img = img[corner:corner+img_rows, corner:corner+img_rows,:] 95 | lab = np_utils.to_categorical(data[i_data+i_batch][1],n_cls) 96 | batch_images[i_batch] = img 97 | batch_label[i_batch] = lab 98 | 99 | yield batch_images, batch_label 100 | 101 | def generate_processed_batch_val(data,batch_size = 16): 102 | batch_images = np.zeros((batch_size, img_rows, img_cols, 3)) 103 | batch_label = np.zeros((batch_size, n_cls)) 104 | 105 | while 1: 106 | for i_data in range(0,len(data),batch_size): 107 | for i_batch in range(batch_size): 108 | img = imread(data[i_data+i_batch][0]) 109 | img = augment(img, np.random.randint(4)) 110 | limit = 256 - img_rows 111 | corner = np.random.randint(0,limit) 112 | img = img[corner:corner+img_rows, corner:corner+img_rows,:] 113 | lab = np_utils.to_categorical(data[i_data+i_batch][1],n_cls) 114 | batch_images[i_batch] = img 115 | batch_label[i_batch] = lab 116 | 117 | yield batch_images, batch_label 118 | 119 | 120 | 121 | 122 | callbacks_list= [ 123 | keras.callbacks.ModelCheckpoint( 124 | filepath='desne_process_re.h5', 125 | mode='min', 126 | monitor='val_loss', 127 | save_best_only=True, 128 | verbose = 1 129 | ), 130 | EarlyStopping(monitor='val_loss', patience=3, verbose=1, min_delta=1e-3), 131 | ReduceLROnPlateau(monitor='val_loss', factor=0.1, patience=2, cooldown=1, 132 | verbose=1, min_lr=1e-7) 133 | ] 134 | 135 | 136 | training_gen = generate_processed_batch(train_data, batch_size) 137 | val_gen = generate_processed_batch_val(valid_data, batch_size) 138 | 139 | base_model = DenseNetImageNet201(input_shape = None, 140 | bottleneck=True, 141 | reduction=0.5, 142 | dropout_rate=0.0, 143 | weight_decay=1e-4, 144 | include_top=False, 145 | weights=None, 146 | input_tensor=None, 147 | pooling=None, 148 | classes=None 149 | ) 150 | x = base_model.output 151 | x= GlobalAveragePooling2D()(x) 152 | 153 | zz = Dense(n_cls, activation = 'softmax')(x) 154 | model = Model(inputs = base_model.input, outputs= zz) 155 | 156 | 157 | model.summary() 158 | 159 | #%% 160 | sgd = SGD(lr=1e-03, decay=1e-6, momentum=0.9, nesterov=True) 161 | model.compile(optimizer=sgd, loss='categorical_crossentropy', metrics=['accuracy']) 162 | #%% 163 | model.fit_generator(training_gen, 164 | steps_per_epoch=int(len(train_data)/batch_size), 165 | nb_epoch=nb_epoch, 166 | validation_data=val_gen, 167 | validation_steps=int(len(valid_data)/batch_size), 168 | callbacks=callbacks_list, 169 | initial_epoch=0 ) -------------------------------------------------------------------------------- /Data_Augmentation/dirProc.m: -------------------------------------------------------------------------------- 1 | function dirProc(readDirName,writeDirName,operation,param,writeFmt,writeQF) 2 | % 3 | % dirProc - This function processes all images in a user specified 'read' 4 | % directory containing only images and writes the processed images to a 5 | % user specified 'write' directory. 6 | % 7 | % Written by Matthew C. Stamm 8 | % v1.0 Released 12/05/17 9 | % 10 | % INPUTS 11 | % readDirName - The name of the directory containing the image files to 12 | % be processed. This name should be provided as a string. 13 | % 14 | % writeDirName - The name of the directory where the processed image 15 | % files should be written to. This name should be provided as a 16 | % string. 17 | % 18 | % operation - A string specifying the operation that the user wishes to 19 | % perform on all of the images in the 'read' directory. 20 | % 21 | % param - The parameter associated with the chosen operation. More 22 | % detail regarding this input is provided below. 23 | % 24 | % writeFmt (optional) - The image file format that should be used when 25 | % writing the processed images. The file format specified by the 26 | % user should be the same as those available when using the 'imwrite' 27 | % operation, e.g. 'tif', 'png', 'jpg', etc. If no format is 28 | % specified, the TIFF file format is chosen by default. 29 | % 30 | % writeQF (optional) - The quality factor used during JPEG compression if 31 | % the write format is chosen as JPEG. 32 | % 33 | % 34 | % Operations available: 35 | % 'block' - This operation divides each image into blocks. The block 36 | % size is specified in the 'param' input variable (e.g. using the 37 | % value of 512 for 'param' will divide the image into 512 x 512 38 | % pixel blocks). 39 | % 40 | % 'jpeg' - This option saves each image as a JPEG whose quality 41 | % factor is specified in the 'param input variable (e.g. using 42 | % value of 75 for 'param' will JPEG compress each image with a 43 | % quality factor of 75). 44 | % 45 | % 'resize' - This option resizes each image using the scaling factor 46 | % specified in the 'param' input variable (e.g. using the value 47 | % of 1.5 for 'param' scales each image by a factor of 1.5). 48 | % 49 | % 'gamma' - This option contrast enhances each image using the gamma 50 | % correction operation where the gamma is specified in the 51 | % 'param' input variable (e.g. using the value of 0.7 for 'param' 52 | % gamma corrects each image with a gamma of 0.7). 53 | % 54 | % 'rename' - This option creates a renamed version of each image, 55 | % where the renamed version of each image corresponds to a string 56 | % specified in the 'param' input variable appended with a number 57 | % assigned to each file (e.g. using the string 'test' for param 58 | % will produce images named 'test01.tif', 'test02.tif', ...) 59 | % 60 | % 'suffix' - This option appends a string to the end of the filename 61 | % (excluding the file extension) of each image where the suffix 62 | % to be appended is specified in the 'param' input variable (e.g. 63 | % if the files in the 'read' directory are named 'test01.tif', 64 | % 'test02.tif', test03.tif',... then using string '_abc' for the 65 | % param variable will produce files in the 'write directory named 66 | % 'test01_abc.tif', 'test02_abc.tif', 'test03_abc.tif', ... 67 | % 68 | % 69 | % OUTPUTS - None. All processed/modified files are written to the 'write' 70 | % directory. 71 | % 72 | 73 | %% 74 | 75 | % NOTE: This function assumes that ONLY image files are in the 'read' 76 | % directory. The first two files provided by the 'dir' function are '.' 77 | % and '..' which are not image files, thus should be skipped. 78 | 79 | % check to see if there are enough input arguments 80 | if nargin < 4 81 | disp(char(10)) 82 | disp('ERROR: Not enough input arguments are specified'); 83 | disp(char(10)); 84 | return 85 | 86 | % if the write file type is not specified, set it to 'tif' 87 | elseif nargin <5 88 | writeFmt= 'tif'; 89 | 90 | end 91 | 92 | % check to see if the 'write' directory already exists 93 | if isdir(writeDirName) == 0 94 | 95 | % if it does not, then make a new directory to write to 96 | mkdir(writeDirName); 97 | 98 | end 99 | 100 | % get the name/path of the current directory 101 | currentDirName= cd; 102 | 103 | 104 | % get information about the directory containing image files to be 105 | % processed 106 | readDir= dir(readDirName); 107 | dirlen= length(readDir); % get number of files in the directory 108 | % dirlen = min(dirlen,20); %% for debugging purpose 109 | 110 | switch operation 111 | 112 | case {'block','Block','BLOCK'} 113 | blocksize= param; 114 | 115 | % loop through all files in the directory 116 | for fnum= 3:dirlen 117 | 118 | % read in the current image 119 | imname= readDir(fnum).name; 120 | im= imread(strcat(readDirName,'/',imname)); 121 | 122 | % get the image's size 123 | [imrows,imcols,colors]= size(im); 124 | 125 | 126 | % loop through all blocks in the image 127 | 128 | % create the filename for this new image block 129 | [filepath,name,ext]=fileparts(imname); 130 | writename= strcat(writeDirName,'/',name,'-b','.',writeFmt); 131 | % writename= strcat(name,'_',num2str(blocknum),... 132 | % '.',writeFmt) 133 | 134 | % write the image block to the 'write' directory 135 | if sum(strcmp(writeFmt,{'jpeg','jpg','JPEG','JPG'})) 136 | imwrite(midBlock(im),writename,writeFmt,... 137 | 'Quality',writeQF); 138 | else 139 | imwrite(midBlock(im),writename,writeFmt); 140 | end 141 | 142 | end % end loop through images 143 | 144 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 145 | 146 | 147 | 148 | case {'jpeg','jpg','JPEG','JPG'} 149 | 150 | if (nargin > 4) & ... 151 | ~ sum(strcmp(writeFmt,{'jpeg','jpg','JPEG','JPG'})) 152 | 153 | disp(char(10)) 154 | disp(strcat('ERROR: The ''operation'' variable is chosen ',... 155 | 'as ''JPEG'' but the')) 156 | disp(strcat(' ''writeFmt'' variable specifies a ',... 157 | ' format other than JPEG.')) 158 | disp(strcat(' Please ensure that these variables ',... 159 | 'match or do not specify')) 160 | disp(' the ''writeFmt'' variable.') 161 | disp(char(10)) 162 | return 163 | 164 | elseif (nargin == 6) & (writeQF ~= param) 165 | 166 | disp(char(10)) 167 | disp(strcat('ERROR: JPEG quality factor specified in',... 168 | ' the ''param'' variable does')) 169 | disp(strcat(' not match the quality factor specified',... 170 | ' in the ''writeQF''')) 171 | disp(strcat(' variable. Either ensure both match or',... 172 | ' specify only one (i.e. ')) 173 | disp(strcat(' do not enter a value for the ',... 174 | '''writeFmt'' and ''writeQF'' variables.')) 175 | disp(char(10)) 176 | return 177 | end 178 | 179 | writeQF= param; 180 | 181 | % loop through all files in the directory 182 | for fnum= 3:dirlen 183 | 184 | % read in the current image 185 | imname= readDir(fnum).name; 186 | im= imread(strcat(readDirName,'/',imname)); 187 | 188 | 189 | % create the write filename for this image 190 | [filepath,name,ext]=fileparts(imname); 191 | writename= strcat(writeDirName,'/',name,'-j',... 192 | num2str(writeQF),'.','jpg'); 193 | 194 | % write the image to the 'write' directory 195 | imwrite(midBlock(im),writename,'JPEG','Quality',writeQF); 196 | 197 | end % end loop through images 198 | 199 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 200 | 201 | 202 | 203 | case {'gamma','Gamma','GAMMA'} 204 | 205 | 206 | g= param; 207 | 208 | % create string to append to the end of the filename noting the 209 | % gamma value used to modify the image 210 | gammaStr= num2str(g); 211 | decInd= find(gammaStr == '.'); 212 | fNameEnd= strcat('-g',gammaStr(1:(decInd-1)),'_',... 213 | gammaStr((decInd+1):end)); 214 | 215 | 216 | % loop through all files in the directory 217 | for fnum= 3:dirlen 218 | 219 | % read in the current image 220 | imname= readDir(fnum).name; 221 | im= imread(strcat(readDirName,'/',imname)); 222 | 223 | % gamma correct the image 224 | gim= 255*((double(im)./255).^g); 225 | gim= uint8(gim); 226 | 227 | % create the filename for this new image block 228 | [filepath,name,ext]=fileparts(imname); 229 | writename= strcat(writeDirName,'/',name,fNameEnd,'.',writeFmt); 230 | 231 | % write the image to the 'write' directory 232 | if sum(strcmp(writeFmt,{'jpeg','jpg','JPEG','JPG'})) 233 | imwrite(midBlock(gim),writename,writeFmt,... 234 | 'Quality',writeQF); 235 | else 236 | imwrite(midBlock(gim),writename,writeFmt); 237 | end 238 | 239 | end % end loop through images 240 | 241 | 242 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 243 | 244 | 245 | case {'resize','Resize','RESIZE'} 246 | 247 | scale= param; 248 | 249 | % create string to append to the end of the filename noting the 250 | % scaling factor used to modify the image 251 | scaleStr= num2str(scale); 252 | decInd= find(scaleStr == '.'); 253 | fNameEnd= strcat('-r',scaleStr(1:(decInd-1)),'_',... 254 | scaleStr((decInd+1):end)); 255 | 256 | 257 | % loop through all files in the directory 258 | for fnum= 3:dirlen 259 | 260 | % read in the current image 261 | imname= readDir(fnum).name; 262 | im= imread(strcat(readDirName,'/',imname)); 263 | 264 | % resize the image 265 | resizedIm = imresize(im,scale); 266 | 267 | % create the filename for the resized image 268 | [filepath,name,ext]=fileparts(imname); 269 | writename= strcat(writeDirName,'/',name,fNameEnd,'.',writeFmt); 270 | 271 | % write the image to the 'write' directory 272 | if sum(strcmp(writeFmt,{'jpeg','jpg','JPEG','JPG'})) 273 | imwrite(midBlock(resizedIm),writename,writeFmt,... 274 | 'Quality',writeQF); 275 | else 276 | imwrite(midBlock(resizedIm),writename,writeFmt); 277 | end 278 | 279 | end % end loop through images 280 | 281 | 282 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 283 | 284 | case {'rename','Rename','RENAME'} 285 | 286 | % get new filename (excluding image number) 287 | newname= param; 288 | 289 | % determine how many digits should be used to add the image 290 | % number to the output (write) filename 291 | numdig= floor(log10(dirlen-2))+1; 292 | numdigstr= strcat('%0',num2str(numdig),'d'); 293 | 294 | % loop through all files in the directory 295 | for fnum= 3:dirlen 296 | 297 | % read in the current image 298 | imname= readDir(fnum).name; 299 | im= imread(strcat(readDirName,'/',imname)); 300 | 301 | 302 | % create the filename for this new image block 303 | [filepath,name,ext]=fileparts(imname); 304 | imnum= fnum-2; 305 | writename= strcat(writeDirName,'/',newname,... 306 | sprintf(numdigstr,imnum),'.',writeFmt); 307 | 308 | % write the image to the 'write' directory 309 | if sum(strcmp(writeFmt,{'jpeg','jpg','JPEG','JPG'})) 310 | imwrite(midBlock(im),writename,writeFmt,... 311 | 'Quality',writeQF); 312 | else 313 | imwrite(midBlock(im),writename,writeFmt); 314 | end 315 | 316 | end % end loop through images 317 | 318 | 319 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 320 | 321 | case {'suffix','Suffix','SUFFIX'} 322 | 323 | % get new filename (excluding image number) 324 | suffix= param; 325 | 326 | % loop through all files in the directory 327 | for fnum= 3:dirlen 328 | 329 | % read in the current image 330 | imname= readDir(fnum).name; 331 | im= imread(strcat(readDirName,'/',imname)); 332 | 333 | 334 | % create the filename for this new image block 335 | [filepath,name,ext]=fileparts(imname); 336 | imnum= fnum-2; 337 | writename= strcat(writeDirName,'/',name,suffix,'.',writeFmt); 338 | 339 | % write the image to the 'write' directory 340 | if sum(strcmp(writeFmt,{'jpeg','jpg','JPEG','JPG'})) 341 | imwrite(midBlock(im),writename,writeFmt,... 342 | 'Quality',writeQF); 343 | else 344 | imwrite(midBlock(im),writename,writeFmt); 345 | end 346 | 347 | end % end loop through images 348 | 349 | 350 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 351 | 352 | 353 | otherwise 354 | disp(char(10)) 355 | disp('ERROR: You have chosen an unknown operation'); 356 | disp(char(10)); 357 | return 358 | end 359 | 360 | function xb = midBlock(x) 361 | sz = size(x); 362 | blocksz = 512; 363 | idx = floor((sz - blocksz)/2) + [1;blocksz]; 364 | xb = x(idx(1,1):idx(2,1), idx(1,2):idx(2,2),:); 365 | end 366 | 367 | end -------------------------------------------------------------------------------- /Phase-I/training/convolutional.py: -------------------------------------------------------------------------------- 1 | 2 | # -*- coding: utf-8 -*- 3 | from __future__ import absolute_import 4 | import functools 5 | 6 | from keras import backend as K 7 | from keras import activations 8 | from keras import initializers 9 | from keras import regularizers 10 | from keras import constraints 11 | from keras.engine import Layer 12 | from keras.engine import InputSpec 13 | from keras.layers.convolutional import Convolution3D 14 | from keras.utils.generic_utils import get_custom_objects 15 | from keras.utils.conv_utils import conv_output_length 16 | from keras.utils.conv_utils import normalize_data_format 17 | import numpy as np 18 | 19 | 20 | class CosineConvolution2D(Layer): 21 | """Cosine Normalized Convolution operator for filtering windows of two-dimensional inputs. 22 | Cosine Normalization: Using Cosine Similarity Instead of Dot Product in Neural Networks 23 | https://arxiv.org/pdf/1702.05870.pdf 24 | When using this layer as the first layer in a model, 25 | provide the keyword argument `input_shape` 26 | (tuple of integers, does not include the sample axis), 27 | e.g. `input_shape=(3, 128, 128)` for 128x128 RGB pictures. 28 | # Examples 29 | ```python 30 | # apply a 3x3 convolution with 64 output filters on a 256x256 image: 31 | model = Sequential() 32 | model.add(CosineConvolution2D(64, 3, 3, 33 | padding='same', 34 | input_shape=(3, 256, 256))) 35 | # now model.output_shape == (None, 64, 256, 256) 36 | # add a 3x3 convolution on top, with 32 output filters: 37 | model.add(CosineConvolution2D(32, 3, 3, padding='same')) 38 | # now model.output_shape == (None, 32, 256, 256) 39 | ``` 40 | # Arguments 41 | filters: Number of convolution filters to use. 42 | kernel_size: kernel_size: An integer or tuple/list of 2 integers, specifying the 43 | dimensions of the convolution window. 44 | init: name of initialization function for the weights of the layer 45 | (see [initializers](../initializers.md)), or alternatively, 46 | Theano function to use for weights initialization. 47 | This parameter is only relevant if you don't pass 48 | a `weights` argument. 49 | activation: name of activation function to use 50 | (see [activations](../activations.md)), 51 | or alternatively, elementwise Theano function. 52 | If you don't specify anything, no activation is applied 53 | (ie. "linear" activation: a(x) = x). 54 | weights: list of numpy arrays to set as initial weights. 55 | padding: 'valid', 'same' or 'full' 56 | ('full' requires the Theano backend). 57 | strides: tuple of length 2. Factor by which to strides output. 58 | Also called strides elsewhere. 59 | kernel_regularizer: instance of [WeightRegularizer](../regularizers.md) 60 | (eg. L1 or L2 regularization), applied to the main weights matrix. 61 | bias_regularizer: instance of [WeightRegularizer](../regularizers.md), 62 | applied to the use_bias. 63 | activity_regularizer: instance of [ActivityRegularizer](../regularizers.md), 64 | applied to the network output. 65 | kernel_constraint: instance of the [constraints](../constraints.md) module 66 | (eg. maxnorm, nonneg), applied to the main weights matrix. 67 | bias_constraint: instance of the [constraints](../constraints.md) module, 68 | applied to the use_bias. 69 | data_format: 'channels_first' or 'channels_last'. In 'channels_first' mode, the channels dimension 70 | (the depth) is at index 1, in 'channels_last' mode is it at index 3. 71 | It defaults to the `image_data_format` value found in your 72 | Keras config file at `~/.keras/keras.json`. 73 | If you never set it, then it will be "tf". 74 | use_bias: whether to include a use_bias 75 | (i.e. make the layer affine rather than linear). 76 | # Input shape 77 | 4D tensor with shape: 78 | `(samples, channels, rows, cols)` if data_format='channels_first' 79 | or 4D tensor with shape: 80 | `(samples, rows, cols, channels)` if data_format='channels_last'. 81 | # Output shape 82 | 4D tensor with shape: 83 | `(samples, filters, nekernel_rows, nekernel_cols)` if data_format='channels_first' 84 | or 4D tensor with shape: 85 | `(samples, nekernel_rows, nekernel_cols, filters)` if data_format='channels_last'. 86 | `rows` and `cols` values might have changed due to padding. 87 | """ 88 | 89 | def __init__(self, filters, kernel_size, 90 | kernel_initializer='glorot_uniform', activation=None, weights=None, 91 | padding='valid', strides=(1, 1), data_format=None, 92 | kernel_regularizer=None, bias_regularizer=None, 93 | activity_regularizer=None, 94 | kernel_constraint=None, bias_constraint=None, 95 | use_bias=True, **kwargs): 96 | if data_format is None: 97 | data_format = K.image_data_format() 98 | if padding not in {'valid', 'same', 'full'}: 99 | raise ValueError('Invalid border mode for CosineConvolution2D:', padding) 100 | self.filters = filters 101 | self.kernel_size = kernel_size 102 | self.nb_row, self.nb_col = self.kernel_size 103 | self.kernel_initializer = initializers.get(kernel_initializer) 104 | self.activation = activations.get(activation) 105 | self.padding = padding 106 | self.strides = tuple(strides) 107 | self.data_format = normalize_data_format(data_format) 108 | self.kernel_regularizer = regularizers.get(kernel_regularizer) 109 | self.bias_regularizer = regularizers.get(bias_regularizer) 110 | self.activity_regularizer = regularizers.get(activity_regularizer) 111 | 112 | self.kernel_constraint = constraints.get(kernel_constraint) 113 | self.bias_constraint = constraints.get(bias_constraint) 114 | 115 | self.use_bias = use_bias 116 | self.input_spec = [InputSpec(ndim=4)] 117 | self.initial_weights = weights 118 | super(CosineConvolution2D, self).__init__(**kwargs) 119 | 120 | def build(self, input_shape): 121 | if self.data_format == 'channels_first': 122 | stack_size = input_shape[1] 123 | self.kernel_shape = (self.filters, stack_size, self.nb_row, self.nb_col) 124 | self.kernel_norm_shape = (1, stack_size, self.nb_row, self.nb_col) 125 | elif self.data_format == 'channels_last': 126 | stack_size = input_shape[3] 127 | self.kernel_shape = (self.nb_row, self.nb_col, stack_size, self.filters) 128 | self.kernel_norm_shape = (self.nb_row, self.nb_col, stack_size, 1) 129 | else: 130 | raise ValueError('Invalid data_format:', self.data_format) 131 | self.W = self.add_weight(self.kernel_shape, 132 | initializer=functools.partial(self.kernel_initializer), 133 | name='{}_W'.format(self.name), 134 | regularizer=self.kernel_regularizer, 135 | constraint=self.kernel_constraint) 136 | 137 | self.kernel_norm = K.variable(np.ones(self.kernel_norm_shape), name='{}_kernel_norm'.format(self.name)) 138 | 139 | if self.use_bias: 140 | self.b = self.add_weight((self.filters,), 141 | initializer='zero', 142 | name='{}_b'.format(self.name), 143 | regularizer=self.bias_regularizer, 144 | constraint=self.bias_constraint) 145 | else: 146 | self.b = None 147 | 148 | if self.initial_weights is not None: 149 | self.set_weights(self.initial_weights) 150 | del self.initial_weights 151 | self.built = True 152 | 153 | def compute_output_shape(self, input_shape): 154 | if self.data_format == 'channels_first': 155 | rows = input_shape[2] 156 | cols = input_shape[3] 157 | elif self.data_format == 'channels_last': 158 | rows = input_shape[1] 159 | cols = input_shape[2] 160 | else: 161 | raise ValueError('Invalid data_format:', self.data_format) 162 | 163 | rows = conv_output_length(rows, self.nb_row, 164 | self.padding, self.strides[0]) 165 | cols = conv_output_length(cols, self.nb_col, 166 | self.padding, self.strides[1]) 167 | 168 | if self.data_format == 'channels_first': 169 | return (input_shape[0], self.filters, rows, cols) 170 | elif self.data_format == 'channels_last': 171 | return (input_shape[0], rows, cols, self.filters) 172 | 173 | def call(self, x, mask=None): 174 | b, xb = 0., 0. 175 | if self.data_format == 'channels_first': 176 | kernel_sum_axes = [1, 2, 3] 177 | if self.use_bias: 178 | b = K.reshape(self.b, (self.filters, 1, 1, 1)) 179 | xb = 1. 180 | elif self.data_format == 'channels_last': 181 | kernel_sum_axes = [0, 1, 2] 182 | if self.use_bias: 183 | b = K.reshape(self.b, (1, 1, 1, self.filters)) 184 | xb = 1. 185 | 186 | Wnorm = K.sqrt(K.sum(K.square(self.W), axis=kernel_sum_axes, keepdims=True) + K.square(b) + K.epsilon()) 187 | xnorm = K.sqrt(K.conv2d(K.square(x), self.kernel_norm, strides=self.strides, 188 | padding=self.padding, 189 | data_format=self.data_format, 190 | filter_shape=self.kernel_norm_shape) + xb + K.epsilon()) 191 | 192 | W = self.W / Wnorm 193 | 194 | output = K.conv2d(x, W, strides=self.strides, 195 | padding=self.padding, 196 | data_format=self.data_format, 197 | filter_shape=self.kernel_shape) 198 | 199 | if K.backend() == 'theano': 200 | xnorm = K.pattern_broadcast(xnorm, [False, True, False, False]) 201 | 202 | output /= xnorm 203 | 204 | if self.use_bias: 205 | b /= Wnorm 206 | if self.data_format == 'channels_first': 207 | b = K.reshape(b, (1, self.filters, 1, 1)) 208 | elif self.data_format == 'channels_last': 209 | b = K.reshape(b, (1, 1, 1, self.filters)) 210 | else: 211 | raise ValueError('Invalid data_format:', self.data_format) 212 | b /= xnorm 213 | output += b 214 | output = self.activation(output) 215 | return output 216 | 217 | def get_config(self): 218 | config = {'filters': self.filters, 219 | 'kernel_size': self.kernel_size, 220 | 'kernel_initializer': initializers.serialize(self.kernel_initializer), 221 | 'activation': activations.serialize(self.activation), 222 | 'padding': self.padding, 223 | 'strides': self.strides, 224 | 'data_format': self.data_format, 225 | 'kernel_regularizer': regularizers.serialize(self.kernel_regularizer), 226 | 'bias_regularizer': regularizers.serialize(self.bias_regularizer), 227 | 'activity_regularizer': regularizers.serialize(self.activity_regularizer), 228 | 'kernel_constraint': constraints.serialize(self.kernel_constraint), 229 | 'bias_constraint': constraints.serialize(self.bias_constraint), 230 | 'use_bias': self.use_bias} 231 | base_config = super(CosineConvolution2D, self).get_config() 232 | return dict(list(base_config.items()) + list(config.items())) 233 | 234 | 235 | CosineConv2D = CosineConvolution2D 236 | get_custom_objects().update({'CosineConvolution2D': CosineConvolution2D}) 237 | get_custom_objects().update({'CosineConv2D': CosineConv2D}) 238 | 239 | 240 | class SubPixelUpscaling(Layer): 241 | """ Sub-pixel convolutional upscaling layer based on the paper "Real-Time Single Image 242 | and Video Super-Resolution Using an Efficient Sub-Pixel Convolutional Neural Network" 243 | (https://arxiv.org/abs/1609.05158). 244 | This layer requires a Convolution2D prior to it, having output filters computed according to 245 | the formula : 246 | filters = k * (scale_factor * scale_factor) 247 | where k = a user defined number of filters (generally larger than 32) 248 | scale_factor = the upscaling factor (generally 2) 249 | This layer performs the depth to space operation on the convolution filters, and returns a 250 | tensor with the size as defined below. 251 | # Example : 252 | ```python 253 | # A standard subpixel upscaling block 254 | x = Convolution2D(256, 3, 3, padding='same', activation='relu')(...) 255 | u = SubPixelUpscaling(scale_factor=2)(x) 256 | [Optional] 257 | x = Convolution2D(256, 3, 3, padding='same', activation='relu')(u) 258 | ``` 259 | In practice, it is useful to have a second convolution layer after the 260 | SubPixelUpscaling layer to speed up the learning process. 261 | However, if you are stacking multiple SubPixelUpscaling blocks, it may increase 262 | the number of parameters greatly, so the Convolution layer after SubPixelUpscaling 263 | layer can be removed. 264 | # Arguments 265 | scale_factor: Upscaling factor. 266 | data_format: Can be None, 'channels_first' or 'channels_last'. 267 | # Input shape 268 | 4D tensor with shape: 269 | `(samples, k * (scale_factor * scale_factor) channels, rows, cols)` if data_format='channels_first' 270 | or 4D tensor with shape: 271 | `(samples, rows, cols, k * (scale_factor * scale_factor) channels)` if data_format='channels_last'. 272 | # Output shape 273 | 4D tensor with shape: 274 | `(samples, k channels, rows * scale_factor, cols * scale_factor))` if data_format='channels_first' 275 | or 4D tensor with shape: 276 | `(samples, rows * scale_factor, cols * scale_factor, k channels)` if data_format='channels_last'. 277 | """ 278 | 279 | def __init__(self, scale_factor=2, data_format=None, **kwargs): 280 | super(SubPixelUpscaling, self).__init__(**kwargs) 281 | 282 | self.scale_factor = scale_factor 283 | self.data_format = normalize_data_format(data_format) 284 | 285 | def build(self, input_shape): 286 | pass 287 | 288 | def call(self, x, mask=None): 289 | y = K.depth_to_space(x, self.scale_factor, self.data_format) 290 | return y 291 | 292 | def compute_output_shape(self, input_shape): 293 | if self.data_format == 'channels_first': 294 | b, k, r, c = input_shape 295 | return (b, k // (self.scale_factor ** 2), r * self.scale_factor, c * self.scale_factor) 296 | else: 297 | b, r, c, k = input_shape 298 | return (b, r * self.scale_factor, c * self.scale_factor, k // (self.scale_factor ** 2)) 299 | 300 | def get_config(self): 301 | config = {'scale_factor': self.scale_factor, 302 | 'data_format': self.data_format} 303 | base_config = super(SubPixelUpscaling, self).get_config() 304 | return dict(list(base_config.items()) + list(config.items())) 305 | -------------------------------------------------------------------------------- /Phase-I/prediction/convolutional.py: -------------------------------------------------------------------------------- 1 | 2 | # -*- coding: utf-8 -*- 3 | from __future__ import absolute_import 4 | import functools 5 | 6 | from keras import backend as K 7 | from keras import activations 8 | from keras import initializers 9 | from keras import regularizers 10 | from keras import constraints 11 | from keras.engine import Layer 12 | from keras.engine import InputSpec 13 | from keras.layers.convolutional import Convolution3D 14 | from keras.utils.generic_utils import get_custom_objects 15 | from keras.utils.conv_utils import conv_output_length 16 | from keras.utils.conv_utils import normalize_data_format 17 | import numpy as np 18 | 19 | 20 | class CosineConvolution2D(Layer): 21 | """Cosine Normalized Convolution operator for filtering windows of two-dimensional inputs. 22 | Cosine Normalization: Using Cosine Similarity Instead of Dot Product in Neural Networks 23 | https://arxiv.org/pdf/1702.05870.pdf 24 | When using this layer as the first layer in a model, 25 | provide the keyword argument `input_shape` 26 | (tuple of integers, does not include the sample axis), 27 | e.g. `input_shape=(3, 128, 128)` for 128x128 RGB pictures. 28 | # Examples 29 | ```python 30 | # apply a 3x3 convolution with 64 output filters on a 256x256 image: 31 | model = Sequential() 32 | model.add(CosineConvolution2D(64, 3, 3, 33 | padding='same', 34 | input_shape=(3, 256, 256))) 35 | # now model.output_shape == (None, 64, 256, 256) 36 | # add a 3x3 convolution on top, with 32 output filters: 37 | model.add(CosineConvolution2D(32, 3, 3, padding='same')) 38 | # now model.output_shape == (None, 32, 256, 256) 39 | ``` 40 | # Arguments 41 | filters: Number of convolution filters to use. 42 | kernel_size: kernel_size: An integer or tuple/list of 2 integers, specifying the 43 | dimensions of the convolution window. 44 | init: name of initialization function for the weights of the layer 45 | (see [initializers](../initializers.md)), or alternatively, 46 | Theano function to use for weights initialization. 47 | This parameter is only relevant if you don't pass 48 | a `weights` argument. 49 | activation: name of activation function to use 50 | (see [activations](../activations.md)), 51 | or alternatively, elementwise Theano function. 52 | If you don't specify anything, no activation is applied 53 | (ie. "linear" activation: a(x) = x). 54 | weights: list of numpy arrays to set as initial weights. 55 | padding: 'valid', 'same' or 'full' 56 | ('full' requires the Theano backend). 57 | strides: tuple of length 2. Factor by which to strides output. 58 | Also called strides elsewhere. 59 | kernel_regularizer: instance of [WeightRegularizer](../regularizers.md) 60 | (eg. L1 or L2 regularization), applied to the main weights matrix. 61 | bias_regularizer: instance of [WeightRegularizer](../regularizers.md), 62 | applied to the use_bias. 63 | activity_regularizer: instance of [ActivityRegularizer](../regularizers.md), 64 | applied to the network output. 65 | kernel_constraint: instance of the [constraints](../constraints.md) module 66 | (eg. maxnorm, nonneg), applied to the main weights matrix. 67 | bias_constraint: instance of the [constraints](../constraints.md) module, 68 | applied to the use_bias. 69 | data_format: 'channels_first' or 'channels_last'. In 'channels_first' mode, the channels dimension 70 | (the depth) is at index 1, in 'channels_last' mode is it at index 3. 71 | It defaults to the `image_data_format` value found in your 72 | Keras config file at `~/.keras/keras.json`. 73 | If you never set it, then it will be "tf". 74 | use_bias: whether to include a use_bias 75 | (i.e. make the layer affine rather than linear). 76 | # Input shape 77 | 4D tensor with shape: 78 | `(samples, channels, rows, cols)` if data_format='channels_first' 79 | or 4D tensor with shape: 80 | `(samples, rows, cols, channels)` if data_format='channels_last'. 81 | # Output shape 82 | 4D tensor with shape: 83 | `(samples, filters, nekernel_rows, nekernel_cols)` if data_format='channels_first' 84 | or 4D tensor with shape: 85 | `(samples, nekernel_rows, nekernel_cols, filters)` if data_format='channels_last'. 86 | `rows` and `cols` values might have changed due to padding. 87 | """ 88 | 89 | def __init__(self, filters, kernel_size, 90 | kernel_initializer='glorot_uniform', activation=None, weights=None, 91 | padding='valid', strides=(1, 1), data_format=None, 92 | kernel_regularizer=None, bias_regularizer=None, 93 | activity_regularizer=None, 94 | kernel_constraint=None, bias_constraint=None, 95 | use_bias=True, **kwargs): 96 | if data_format is None: 97 | data_format = K.image_data_format() 98 | if padding not in {'valid', 'same', 'full'}: 99 | raise ValueError('Invalid border mode for CosineConvolution2D:', padding) 100 | self.filters = filters 101 | self.kernel_size = kernel_size 102 | self.nb_row, self.nb_col = self.kernel_size 103 | self.kernel_initializer = initializers.get(kernel_initializer) 104 | self.activation = activations.get(activation) 105 | self.padding = padding 106 | self.strides = tuple(strides) 107 | self.data_format = normalize_data_format(data_format) 108 | self.kernel_regularizer = regularizers.get(kernel_regularizer) 109 | self.bias_regularizer = regularizers.get(bias_regularizer) 110 | self.activity_regularizer = regularizers.get(activity_regularizer) 111 | 112 | self.kernel_constraint = constraints.get(kernel_constraint) 113 | self.bias_constraint = constraints.get(bias_constraint) 114 | 115 | self.use_bias = use_bias 116 | self.input_spec = [InputSpec(ndim=4)] 117 | self.initial_weights = weights 118 | super(CosineConvolution2D, self).__init__(**kwargs) 119 | 120 | def build(self, input_shape): 121 | if self.data_format == 'channels_first': 122 | stack_size = input_shape[1] 123 | self.kernel_shape = (self.filters, stack_size, self.nb_row, self.nb_col) 124 | self.kernel_norm_shape = (1, stack_size, self.nb_row, self.nb_col) 125 | elif self.data_format == 'channels_last': 126 | stack_size = input_shape[3] 127 | self.kernel_shape = (self.nb_row, self.nb_col, stack_size, self.filters) 128 | self.kernel_norm_shape = (self.nb_row, self.nb_col, stack_size, 1) 129 | else: 130 | raise ValueError('Invalid data_format:', self.data_format) 131 | self.W = self.add_weight(self.kernel_shape, 132 | initializer=functools.partial(self.kernel_initializer), 133 | name='{}_W'.format(self.name), 134 | regularizer=self.kernel_regularizer, 135 | constraint=self.kernel_constraint) 136 | 137 | self.kernel_norm = K.variable(np.ones(self.kernel_norm_shape), name='{}_kernel_norm'.format(self.name)) 138 | 139 | if self.use_bias: 140 | self.b = self.add_weight((self.filters,), 141 | initializer='zero', 142 | name='{}_b'.format(self.name), 143 | regularizer=self.bias_regularizer, 144 | constraint=self.bias_constraint) 145 | else: 146 | self.b = None 147 | 148 | if self.initial_weights is not None: 149 | self.set_weights(self.initial_weights) 150 | del self.initial_weights 151 | self.built = True 152 | 153 | def compute_output_shape(self, input_shape): 154 | if self.data_format == 'channels_first': 155 | rows = input_shape[2] 156 | cols = input_shape[3] 157 | elif self.data_format == 'channels_last': 158 | rows = input_shape[1] 159 | cols = input_shape[2] 160 | else: 161 | raise ValueError('Invalid data_format:', self.data_format) 162 | 163 | rows = conv_output_length(rows, self.nb_row, 164 | self.padding, self.strides[0]) 165 | cols = conv_output_length(cols, self.nb_col, 166 | self.padding, self.strides[1]) 167 | 168 | if self.data_format == 'channels_first': 169 | return (input_shape[0], self.filters, rows, cols) 170 | elif self.data_format == 'channels_last': 171 | return (input_shape[0], rows, cols, self.filters) 172 | 173 | def call(self, x, mask=None): 174 | b, xb = 0., 0. 175 | if self.data_format == 'channels_first': 176 | kernel_sum_axes = [1, 2, 3] 177 | if self.use_bias: 178 | b = K.reshape(self.b, (self.filters, 1, 1, 1)) 179 | xb = 1. 180 | elif self.data_format == 'channels_last': 181 | kernel_sum_axes = [0, 1, 2] 182 | if self.use_bias: 183 | b = K.reshape(self.b, (1, 1, 1, self.filters)) 184 | xb = 1. 185 | 186 | Wnorm = K.sqrt(K.sum(K.square(self.W), axis=kernel_sum_axes, keepdims=True) + K.square(b) + K.epsilon()) 187 | xnorm = K.sqrt(K.conv2d(K.square(x), self.kernel_norm, strides=self.strides, 188 | padding=self.padding, 189 | data_format=self.data_format, 190 | filter_shape=self.kernel_norm_shape) + xb + K.epsilon()) 191 | 192 | W = self.W / Wnorm 193 | 194 | output = K.conv2d(x, W, strides=self.strides, 195 | padding=self.padding, 196 | data_format=self.data_format, 197 | filter_shape=self.kernel_shape) 198 | 199 | if K.backend() == 'theano': 200 | xnorm = K.pattern_broadcast(xnorm, [False, True, False, False]) 201 | 202 | output /= xnorm 203 | 204 | if self.use_bias: 205 | b /= Wnorm 206 | if self.data_format == 'channels_first': 207 | b = K.reshape(b, (1, self.filters, 1, 1)) 208 | elif self.data_format == 'channels_last': 209 | b = K.reshape(b, (1, 1, 1, self.filters)) 210 | else: 211 | raise ValueError('Invalid data_format:', self.data_format) 212 | b /= xnorm 213 | output += b 214 | output = self.activation(output) 215 | return output 216 | 217 | def get_config(self): 218 | config = {'filters': self.filters, 219 | 'kernel_size': self.kernel_size, 220 | 'kernel_initializer': initializers.serialize(self.kernel_initializer), 221 | 'activation': activations.serialize(self.activation), 222 | 'padding': self.padding, 223 | 'strides': self.strides, 224 | 'data_format': self.data_format, 225 | 'kernel_regularizer': regularizers.serialize(self.kernel_regularizer), 226 | 'bias_regularizer': regularizers.serialize(self.bias_regularizer), 227 | 'activity_regularizer': regularizers.serialize(self.activity_regularizer), 228 | 'kernel_constraint': constraints.serialize(self.kernel_constraint), 229 | 'bias_constraint': constraints.serialize(self.bias_constraint), 230 | 'use_bias': self.use_bias} 231 | base_config = super(CosineConvolution2D, self).get_config() 232 | return dict(list(base_config.items()) + list(config.items())) 233 | 234 | 235 | CosineConv2D = CosineConvolution2D 236 | get_custom_objects().update({'CosineConvolution2D': CosineConvolution2D}) 237 | get_custom_objects().update({'CosineConv2D': CosineConv2D}) 238 | 239 | 240 | class SubPixelUpscaling(Layer): 241 | """ Sub-pixel convolutional upscaling layer based on the paper "Real-Time Single Image 242 | and Video Super-Resolution Using an Efficient Sub-Pixel Convolutional Neural Network" 243 | (https://arxiv.org/abs/1609.05158). 244 | This layer requires a Convolution2D prior to it, having output filters computed according to 245 | the formula : 246 | filters = k * (scale_factor * scale_factor) 247 | where k = a user defined number of filters (generally larger than 32) 248 | scale_factor = the upscaling factor (generally 2) 249 | This layer performs the depth to space operation on the convolution filters, and returns a 250 | tensor with the size as defined below. 251 | # Example : 252 | ```python 253 | # A standard subpixel upscaling block 254 | x = Convolution2D(256, 3, 3, padding='same', activation='relu')(...) 255 | u = SubPixelUpscaling(scale_factor=2)(x) 256 | [Optional] 257 | x = Convolution2D(256, 3, 3, padding='same', activation='relu')(u) 258 | ``` 259 | In practice, it is useful to have a second convolution layer after the 260 | SubPixelUpscaling layer to speed up the learning process. 261 | However, if you are stacking multiple SubPixelUpscaling blocks, it may increase 262 | the number of parameters greatly, so the Convolution layer after SubPixelUpscaling 263 | layer can be removed. 264 | # Arguments 265 | scale_factor: Upscaling factor. 266 | data_format: Can be None, 'channels_first' or 'channels_last'. 267 | # Input shape 268 | 4D tensor with shape: 269 | `(samples, k * (scale_factor * scale_factor) channels, rows, cols)` if data_format='channels_first' 270 | or 4D tensor with shape: 271 | `(samples, rows, cols, k * (scale_factor * scale_factor) channels)` if data_format='channels_last'. 272 | # Output shape 273 | 4D tensor with shape: 274 | `(samples, k channels, rows * scale_factor, cols * scale_factor))` if data_format='channels_first' 275 | or 4D tensor with shape: 276 | `(samples, rows * scale_factor, cols * scale_factor, k channels)` if data_format='channels_last'. 277 | """ 278 | 279 | def __init__(self, scale_factor=2, data_format=None, **kwargs): 280 | super(SubPixelUpscaling, self).__init__(**kwargs) 281 | 282 | self.scale_factor = scale_factor 283 | self.data_format = normalize_data_format(data_format) 284 | 285 | def build(self, input_shape): 286 | pass 287 | 288 | def call(self, x, mask=None): 289 | y = K.depth_to_space(x, self.scale_factor, self.data_format) 290 | return y 291 | 292 | def compute_output_shape(self, input_shape): 293 | if self.data_format == 'channels_first': 294 | b, k, r, c = input_shape 295 | return (b, k // (self.scale_factor ** 2), r * self.scale_factor, c * self.scale_factor) 296 | else: 297 | b, r, c, k = input_shape 298 | return (b, r * self.scale_factor, c * self.scale_factor, k // (self.scale_factor ** 2)) 299 | 300 | def get_config(self): 301 | config = {'scale_factor': self.scale_factor, 302 | 'data_format': self.data_format} 303 | base_config = super(SubPixelUpscaling, self).get_config() 304 | return dict(list(base_config.items()) + list(config.items())) 305 | -------------------------------------------------------------------------------- /Phase-III/prediction/convolutional.py: -------------------------------------------------------------------------------- 1 | 2 | # -*- coding: utf-8 -*- 3 | from __future__ import absolute_import 4 | import functools 5 | 6 | from keras import backend as K 7 | from keras import activations 8 | from keras import initializers 9 | from keras import regularizers 10 | from keras import constraints 11 | from keras.engine import Layer 12 | from keras.engine import InputSpec 13 | from keras.layers.convolutional import Convolution3D 14 | from keras.utils.generic_utils import get_custom_objects 15 | from keras.utils.conv_utils import conv_output_length 16 | from keras.utils.conv_utils import normalize_data_format 17 | import numpy as np 18 | 19 | 20 | class CosineConvolution2D(Layer): 21 | """Cosine Normalized Convolution operator for filtering windows of two-dimensional inputs. 22 | Cosine Normalization: Using Cosine Similarity Instead of Dot Product in Neural Networks 23 | https://arxiv.org/pdf/1702.05870.pdf 24 | When using this layer as the first layer in a model, 25 | provide the keyword argument `input_shape` 26 | (tuple of integers, does not include the sample axis), 27 | e.g. `input_shape=(3, 128, 128)` for 128x128 RGB pictures. 28 | # Examples 29 | ```python 30 | # apply a 3x3 convolution with 64 output filters on a 256x256 image: 31 | model = Sequential() 32 | model.add(CosineConvolution2D(64, 3, 3, 33 | padding='same', 34 | input_shape=(3, 256, 256))) 35 | # now model.output_shape == (None, 64, 256, 256) 36 | # add a 3x3 convolution on top, with 32 output filters: 37 | model.add(CosineConvolution2D(32, 3, 3, padding='same')) 38 | # now model.output_shape == (None, 32, 256, 256) 39 | ``` 40 | # Arguments 41 | filters: Number of convolution filters to use. 42 | kernel_size: kernel_size: An integer or tuple/list of 2 integers, specifying the 43 | dimensions of the convolution window. 44 | init: name of initialization function for the weights of the layer 45 | (see [initializers](../initializers.md)), or alternatively, 46 | Theano function to use for weights initialization. 47 | This parameter is only relevant if you don't pass 48 | a `weights` argument. 49 | activation: name of activation function to use 50 | (see [activations](../activations.md)), 51 | or alternatively, elementwise Theano function. 52 | If you don't specify anything, no activation is applied 53 | (ie. "linear" activation: a(x) = x). 54 | weights: list of numpy arrays to set as initial weights. 55 | padding: 'valid', 'same' or 'full' 56 | ('full' requires the Theano backend). 57 | strides: tuple of length 2. Factor by which to strides output. 58 | Also called strides elsewhere. 59 | kernel_regularizer: instance of [WeightRegularizer](../regularizers.md) 60 | (eg. L1 or L2 regularization), applied to the main weights matrix. 61 | bias_regularizer: instance of [WeightRegularizer](../regularizers.md), 62 | applied to the use_bias. 63 | activity_regularizer: instance of [ActivityRegularizer](../regularizers.md), 64 | applied to the network output. 65 | kernel_constraint: instance of the [constraints](../constraints.md) module 66 | (eg. maxnorm, nonneg), applied to the main weights matrix. 67 | bias_constraint: instance of the [constraints](../constraints.md) module, 68 | applied to the use_bias. 69 | data_format: 'channels_first' or 'channels_last'. In 'channels_first' mode, the channels dimension 70 | (the depth) is at index 1, in 'channels_last' mode is it at index 3. 71 | It defaults to the `image_data_format` value found in your 72 | Keras config file at `~/.keras/keras.json`. 73 | If you never set it, then it will be "tf". 74 | use_bias: whether to include a use_bias 75 | (i.e. make the layer affine rather than linear). 76 | # Input shape 77 | 4D tensor with shape: 78 | `(samples, channels, rows, cols)` if data_format='channels_first' 79 | or 4D tensor with shape: 80 | `(samples, rows, cols, channels)` if data_format='channels_last'. 81 | # Output shape 82 | 4D tensor with shape: 83 | `(samples, filters, nekernel_rows, nekernel_cols)` if data_format='channels_first' 84 | or 4D tensor with shape: 85 | `(samples, nekernel_rows, nekernel_cols, filters)` if data_format='channels_last'. 86 | `rows` and `cols` values might have changed due to padding. 87 | """ 88 | 89 | def __init__(self, filters, kernel_size, 90 | kernel_initializer='glorot_uniform', activation=None, weights=None, 91 | padding='valid', strides=(1, 1), data_format=None, 92 | kernel_regularizer=None, bias_regularizer=None, 93 | activity_regularizer=None, 94 | kernel_constraint=None, bias_constraint=None, 95 | use_bias=True, **kwargs): 96 | if data_format is None: 97 | data_format = K.image_data_format() 98 | if padding not in {'valid', 'same', 'full'}: 99 | raise ValueError('Invalid border mode for CosineConvolution2D:', padding) 100 | self.filters = filters 101 | self.kernel_size = kernel_size 102 | self.nb_row, self.nb_col = self.kernel_size 103 | self.kernel_initializer = initializers.get(kernel_initializer) 104 | self.activation = activations.get(activation) 105 | self.padding = padding 106 | self.strides = tuple(strides) 107 | self.data_format = normalize_data_format(data_format) 108 | self.kernel_regularizer = regularizers.get(kernel_regularizer) 109 | self.bias_regularizer = regularizers.get(bias_regularizer) 110 | self.activity_regularizer = regularizers.get(activity_regularizer) 111 | 112 | self.kernel_constraint = constraints.get(kernel_constraint) 113 | self.bias_constraint = constraints.get(bias_constraint) 114 | 115 | self.use_bias = use_bias 116 | self.input_spec = [InputSpec(ndim=4)] 117 | self.initial_weights = weights 118 | super(CosineConvolution2D, self).__init__(**kwargs) 119 | 120 | def build(self, input_shape): 121 | if self.data_format == 'channels_first': 122 | stack_size = input_shape[1] 123 | self.kernel_shape = (self.filters, stack_size, self.nb_row, self.nb_col) 124 | self.kernel_norm_shape = (1, stack_size, self.nb_row, self.nb_col) 125 | elif self.data_format == 'channels_last': 126 | stack_size = input_shape[3] 127 | self.kernel_shape = (self.nb_row, self.nb_col, stack_size, self.filters) 128 | self.kernel_norm_shape = (self.nb_row, self.nb_col, stack_size, 1) 129 | else: 130 | raise ValueError('Invalid data_format:', self.data_format) 131 | self.W = self.add_weight(self.kernel_shape, 132 | initializer=functools.partial(self.kernel_initializer), 133 | name='{}_W'.format(self.name), 134 | regularizer=self.kernel_regularizer, 135 | constraint=self.kernel_constraint) 136 | 137 | self.kernel_norm = K.variable(np.ones(self.kernel_norm_shape), name='{}_kernel_norm'.format(self.name)) 138 | 139 | if self.use_bias: 140 | self.b = self.add_weight((self.filters,), 141 | initializer='zero', 142 | name='{}_b'.format(self.name), 143 | regularizer=self.bias_regularizer, 144 | constraint=self.bias_constraint) 145 | else: 146 | self.b = None 147 | 148 | if self.initial_weights is not None: 149 | self.set_weights(self.initial_weights) 150 | del self.initial_weights 151 | self.built = True 152 | 153 | def compute_output_shape(self, input_shape): 154 | if self.data_format == 'channels_first': 155 | rows = input_shape[2] 156 | cols = input_shape[3] 157 | elif self.data_format == 'channels_last': 158 | rows = input_shape[1] 159 | cols = input_shape[2] 160 | else: 161 | raise ValueError('Invalid data_format:', self.data_format) 162 | 163 | rows = conv_output_length(rows, self.nb_row, 164 | self.padding, self.strides[0]) 165 | cols = conv_output_length(cols, self.nb_col, 166 | self.padding, self.strides[1]) 167 | 168 | if self.data_format == 'channels_first': 169 | return (input_shape[0], self.filters, rows, cols) 170 | elif self.data_format == 'channels_last': 171 | return (input_shape[0], rows, cols, self.filters) 172 | 173 | def call(self, x, mask=None): 174 | b, xb = 0., 0. 175 | if self.data_format == 'channels_first': 176 | kernel_sum_axes = [1, 2, 3] 177 | if self.use_bias: 178 | b = K.reshape(self.b, (self.filters, 1, 1, 1)) 179 | xb = 1. 180 | elif self.data_format == 'channels_last': 181 | kernel_sum_axes = [0, 1, 2] 182 | if self.use_bias: 183 | b = K.reshape(self.b, (1, 1, 1, self.filters)) 184 | xb = 1. 185 | 186 | Wnorm = K.sqrt(K.sum(K.square(self.W), axis=kernel_sum_axes, keepdims=True) + K.square(b) + K.epsilon()) 187 | xnorm = K.sqrt(K.conv2d(K.square(x), self.kernel_norm, strides=self.strides, 188 | padding=self.padding, 189 | data_format=self.data_format, 190 | filter_shape=self.kernel_norm_shape) + xb + K.epsilon()) 191 | 192 | W = self.W / Wnorm 193 | 194 | output = K.conv2d(x, W, strides=self.strides, 195 | padding=self.padding, 196 | data_format=self.data_format, 197 | filter_shape=self.kernel_shape) 198 | 199 | if K.backend() == 'theano': 200 | xnorm = K.pattern_broadcast(xnorm, [False, True, False, False]) 201 | 202 | output /= xnorm 203 | 204 | if self.use_bias: 205 | b /= Wnorm 206 | if self.data_format == 'channels_first': 207 | b = K.reshape(b, (1, self.filters, 1, 1)) 208 | elif self.data_format == 'channels_last': 209 | b = K.reshape(b, (1, 1, 1, self.filters)) 210 | else: 211 | raise ValueError('Invalid data_format:', self.data_format) 212 | b /= xnorm 213 | output += b 214 | output = self.activation(output) 215 | return output 216 | 217 | def get_config(self): 218 | config = {'filters': self.filters, 219 | 'kernel_size': self.kernel_size, 220 | 'kernel_initializer': initializers.serialize(self.kernel_initializer), 221 | 'activation': activations.serialize(self.activation), 222 | 'padding': self.padding, 223 | 'strides': self.strides, 224 | 'data_format': self.data_format, 225 | 'kernel_regularizer': regularizers.serialize(self.kernel_regularizer), 226 | 'bias_regularizer': regularizers.serialize(self.bias_regularizer), 227 | 'activity_regularizer': regularizers.serialize(self.activity_regularizer), 228 | 'kernel_constraint': constraints.serialize(self.kernel_constraint), 229 | 'bias_constraint': constraints.serialize(self.bias_constraint), 230 | 'use_bias': self.use_bias} 231 | base_config = super(CosineConvolution2D, self).get_config() 232 | return dict(list(base_config.items()) + list(config.items())) 233 | 234 | 235 | CosineConv2D = CosineConvolution2D 236 | get_custom_objects().update({'CosineConvolution2D': CosineConvolution2D}) 237 | get_custom_objects().update({'CosineConv2D': CosineConv2D}) 238 | 239 | 240 | class SubPixelUpscaling(Layer): 241 | """ Sub-pixel convolutional upscaling layer based on the paper "Real-Time Single Image 242 | and Video Super-Resolution Using an Efficient Sub-Pixel Convolutional Neural Network" 243 | (https://arxiv.org/abs/1609.05158). 244 | This layer requires a Convolution2D prior to it, having output filters computed according to 245 | the formula : 246 | filters = k * (scale_factor * scale_factor) 247 | where k = a user defined number of filters (generally larger than 32) 248 | scale_factor = the upscaling factor (generally 2) 249 | This layer performs the depth to space operation on the convolution filters, and returns a 250 | tensor with the size as defined below. 251 | # Example : 252 | ```python 253 | # A standard subpixel upscaling block 254 | x = Convolution2D(256, 3, 3, padding='same', activation='relu')(...) 255 | u = SubPixelUpscaling(scale_factor=2)(x) 256 | [Optional] 257 | x = Convolution2D(256, 3, 3, padding='same', activation='relu')(u) 258 | ``` 259 | In practice, it is useful to have a second convolution layer after the 260 | SubPixelUpscaling layer to speed up the learning process. 261 | However, if you are stacking multiple SubPixelUpscaling blocks, it may increase 262 | the number of parameters greatly, so the Convolution layer after SubPixelUpscaling 263 | layer can be removed. 264 | # Arguments 265 | scale_factor: Upscaling factor. 266 | data_format: Can be None, 'channels_first' or 'channels_last'. 267 | # Input shape 268 | 4D tensor with shape: 269 | `(samples, k * (scale_factor * scale_factor) channels, rows, cols)` if data_format='channels_first' 270 | or 4D tensor with shape: 271 | `(samples, rows, cols, k * (scale_factor * scale_factor) channels)` if data_format='channels_last'. 272 | # Output shape 273 | 4D tensor with shape: 274 | `(samples, k channels, rows * scale_factor, cols * scale_factor))` if data_format='channels_first' 275 | or 4D tensor with shape: 276 | `(samples, rows * scale_factor, cols * scale_factor, k channels)` if data_format='channels_last'. 277 | """ 278 | 279 | def __init__(self, scale_factor=2, data_format=None, **kwargs): 280 | super(SubPixelUpscaling, self).__init__(**kwargs) 281 | 282 | self.scale_factor = scale_factor 283 | self.data_format = normalize_data_format(data_format) 284 | 285 | def build(self, input_shape): 286 | pass 287 | 288 | def call(self, x, mask=None): 289 | y = K.depth_to_space(x, self.scale_factor, self.data_format) 290 | return y 291 | 292 | def compute_output_shape(self, input_shape): 293 | if self.data_format == 'channels_first': 294 | b, k, r, c = input_shape 295 | return (b, k // (self.scale_factor ** 2), r * self.scale_factor, c * self.scale_factor) 296 | else: 297 | b, r, c, k = input_shape 298 | return (b, r * self.scale_factor, c * self.scale_factor, k // (self.scale_factor ** 2)) 299 | 300 | def get_config(self): 301 | config = {'scale_factor': self.scale_factor, 302 | 'data_format': self.data_format} 303 | base_config = super(SubPixelUpscaling, self).get_config() 304 | return dict(list(base_config.items()) + list(config.items())) 305 | -------------------------------------------------------------------------------- /Phase-I/prediction/dense_all_keras.py: -------------------------------------------------------------------------------- 1 | 2 | # -*- coding: utf-8 -*- 3 | '''DenseNet and DenseNet-FCN models for Keras. 4 | DenseNet is a network architecture where each layer is directly connected 5 | to every other layer in a feed-forward fashion (within each dense block). 6 | For each layer, the feature maps of all preceding layers are treated as 7 | separate inputs whereas its own feature maps are passed on as inputs to 8 | all subsequent layers. This connectivity pattern yields state-of-the-art 9 | accuracies on CIFAR10/100 (with or without data augmentation) and SVHN. 10 | On the large scale ILSVRC 2012 (ImageNet) dataset, DenseNet achieves a 11 | similar accuracy as ResNet, but using less than half the amount of 12 | parameters and roughly half the number of FLOPs. 13 | DenseNets support any input image size of 32x32 or greater, and are thus 14 | suited for CIFAR-10 or CIFAR-100 datasets. There are two types of DenseNets, 15 | one suited for smaller images (DenseNet) and one suited for ImageNet, 16 | called DenseNetImageNet. They are differentiated by the strided convolution 17 | and pooling operations prior to the initial dense block. 18 | The following table describes the size and accuracy of DenseNetImageNet models 19 | on the ImageNet dataset (single crop), for which weights are provided: 20 | ------------------------------------------------------------------------------------ 21 | Model type | ImageNet Acc (Top 1) | ImageNet Acc (Top 5) | Params (M) | 22 | ------------------------------------------------------------------------------------ 23 | | DenseNet-121 | 25.02 % | 7.71 % | 8.0 | 24 | | DenseNet-169 | 23.80 % | 6.85 % | 14.3 | 25 | | DenseNet-201 | 22.58 % | 6.34 % | 20.2 | 26 | | DenseNet-161 | 22.20 % | - % | 28.9 | 27 | ------------------------------------------------------------------------------------ 28 | DenseNets can be extended to image segmentation tasks as described in the 29 | paper "The One Hundred Layers Tiramisu: Fully Convolutional DenseNets for 30 | Semantic Segmentation". Here, the dense blocks are arranged and concatenated 31 | with long skip connections for state of the art performance on the CamVid dataset. 32 | # Reference 33 | - [Densely Connected Convolutional Networks](https://arxiv.org/pdf/1608.06993.pdf) 34 | - [The One Hundred Layers Tiramisu: Fully Convolutional DenseNets for Semantic Segmentation](https://arxiv.org/pdf/1611.09326.pdf) 35 | This implementation is based on the following reference code: 36 | - https://github.com/gpleiss/efficient_densenet_pytorch 37 | - https://github.com/liuzhuang13/DenseNet 38 | ''' 39 | from __future__ import print_function 40 | from __future__ import absolute_import 41 | from __future__ import division 42 | 43 | import warnings 44 | 45 | from keras.models import Model 46 | from keras.layers import Dense 47 | from keras.layers import Dropout 48 | from keras.layers import Activation 49 | from keras.layers import Reshape 50 | from keras.layers import Conv2D 51 | from keras.layers import Conv2DTranspose 52 | from keras.layers import UpSampling2D 53 | from keras.layers import MaxPooling2D 54 | from keras.layers import AveragePooling2D 55 | from keras.layers import GlobalMaxPooling2D 56 | from keras.layers import GlobalAveragePooling2D 57 | from keras.layers import Input 58 | from keras.layers import concatenate 59 | from keras.layers import BatchNormalization 60 | from keras.regularizers import l2 61 | from keras.utils.layer_utils import convert_all_kernels_in_model 62 | from keras.utils.data_utils import get_file 63 | from keras.engine.topology import get_source_inputs 64 | from keras.applications.imagenet_utils import _obtain_input_shape 65 | from keras.applications.imagenet_utils import decode_predictions 66 | from keras.applications.imagenet_utils import preprocess_input as _preprocess_input 67 | import keras.backend as K 68 | 69 | from convolutional import SubPixelUpscaling 70 | 71 | DENSENET_121_WEIGHTS_PATH = r'https://github.com/titu1994/DenseNet/releases/download/v3.0/DenseNet-BC-121-32.h5' 72 | DENSENET_161_WEIGHTS_PATH = r'https://github.com/titu1994/DenseNet/releases/download/v3.0/DenseNet-BC-161-48.h5' 73 | DENSENET_169_WEIGHTS_PATH = r'https://github.com/titu1994/DenseNet/releases/download/v3.0/DenseNet-BC-169-32.h5' 74 | DENSENET_121_WEIGHTS_PATH_NO_TOP = r'https://github.com/titu1994/DenseNet/releases/download/v3.0/DenseNet-BC-121-32-no-top.h5' 75 | DENSENET_161_WEIGHTS_PATH_NO_TOP = r'https://github.com/titu1994/DenseNet/releases/download/v3.0/DenseNet-BC-161-48-no-top.h5' 76 | DENSENET_169_WEIGHTS_PATH_NO_TOP = r'https://github.com/titu1994/DenseNet/releases/download/v3.0/DenseNet-BC-169-32-no-top.h5' 77 | 78 | 79 | def preprocess_input(x, data_format=None): 80 | """Preprocesses a tensor encoding a batch of images. 81 | # Arguments 82 | x: input Numpy tensor, 4D. 83 | data_format: data format of the image tensor. 84 | # Returns 85 | Preprocessed tensor. 86 | """ 87 | x = _preprocess_input(x, data_format=data_format) 88 | x *= 0.017 # scale values 89 | return x 90 | 91 | 92 | def DenseNet(input_shape=None, 93 | depth=40, 94 | nb_dense_block=3, 95 | growth_rate=12, 96 | nb_filter=-1, 97 | nb_layers_per_block=-1, 98 | bottleneck=False, 99 | reduction=0.0, 100 | dropout_rate=0.0, 101 | weight_decay=1e-4, 102 | subsample_initial_block=False, 103 | include_top=True, 104 | weights=None, 105 | input_tensor=None, 106 | pooling=None, 107 | classes=10, 108 | activation='softmax', 109 | transition_pooling='avg'): 110 | '''Instantiate the DenseNet architecture. 111 | The model and the weights are compatible with both 112 | TensorFlow and Theano. The dimension ordering 113 | convention used by the model is the one 114 | specified in your Keras config file. 115 | # Arguments 116 | input_shape: optional shape tuple, only to be specified 117 | if `include_top` is False (otherwise the input shape 118 | has to be `(224, 224, 3)` (with `channels_last` dim ordering) 119 | or `(3, 224, 224)` (with `channels_first` dim ordering). 120 | It should have exactly 3 inputs channels, 121 | and width and height should be no smaller than 8. 122 | E.g. `(224, 224, 3)` would be one valid value. 123 | depth: number or layers in the DenseNet 124 | nb_dense_block: number of dense blocks to add to end 125 | growth_rate: number of filters to add per dense block 126 | nb_filter: initial number of filters. -1 indicates initial 127 | number of filters will default to 2 * growth_rate 128 | nb_layers_per_block: number of layers in each dense block. 129 | Can be a -1, positive integer or a list. 130 | If -1, calculates nb_layer_per_block from the network depth. 131 | If positive integer, a set number of layers per dense block. 132 | If list, nb_layer is used as provided. Note that list size must 133 | be nb_dense_block 134 | bottleneck: flag to add bottleneck blocks in between dense blocks 135 | reduction: reduction factor of transition blocks. 136 | Note : reduction value is inverted to compute compression. 137 | dropout_rate: dropout rate 138 | weight_decay: weight decay rate 139 | subsample_initial_block: Changes model type to suit different datasets. 140 | Should be set to True for ImageNet, and False for CIFAR datasets. 141 | When set to True, the initial convolution will be strided and 142 | adds a MaxPooling2D before the initial dense block. 143 | include_top: whether to include the fully-connected 144 | layer at the top of the network. 145 | weights: one of `None` (random initialization) or 146 | 'imagenet' (pre-training on ImageNet).. 147 | input_tensor: optional Keras tensor (i.e. output of `layers.Input()`) 148 | to use as image input for the model. 149 | pooling: Optional pooling mode for feature extraction 150 | when `include_top` is `False`. 151 | - `None` means that the output of the model 152 | will be the 4D tensor output of the 153 | last convolutional layer. 154 | - `avg` means that global average pooling 155 | will be applied to the output of the 156 | last convolutional layer, and thus 157 | the output of the model will be a 158 | 2D tensor. 159 | - `max` means that global max pooling will 160 | be applied. 161 | classes: optional number of classes to classify images 162 | into, only to be specified if `include_top` is True, and 163 | if no `weights` argument is specified. 164 | activation: Type of activation at the top layer. Can be one of 165 | 'softmax' or 'sigmoid'. Note that if sigmoid is used, 166 | classes must be 1. 167 | transition_pooling: `avg` for avg pooling (default), `max` for max pooling, 168 | None for no pooling during scale transition blocks. Please note that this 169 | default differs from the DenseNetFCN paper in accordance with the DenseNet 170 | paper. 171 | # Returns 172 | A Keras model instance. 173 | # Raises 174 | ValueError: in case of invalid argument for `weights`, 175 | or invalid input shape. 176 | ''' 177 | 178 | if weights not in {'imagenet', None}: 179 | raise ValueError('The `weights` argument should be either ' 180 | '`None` (random initialization) or `imagenet` ' 181 | '(pre-training on ImageNet).') 182 | 183 | if weights == 'imagenet' and include_top and classes != 1000: 184 | raise ValueError('If using `weights` as ImageNet with `include_top` ' 185 | 'as true, `classes` should be 1000') 186 | 187 | if activation not in ['softmax', 'sigmoid']: 188 | raise ValueError('activation must be one of "softmax" or "sigmoid"') 189 | 190 | if activation == 'sigmoid' and classes != 1: 191 | raise ValueError('sigmoid activation can only be used when classes = 1') 192 | 193 | # Determine proper input shape 194 | input_shape = _obtain_input_shape(input_shape, 195 | default_size=32, 196 | min_size=8, 197 | data_format=K.image_data_format(), 198 | require_flatten=include_top) 199 | 200 | if input_tensor is None: 201 | img_input = Input(shape=input_shape) 202 | else: 203 | if not K.is_keras_tensor(input_tensor): 204 | img_input = Input(tensor=input_tensor, shape=input_shape) 205 | else: 206 | img_input = input_tensor 207 | 208 | x = __create_dense_net(classes, img_input, include_top, depth, nb_dense_block, 209 | growth_rate, nb_filter, nb_layers_per_block, bottleneck, 210 | reduction, dropout_rate, weight_decay, subsample_initial_block, 211 | pooling, activation, transition_pooling) 212 | 213 | # Ensure that the model takes into account 214 | # any potential predecessors of `input_tensor`. 215 | if input_tensor is not None: 216 | inputs = get_source_inputs(input_tensor) 217 | else: 218 | inputs = img_input 219 | # Create model. 220 | model = Model(inputs, x, name='densenet') 221 | 222 | # load weights 223 | if weights == 'imagenet': 224 | weights_loaded = False 225 | 226 | if (depth == 121) and (nb_dense_block == 4) and (growth_rate == 32) and (nb_filter == 64) and \ 227 | (bottleneck is True) and (reduction == 0.5) and (subsample_initial_block): 228 | if include_top: 229 | weights_path = get_file('DenseNet-BC-121-32.h5', 230 | DENSENET_121_WEIGHTS_PATH, 231 | cache_subdir='models', 232 | md5_hash='a439dd41aa672aef6daba4ee1fd54abd') 233 | else: 234 | weights_path = get_file('DenseNet-BC-121-32-no-top.h5', 235 | DENSENET_121_WEIGHTS_PATH_NO_TOP, 236 | cache_subdir='models', 237 | md5_hash='55e62a6358af8a0af0eedf399b5aea99') 238 | model.load_weights(weights_path, by_name=True) 239 | weights_loaded = True 240 | 241 | if (depth == 161) and (nb_dense_block == 4) and (growth_rate == 48) and (nb_filter == 96) and \ 242 | (bottleneck is True) and (reduction == 0.5) and (subsample_initial_block): 243 | if include_top: 244 | weights_path = get_file('DenseNet-BC-161-48.h5', 245 | DENSENET_161_WEIGHTS_PATH, 246 | cache_subdir='models', 247 | md5_hash='6c326cf4fbdb57d31eff04333a23fcca') 248 | else: 249 | weights_path = get_file('DenseNet-BC-161-48-no-top.h5', 250 | DENSENET_161_WEIGHTS_PATH_NO_TOP, 251 | cache_subdir='models', 252 | md5_hash='1a9476b79f6b7673acaa2769e6427b92') 253 | model.load_weights(weights_path, by_name=True) 254 | weights_loaded = True 255 | 256 | if (depth == 169) and (nb_dense_block == 4) and (growth_rate == 32) and (nb_filter == 64) and \ 257 | (bottleneck is True) and (reduction == 0.5) and (subsample_initial_block): 258 | if include_top: 259 | weights_path = get_file('DenseNet-BC-169-32.h5', 260 | DENSENET_169_WEIGHTS_PATH, 261 | cache_subdir='models', 262 | md5_hash='914869c361303d2e39dec640b4e606a6') 263 | else: 264 | weights_path = get_file('DenseNet-BC-169-32-no-top.h5', 265 | DENSENET_169_WEIGHTS_PATH_NO_TOP, 266 | cache_subdir='models', 267 | md5_hash='89c19e8276cfd10585d5fadc1df6859e') 268 | model.load_weights(weights_path, by_name=True) 269 | weights_loaded = True 270 | 271 | if weights_loaded: 272 | if K.backend() == 'theano': 273 | convert_all_kernels_in_model(model) 274 | 275 | if K.image_data_format() == 'channels_first' and K.backend() == 'tensorflow': 276 | warnings.warn('You are using the TensorFlow backend, yet you ' 277 | 'are using the Theano ' 278 | 'image data format convention ' 279 | '(`image_data_format="channels_first"`). ' 280 | 'For best performance, set ' 281 | '`image_data_format="channels_last"` in ' 282 | 'your Keras config ' 283 | 'at ~/.keras/keras.json.') 284 | 285 | print("Weights for the model were loaded successfully") 286 | 287 | return model 288 | 289 | 290 | def DenseNetFCN(input_shape, nb_dense_block=5, growth_rate=16, nb_layers_per_block=4, 291 | reduction=0.0, dropout_rate=0.0, weight_decay=1E-4, init_conv_filters=48, 292 | include_top=True, weights=None, input_tensor=None, classes=1, activation='softmax', 293 | upsampling_conv=128, upsampling_type='deconv', early_transition=False, 294 | transition_pooling='max', initial_kernel_size=(3, 3)): 295 | '''Instantiate the DenseNet FCN architecture. 296 | Note that when using TensorFlow, 297 | for best performance you should set 298 | `image_data_format='channels_last'` in your Keras config 299 | at ~/.keras/keras.json. 300 | # Arguments 301 | nb_dense_block: number of dense blocks to add to end (generally = 3) 302 | growth_rate: number of filters to add per dense block 303 | nb_layers_per_block: number of layers in each dense block. 304 | Can be a positive integer or a list. 305 | If positive integer, a set number of layers per dense block. 306 | If list, nb_layer is used as provided. Note that list size must 307 | be (nb_dense_block + 1) 308 | reduction: reduction factor of transition blocks. 309 | Note : reduction value is inverted to compute compression. 310 | dropout_rate: dropout rate 311 | weight_decay: weight decay factor 312 | init_conv_filters: number of layers in the initial convolution layer 313 | include_top: whether to include the fully-connected 314 | layer at the top of the network. 315 | weights: one of `None` (random initialization) or 316 | 'cifar10' (pre-training on CIFAR-10).. 317 | input_tensor: optional Keras tensor (i.e. output of `layers.Input()`) 318 | to use as image input for the model. 319 | input_shape: optional shape tuple, only to be specified 320 | if `include_top` is False (otherwise the input shape 321 | has to be `(32, 32, 3)` (with `channels_last` dim ordering) 322 | or `(3, 32, 32)` (with `channels_first` dim ordering). 323 | It should have exactly 3 inputs channels, 324 | and width and height should be no smaller than 8. 325 | E.g. `(200, 200, 3)` would be one valid value. 326 | classes: optional number of classes to classify images 327 | into, only to be specified if `include_top` is True, and 328 | if no `weights` argument is specified. 329 | activation: Type of activation at the top layer. Can be one of 'softmax' or 'sigmoid'. 330 | Note that if sigmoid is used, classes must be 1. 331 | upsampling_conv: number of convolutional layers in upsampling via subpixel convolution 332 | upsampling_type: Can be one of 'deconv', 'upsampling' and 333 | 'subpixel'. Defines type of upsampling algorithm used. 334 | batchsize: Fixed batch size. This is a temporary requirement for 335 | computation of output shape in the case of Deconvolution2D layers. 336 | Parameter will be removed in next iteration of Keras, which infers 337 | output shape of deconvolution layers automatically. 338 | early_transition: Start with an extra initial transition down and end with an extra 339 | transition up to reduce the network size. 340 | initial_kernel_size: The first Conv2D kernel might vary in size based on the 341 | application, this parameter makes it configurable. 342 | # Returns 343 | A Keras model instance. 344 | ''' 345 | 346 | if weights not in {None}: 347 | raise ValueError('The `weights` argument should be ' 348 | '`None` (random initialization) as no ' 349 | 'model weights are provided.') 350 | 351 | upsampling_type = upsampling_type.lower() 352 | 353 | if upsampling_type not in ['upsampling', 'deconv', 'subpixel']: 354 | raise ValueError('Parameter "upsampling_type" must be one of "upsampling", ' 355 | '"deconv" or "subpixel".') 356 | 357 | if input_shape is None: 358 | raise ValueError('For fully convolutional models, input shape must be supplied.') 359 | 360 | if type(nb_layers_per_block) is not list and nb_dense_block < 1: 361 | raise ValueError('Number of dense layers per block must be greater than 1. Argument ' 362 | 'value was %d.' % (nb_layers_per_block)) 363 | 364 | if activation not in ['softmax', 'sigmoid']: 365 | raise ValueError('activation must be one of "softmax" or "sigmoid"') 366 | 367 | if activation == 'sigmoid' and classes != 1: 368 | raise ValueError('sigmoid activation can only be used when classes = 1') 369 | 370 | # Determine proper input shape 371 | min_size = 2 ** nb_dense_block 372 | 373 | if K.image_data_format() == 'channels_first': 374 | if input_shape is not None: 375 | if ((input_shape[1] is not None and input_shape[1] < min_size) or 376 | (input_shape[2] is not None and input_shape[2] < min_size)): 377 | raise ValueError('Input size must be at least ' + 378 | str(min_size) + 'x' + str(min_size) + ', got ' 379 | '`input_shape=' + str(input_shape) + '`') 380 | else: 381 | input_shape = (classes, None, None) 382 | else: 383 | if input_shape is not None: 384 | if ((input_shape[0] is not None and input_shape[0] < min_size) or 385 | (input_shape[1] is not None and input_shape[1] < min_size)): 386 | raise ValueError('Input size must be at least ' + 387 | str(min_size) + 'x' + str(min_size) + ', got ' 388 | '`input_shape=' + str(input_shape) + '`') 389 | else: 390 | input_shape = (None, None, classes) 391 | 392 | if input_tensor is None: 393 | img_input = Input(shape=input_shape) 394 | else: 395 | if not K.is_keras_tensor(input_tensor): 396 | img_input = Input(tensor=input_tensor, shape=input_shape) 397 | else: 398 | img_input = input_tensor 399 | 400 | x = __create_fcn_dense_net(classes, img_input, include_top, nb_dense_block, growth_rate, 401 | reduction, dropout_rate, weight_decay, 402 | nb_layers_per_block, upsampling_conv, upsampling_type, 403 | init_conv_filters, input_shape, activation, 404 | early_transition, transition_pooling, initial_kernel_size) 405 | 406 | # Ensure that the model takes into account 407 | # any potential predecessors of `input_tensor`. 408 | if input_tensor is not None: 409 | inputs = get_source_inputs(input_tensor) 410 | else: 411 | inputs = img_input 412 | # Create model. 413 | model = Model(inputs, x, name='fcn-densenet') 414 | 415 | return model 416 | 417 | 418 | def DenseNetImageNet121(input_shape=None, 419 | bottleneck=True, 420 | reduction=0.5, 421 | dropout_rate=0.0, 422 | weight_decay=1e-4, 423 | include_top=True, 424 | weights='imagenet', 425 | input_tensor=None, 426 | pooling=None, 427 | classes=1000, 428 | activation='softmax'): 429 | return DenseNet(input_shape, depth=121, nb_dense_block=4, growth_rate=32, nb_filter=64, 430 | nb_layers_per_block=[6, 12, 24, 16], bottleneck=bottleneck, reduction=reduction, 431 | dropout_rate=dropout_rate, weight_decay=weight_decay, subsample_initial_block=True, 432 | include_top=include_top, weights=weights, input_tensor=input_tensor, 433 | pooling=pooling, classes=classes, activation=activation) 434 | 435 | 436 | def DenseNetImageNet169(input_shape=None, 437 | bottleneck=True, 438 | reduction=0.5, 439 | dropout_rate=0.0, 440 | weight_decay=1e-4, 441 | include_top=True, 442 | weights='imagenet', 443 | input_tensor=None, 444 | pooling=None, 445 | classes=1000, 446 | activation='softmax'): 447 | return DenseNet(input_shape, depth=169, nb_dense_block=4, growth_rate=32, nb_filter=64, 448 | nb_layers_per_block=[6, 12, 32, 32], bottleneck=bottleneck, reduction=reduction, 449 | dropout_rate=dropout_rate, weight_decay=weight_decay, subsample_initial_block=True, 450 | include_top=include_top, weights=weights, input_tensor=input_tensor, 451 | pooling=pooling, classes=classes, activation=activation) 452 | 453 | 454 | def DenseNetImageNet201(input_shape=None, 455 | bottleneck=True, 456 | reduction=0.5, 457 | dropout_rate=0.0, 458 | weight_decay=1e-4, 459 | include_top=True, 460 | weights=None, 461 | input_tensor=None, 462 | pooling=None, 463 | classes=1000, 464 | activation='softmax'): 465 | return DenseNet(input_shape, depth=201, nb_dense_block=4, growth_rate=32, nb_filter=64, 466 | nb_layers_per_block=[6, 12, 48, 32], bottleneck=bottleneck, reduction=reduction, 467 | dropout_rate=dropout_rate, weight_decay=weight_decay, subsample_initial_block=True, 468 | include_top=include_top, weights=weights, input_tensor=input_tensor, 469 | pooling=pooling, classes=classes, activation=activation) 470 | 471 | 472 | def DenseNetImageNet264(input_shape=None, 473 | bottleneck=True, 474 | reduction=0.5, 475 | dropout_rate=0.0, 476 | weight_decay=1e-4, 477 | include_top=True, 478 | weights=None, 479 | input_tensor=None, 480 | pooling=None, 481 | classes=1000, 482 | activation='softmax'): 483 | return DenseNet(input_shape, depth=264, nb_dense_block=4, growth_rate=32, nb_filter=64, 484 | nb_layers_per_block=[6, 12, 64, 48], bottleneck=bottleneck, reduction=reduction, 485 | dropout_rate=dropout_rate, weight_decay=weight_decay, subsample_initial_block=True, 486 | include_top=include_top, weights=weights, input_tensor=input_tensor, 487 | pooling=pooling, classes=classes, activation=activation) 488 | 489 | 490 | def DenseNetImageNet161(input_shape=None, 491 | bottleneck=True, 492 | reduction=0.5, 493 | dropout_rate=0.0, 494 | weight_decay=1e-4, 495 | include_top=True, 496 | weights='imagenet', 497 | input_tensor=None, 498 | pooling=None, 499 | classes=1000, 500 | activation='softmax'): 501 | return DenseNet(input_shape, depth=161, nb_dense_block=4, growth_rate=48, nb_filter=96, 502 | nb_layers_per_block=[6, 12, 36, 24], bottleneck=bottleneck, reduction=reduction, 503 | dropout_rate=dropout_rate, weight_decay=weight_decay, subsample_initial_block=True, 504 | include_top=include_top, weights=weights, input_tensor=input_tensor, 505 | pooling=pooling, classes=classes, activation=activation) 506 | 507 | 508 | def name_or_none(prefix, name): 509 | return prefix + name if (prefix is not None and name is not None) else None 510 | 511 | 512 | def __conv_block(ip, nb_filter, bottleneck=False, dropout_rate=None, weight_decay=1e-4, block_prefix=None): 513 | ''' 514 | Adds a convolution layer (with batch normalization and relu), 515 | and optionally a bottleneck layer. 516 | # Arguments 517 | ip: Input tensor 518 | nb_filter: integer, the dimensionality of the output space 519 | (i.e. the number output of filters in the convolution) 520 | bottleneck: if True, adds a bottleneck convolution block 521 | dropout_rate: dropout rate 522 | weight_decay: weight decay factor 523 | block_prefix: str, for unique layer naming 524 | # Input shape 525 | 4D tensor with shape: 526 | `(samples, channels, rows, cols)` if data_format='channels_first' 527 | or 4D tensor with shape: 528 | `(samples, rows, cols, channels)` if data_format='channels_last'. 529 | # Output shape 530 | 4D tensor with shape: 531 | `(samples, filters, new_rows, new_cols)` if data_format='channels_first' 532 | or 4D tensor with shape: 533 | `(samples, new_rows, new_cols, filters)` if data_format='channels_last'. 534 | `rows` and `cols` values might have changed due to stride. 535 | # Returns 536 | output tensor of block 537 | ''' 538 | with K.name_scope('ConvBlock'): 539 | concat_axis = 1 if K.image_data_format() == 'channels_first' else -1 540 | 541 | x = BatchNormalization(axis=concat_axis, epsilon=1.1e-5, name=name_or_none(block_prefix, '_bn'))(ip) 542 | x = Activation('relu')(x) 543 | 544 | if bottleneck: 545 | inter_channel = nb_filter * 4 546 | 547 | x = Conv2D(inter_channel, (1, 1), kernel_initializer='he_normal', padding='same', use_bias=False, 548 | kernel_regularizer=l2(weight_decay), name=name_or_none(block_prefix, '_bottleneck_conv2D'))(x) 549 | x = BatchNormalization(axis=concat_axis, epsilon=1.1e-5, 550 | name=name_or_none(block_prefix, '_bottleneck_bn'))(x) 551 | x = Activation('relu')(x) 552 | 553 | x = Conv2D(nb_filter, (3, 3), kernel_initializer='he_normal', padding='same', use_bias=False, 554 | name=name_or_none(block_prefix, '_conv2D'))(x) 555 | if dropout_rate: 556 | x = Dropout(dropout_rate)(x) 557 | 558 | return x 559 | 560 | 561 | def __dense_block(x, nb_layers, nb_filter, growth_rate, bottleneck=False, dropout_rate=None, 562 | weight_decay=1e-4, grow_nb_filters=True, return_concat_list=False, block_prefix=None): 563 | ''' 564 | Build a dense_block where the output of each conv_block is fed 565 | to subsequent ones 566 | # Arguments 567 | x: input keras tensor 568 | nb_layers: the number of conv_blocks to append to the model 569 | nb_filter: integer, the dimensionality of the output space 570 | (i.e. the number output of filters in the convolution) 571 | growth_rate: growth rate of the dense block 572 | bottleneck: if True, adds a bottleneck convolution block to 573 | each conv_block 574 | dropout_rate: dropout rate 575 | weight_decay: weight decay factor 576 | grow_nb_filters: if True, allows number of filters to grow 577 | return_concat_list: set to True to return the list of 578 | feature maps along with the actual output 579 | block_prefix: str, for block unique naming 580 | # Return 581 | If return_concat_list is True, returns a list of the output 582 | keras tensor, the number of filters and a list of all the 583 | dense blocks added to the keras tensor 584 | If return_concat_list is False, returns a list of the output 585 | keras tensor and the number of filters 586 | ''' 587 | with K.name_scope('DenseBlock'): 588 | concat_axis = 1 if K.image_data_format() == 'channels_first' else -1 589 | 590 | x_list = [x] 591 | 592 | for i in range(nb_layers): 593 | cb = __conv_block(x, growth_rate, bottleneck, dropout_rate, weight_decay, 594 | block_prefix=name_or_none(block_prefix, '_%i' % i)) 595 | x_list.append(cb) 596 | 597 | x = concatenate([x, cb], axis=concat_axis) 598 | 599 | if grow_nb_filters: 600 | nb_filter += growth_rate 601 | 602 | if return_concat_list: 603 | return x, nb_filter, x_list 604 | else: 605 | return x, nb_filter 606 | 607 | 608 | def __transition_block(ip, nb_filter, compression=1.0, weight_decay=1e-4, block_prefix=None, transition_pooling='max'): 609 | ''' 610 | Adds a pointwise convolution layer (with batch normalization and relu), 611 | and an average pooling layer. The number of output convolution filters 612 | can be reduced by appropriately reducing the compression parameter. 613 | # Arguments 614 | ip: input keras tensor 615 | nb_filter: integer, the dimensionality of the output space 616 | (i.e. the number output of filters in the convolution) 617 | compression: calculated as 1 - reduction. Reduces the number 618 | of feature maps in the transition block. 619 | weight_decay: weight decay factor 620 | block_prefix: str, for block unique naming 621 | # Input shape 622 | 4D tensor with shape: 623 | `(samples, channels, rows, cols)` if data_format='channels_first' 624 | or 4D tensor with shape: 625 | `(samples, rows, cols, channels)` if data_format='channels_last'. 626 | # Output shape 627 | 4D tensor with shape: 628 | `(samples, nb_filter * compression, rows / 2, cols / 2)` 629 | if data_format='channels_first' 630 | or 4D tensor with shape: 631 | `(samples, rows / 2, cols / 2, nb_filter * compression)` 632 | if data_format='channels_last'. 633 | # Returns 634 | a keras tensor 635 | ''' 636 | with K.name_scope('Transition'): 637 | concat_axis = 1 if K.image_data_format() == 'channels_first' else -1 638 | 639 | x = BatchNormalization(axis=concat_axis, epsilon=1.1e-5, name=name_or_none(block_prefix, '_bn'))(ip) 640 | x = Activation('relu')(x) 641 | x = Conv2D(int(nb_filter * compression), (1, 1), kernel_initializer='he_normal', padding='same', 642 | use_bias=False, kernel_regularizer=l2(weight_decay), name=name_or_none(block_prefix, '_conv2D'))(x) 643 | if transition_pooling == 'avg': 644 | x = AveragePooling2D((2, 2), strides=(2, 2))(x) 645 | elif transition_pooling == 'max': 646 | x = MaxPooling2D((2, 2), strides=(2, 2))(x) 647 | 648 | return x 649 | 650 | 651 | def __transition_up_block(ip, nb_filters, type='deconv', weight_decay=1E-4, block_prefix=None): 652 | '''Adds an upsampling block. Upsampling operation relies on the the type parameter. 653 | # Arguments 654 | ip: input keras tensor 655 | nb_filters: integer, the dimensionality of the output space 656 | (i.e. the number output of filters in the convolution) 657 | type: can be 'upsampling', 'subpixel', 'deconv'. Determines 658 | type of upsampling performed 659 | weight_decay: weight decay factor 660 | block_prefix: str, for block unique naming 661 | # Input shape 662 | 4D tensor with shape: 663 | `(samples, channels, rows, cols)` if data_format='channels_first' 664 | or 4D tensor with shape: 665 | `(samples, rows, cols, channels)` if data_format='channels_last'. 666 | # Output shape 667 | 4D tensor with shape: 668 | `(samples, nb_filter, rows * 2, cols * 2)` if data_format='channels_first' 669 | or 4D tensor with shape: 670 | `(samples, rows * 2, cols * 2, nb_filter)` if data_format='channels_last'. 671 | # Returns 672 | a keras tensor 673 | ''' 674 | with K.name_scope('TransitionUp'): 675 | 676 | if type == 'upsampling': 677 | x = UpSampling2D(name=name_or_none(block_prefix, '_upsampling'))(ip) 678 | elif type == 'subpixel': 679 | x = Conv2D(nb_filters, (3, 3), activation='relu', padding='same', kernel_regularizer=l2(weight_decay), 680 | use_bias=False, kernel_initializer='he_normal', name=name_or_none(block_prefix, '_conv2D'))(ip) 681 | x = SubPixelUpscaling(scale_factor=2, name=name_or_none(block_prefix, '_subpixel'))(x) 682 | x = Conv2D(nb_filters, (3, 3), activation='relu', padding='same', kernel_regularizer=l2(weight_decay), 683 | use_bias=False, kernel_initializer='he_normal', name=name_or_none(block_prefix, '_conv2D'))(x) 684 | else: 685 | x = Conv2DTranspose(nb_filters, (3, 3), activation='relu', padding='same', strides=(2, 2), 686 | kernel_initializer='he_normal', kernel_regularizer=l2(weight_decay), 687 | name=name_or_none(block_prefix, '_conv2DT'))(ip) 688 | return x 689 | 690 | 691 | def __create_dense_net(nb_classes, img_input, include_top, depth=40, nb_dense_block=3, growth_rate=12, nb_filter=-1, 692 | nb_layers_per_block=-1, bottleneck=False, reduction=0.0, dropout_rate=None, weight_decay=1e-4, 693 | subsample_initial_block=False, pooling=None, activation='softmax', transition_pooling='avg'): 694 | ''' Build the DenseNet model 695 | # Arguments 696 | nb_classes: number of classes 697 | img_input: tuple of shape (channels, rows, columns) or (rows, columns, channels) 698 | include_top: flag to include the final Dense layer 699 | depth: number or layers 700 | nb_dense_block: number of dense blocks to add to end (generally = 3) 701 | growth_rate: number of filters to add per dense block 702 | nb_filter: initial number of filters. Default -1 indicates initial number of filters is 2 * growth_rate 703 | nb_layers_per_block: number of layers in each dense block. 704 | Can be a -1, positive integer or a list. 705 | If -1, calculates nb_layer_per_block from the depth of the network. 706 | If positive integer, a set number of layers per dense block. 707 | If list, nb_layer is used as provided. Note that list size must 708 | be (nb_dense_block + 1) 709 | bottleneck: add bottleneck blocks 710 | reduction: reduction factor of transition blocks. Note : reduction value is inverted to compute compression 711 | dropout_rate: dropout rate 712 | weight_decay: weight decay rate 713 | subsample_initial_block: Changes model type to suit different datasets. 714 | Should be set to True for ImageNet, and False for CIFAR datasets. 715 | When set to True, the initial convolution will be strided and 716 | adds a MaxPooling2D before the initial dense block. 717 | pooling: Optional pooling mode for feature extraction 718 | when `include_top` is `False`. 719 | - `None` means that the output of the model 720 | will be the 4D tensor output of the 721 | last convolutional layer. 722 | - `avg` means that global average pooling 723 | will be applied to the output of the 724 | last convolutional layer, and thus 725 | the output of the model will be a 726 | 2D tensor. 727 | - `max` means that global max pooling will 728 | be applied. 729 | activation: Type of activation at the top layer. Can be one of 'softmax' or 'sigmoid'. 730 | Note that if sigmoid is used, classes must be 1. 731 | transition_pooling: `avg` for avg pooling (default), `max` for max pooling, 732 | None for no pooling during scale transition blocks. Please note that this 733 | default differs from the DenseNetFCN paper in accordance with the DenseNet 734 | paper. 735 | # Returns 736 | a keras tensor 737 | # Raises 738 | ValueError: in case of invalid argument for `reduction` 739 | or `nb_dense_block` 740 | ''' 741 | with K.name_scope('DenseNet'): 742 | concat_axis = 1 if K.image_data_format() == 'channels_first' else -1 743 | 744 | if reduction != 0.0: 745 | if not (reduction <= 1.0 and reduction > 0.0): 746 | raise ValueError('`reduction` value must lie between 0.0 and 1.0') 747 | 748 | # layers in each dense block 749 | if type(nb_layers_per_block) is list or type(nb_layers_per_block) is tuple: 750 | nb_layers = list(nb_layers_per_block) # Convert tuple to list 751 | 752 | if len(nb_layers) != (nb_dense_block): 753 | raise ValueError('If `nb_dense_block` is a list, its length must match ' 754 | 'the number of layers provided by `nb_layers`.') 755 | 756 | final_nb_layer = nb_layers[-1] 757 | nb_layers = nb_layers[:-1] 758 | else: 759 | if nb_layers_per_block == -1: 760 | assert (depth - 4) % 3 == 0, 'Depth must be 3 N + 4 if nb_layers_per_block == -1' 761 | count = int((depth - 4) / 3) 762 | 763 | if bottleneck: 764 | count = count // 2 765 | 766 | nb_layers = [count for _ in range(nb_dense_block)] 767 | final_nb_layer = count 768 | else: 769 | final_nb_layer = nb_layers_per_block 770 | nb_layers = [nb_layers_per_block] * nb_dense_block 771 | 772 | # compute initial nb_filter if -1, else accept users initial nb_filter 773 | if nb_filter <= 0: 774 | nb_filter = 2 * growth_rate 775 | 776 | # compute compression factor 777 | compression = 1.0 - reduction 778 | 779 | # Initial convolution 780 | if subsample_initial_block: 781 | initial_kernel = (7, 7) 782 | initial_strides = (2, 2) 783 | else: 784 | initial_kernel = (3, 3) 785 | initial_strides = (1, 1) 786 | 787 | x = Conv2D(nb_filter, initial_kernel, kernel_initializer='he_normal', padding='same', name='initial_conv2D', 788 | strides=initial_strides, use_bias=False, kernel_regularizer=l2(weight_decay))(img_input) 789 | 790 | if subsample_initial_block: 791 | x = BatchNormalization(axis=concat_axis, epsilon=1.1e-5, name='initial_bn')(x) 792 | x = Activation('relu')(x) 793 | x = MaxPooling2D((3, 3), strides=(2, 2), padding='same')(x) 794 | 795 | # Add dense blocks 796 | for block_idx in range(nb_dense_block - 1): 797 | x, nb_filter = __dense_block(x, nb_layers[block_idx], nb_filter, growth_rate, bottleneck=bottleneck, 798 | dropout_rate=dropout_rate, weight_decay=weight_decay, 799 | block_prefix='dense_%i' % block_idx) 800 | # add transition_block 801 | x = __transition_block(x, nb_filter, compression=compression, weight_decay=weight_decay, 802 | block_prefix='tr_%i' % block_idx, transition_pooling=transition_pooling) 803 | nb_filter = int(nb_filter * compression) 804 | 805 | # The last dense_block does not have a transition_block 806 | x, nb_filter = __dense_block(x, final_nb_layer, nb_filter, growth_rate, bottleneck=bottleneck, 807 | dropout_rate=dropout_rate, weight_decay=weight_decay, 808 | block_prefix='dense_%i' % (nb_dense_block - 1)) 809 | 810 | x = BatchNormalization(axis=concat_axis, epsilon=1.1e-5, name='final_bn')(x) 811 | x = Activation('relu')(x) 812 | 813 | if include_top: 814 | if pooling == 'avg': 815 | x = GlobalAveragePooling2D()(x) 816 | elif pooling == 'max': 817 | x = GlobalMaxPooling2D()(x) 818 | x = Dense(nb_classes, activation=activation)(x) 819 | else: 820 | if pooling == 'avg': 821 | x = GlobalAveragePooling2D()(x) 822 | elif pooling == 'max': 823 | x = GlobalMaxPooling2D()(x) 824 | 825 | return x 826 | 827 | 828 | def __create_fcn_dense_net(nb_classes, img_input, include_top, nb_dense_block=5, growth_rate=12, 829 | reduction=0.0, dropout_rate=None, weight_decay=1e-4, 830 | nb_layers_per_block=4, nb_upsampling_conv=128, upsampling_type='deconv', 831 | init_conv_filters=48, input_shape=None, activation='softmax', 832 | early_transition=False, transition_pooling='max', initial_kernel_size=(3, 3)): 833 | ''' Build the DenseNet-FCN model 834 | # Arguments 835 | nb_classes: number of classes 836 | img_input: tuple of shape (channels, rows, columns) or (rows, columns, channels) 837 | include_top: flag to include the final Dense layer 838 | nb_dense_block: number of dense blocks to add to end (generally = 3) 839 | growth_rate: number of filters to add per dense block 840 | reduction: reduction factor of transition blocks. Note : reduction value is inverted to compute compression 841 | dropout_rate: dropout rate 842 | weight_decay: weight decay 843 | nb_layers_per_block: number of layers in each dense block. 844 | Can be a positive integer or a list. 845 | If positive integer, a set number of layers per dense block. 846 | If list, nb_layer is used as provided. Note that list size must 847 | be (nb_dense_block + 1) 848 | nb_upsampling_conv: number of convolutional layers in upsampling via subpixel convolution 849 | upsampling_type: Can be one of 'upsampling', 'deconv' and 'subpixel'. Defines 850 | type of upsampling algorithm used. 851 | input_shape: Only used for shape inference in fully convolutional networks. 852 | activation: Type of activation at the top layer. Can be one of 'softmax' or 'sigmoid'. 853 | Note that if sigmoid is used, classes must be 1. 854 | early_transition: Start with an extra initial transition down and end with an extra 855 | transition up to reduce the network size. 856 | transition_pooling: 'max' for max pooling (default), 'avg' for average pooling, 857 | None for no pooling. Please note that this default differs from the DenseNet 858 | paper in accordance with the DenseNetFCN paper. 859 | initial_kernel_size: The first Conv2D kernel might vary in size based on the 860 | application, this parameter makes it configurable. 861 | # Returns 862 | a keras tensor 863 | # Raises 864 | ValueError: in case of invalid argument for `reduction`, 865 | `nb_dense_block` or `nb_upsampling_conv`. 866 | ''' 867 | with K.name_scope('DenseNetFCN'): 868 | concat_axis = 1 if K.image_data_format() == 'channels_first' else -1 869 | 870 | if concat_axis == 1: # channels_first dim ordering 871 | _, rows, cols = input_shape 872 | else: 873 | rows, cols, _ = input_shape 874 | 875 | if reduction != 0.0: 876 | if not (reduction <= 1.0 and reduction > 0.0): 877 | raise ValueError('`reduction` value must lie between 0.0 and 1.0') 878 | 879 | # check if upsampling_conv has minimum number of filters 880 | # minimum is set to 12, as at least 3 color channels are needed for correct upsampling 881 | if not (nb_upsampling_conv > 12 and nb_upsampling_conv % 4 == 0): 882 | raise ValueError('Parameter `nb_upsampling_conv` number of channels must ' 883 | 'be a positive number divisible by 4 and greater than 12') 884 | 885 | # layers in each dense block 886 | if type(nb_layers_per_block) is list or type(nb_layers_per_block) is tuple: 887 | nb_layers = list(nb_layers_per_block) # Convert tuple to list 888 | 889 | if len(nb_layers) != (nb_dense_block + 1): 890 | raise ValueError('If `nb_dense_block` is a list, its length must be ' 891 | '(`nb_dense_block` + 1)') 892 | 893 | bottleneck_nb_layers = nb_layers[-1] 894 | rev_layers = nb_layers[::-1] 895 | nb_layers.extend(rev_layers[1:]) 896 | else: 897 | bottleneck_nb_layers = nb_layers_per_block 898 | nb_layers = [nb_layers_per_block] * (2 * nb_dense_block + 1) 899 | 900 | # compute compression factor 901 | compression = 1.0 - reduction 902 | 903 | # Initial convolution 904 | x = Conv2D(init_conv_filters, initial_kernel_size, kernel_initializer='he_normal', padding='same', name='initial_conv2D', 905 | use_bias=False, kernel_regularizer=l2(weight_decay))(img_input) 906 | x = BatchNormalization(axis=concat_axis, epsilon=1.1e-5, name='initial_bn')(x) 907 | x = Activation('relu')(x) 908 | 909 | nb_filter = init_conv_filters 910 | 911 | skip_list = [] 912 | 913 | if early_transition: 914 | x = __transition_block(x, nb_filter, compression=compression, weight_decay=weight_decay, 915 | block_prefix='tr_early', transition_pooling=transition_pooling) 916 | 917 | # Add dense blocks and transition down block 918 | for block_idx in range(nb_dense_block): 919 | x, nb_filter = __dense_block(x, nb_layers[block_idx], nb_filter, growth_rate, dropout_rate=dropout_rate, 920 | weight_decay=weight_decay, block_prefix='dense_%i' % block_idx) 921 | 922 | # Skip connection 923 | skip_list.append(x) 924 | 925 | # add transition_block 926 | x = __transition_block(x, nb_filter, compression=compression, weight_decay=weight_decay, 927 | block_prefix='tr_%i' % block_idx, transition_pooling=transition_pooling) 928 | 929 | nb_filter = int(nb_filter * compression) # this is calculated inside transition_down_block 930 | 931 | # The last dense_block does not have a transition_down_block 932 | # return the concatenated feature maps without the concatenation of the input 933 | _, nb_filter, concat_list = __dense_block(x, bottleneck_nb_layers, nb_filter, growth_rate, 934 | dropout_rate=dropout_rate, weight_decay=weight_decay, 935 | return_concat_list=True, 936 | block_prefix='dense_%i' % nb_dense_block) 937 | 938 | skip_list = skip_list[::-1] # reverse the skip list 939 | 940 | # Add dense blocks and transition up block 941 | for block_idx in range(nb_dense_block): 942 | n_filters_keep = growth_rate * nb_layers[nb_dense_block + block_idx] 943 | 944 | # upsampling block must upsample only the feature maps (concat_list[1:]), 945 | # not the concatenation of the input with the feature maps (concat_list[0]. 946 | l = concatenate(concat_list[1:], axis=concat_axis) 947 | 948 | t = __transition_up_block(l, nb_filters=n_filters_keep, type=upsampling_type, weight_decay=weight_decay, 949 | block_prefix='tr_up_%i' % block_idx) 950 | 951 | # concatenate the skip connection with the transition block 952 | x = concatenate([t, skip_list[block_idx]], axis=concat_axis) 953 | 954 | # Dont allow the feature map size to grow in upsampling dense blocks 955 | x_up, nb_filter, concat_list = __dense_block(x, nb_layers[nb_dense_block + block_idx + 1], 956 | nb_filter=growth_rate, growth_rate=growth_rate, 957 | dropout_rate=dropout_rate, weight_decay=weight_decay, 958 | return_concat_list=True, grow_nb_filters=False, 959 | block_prefix='dense_%i' % (nb_dense_block + 1 + block_idx)) 960 | 961 | if early_transition: 962 | x_up = __transition_up_block(x_up, nb_filters=nb_filter, type=upsampling_type, weight_decay=weight_decay, 963 | block_prefix='tr_up_early') 964 | if include_top: 965 | x = Conv2D(nb_classes, (1, 1), activation='linear', padding='same', use_bias=False)(x_up) 966 | 967 | if K.image_data_format() == 'channels_first': 968 | channel, row, col = input_shape 969 | else: 970 | row, col, channel = input_shape 971 | 972 | x = Reshape((row * col, nb_classes))(x) 973 | x = Activation(activation)(x) 974 | x = Reshape((row, col, nb_classes))(x) 975 | else: 976 | x = x_up 977 | 978 | return x 979 | -------------------------------------------------------------------------------- /Phase-I/training/dense_all_keras.py: -------------------------------------------------------------------------------- 1 | 2 | # -*- coding: utf-8 -*- 3 | '''DenseNet and DenseNet-FCN models for Keras. 4 | DenseNet is a network architecture where each layer is directly connected 5 | to every other layer in a feed-forward fashion (within each dense block). 6 | For each layer, the feature maps of all preceding layers are treated as 7 | separate inputs whereas its own feature maps are passed on as inputs to 8 | all subsequent layers. This connectivity pattern yields state-of-the-art 9 | accuracies on CIFAR10/100 (with or without data augmentation) and SVHN. 10 | On the large scale ILSVRC 2012 (ImageNet) dataset, DenseNet achieves a 11 | similar accuracy as ResNet, but using less than half the amount of 12 | parameters and roughly half the number of FLOPs. 13 | DenseNets support any input image size of 32x32 or greater, and are thus 14 | suited for CIFAR-10 or CIFAR-100 datasets. There are two types of DenseNets, 15 | one suited for smaller images (DenseNet) and one suited for ImageNet, 16 | called DenseNetImageNet. They are differentiated by the strided convolution 17 | and pooling operations prior to the initial dense block. 18 | The following table describes the size and accuracy of DenseNetImageNet models 19 | on the ImageNet dataset (single crop), for which weights are provided: 20 | ------------------------------------------------------------------------------------ 21 | Model type | ImageNet Acc (Top 1) | ImageNet Acc (Top 5) | Params (M) | 22 | ------------------------------------------------------------------------------------ 23 | | DenseNet-121 | 25.02 % | 7.71 % | 8.0 | 24 | | DenseNet-169 | 23.80 % | 6.85 % | 14.3 | 25 | | DenseNet-201 | 22.58 % | 6.34 % | 20.2 | 26 | | DenseNet-161 | 22.20 % | - % | 28.9 | 27 | ------------------------------------------------------------------------------------ 28 | DenseNets can be extended to image segmentation tasks as described in the 29 | paper "The One Hundred Layers Tiramisu: Fully Convolutional DenseNets for 30 | Semantic Segmentation". Here, the dense blocks are arranged and concatenated 31 | with long skip connections for state of the art performance on the CamVid dataset. 32 | # Reference 33 | - [Densely Connected Convolutional Networks](https://arxiv.org/pdf/1608.06993.pdf) 34 | - [The One Hundred Layers Tiramisu: Fully Convolutional DenseNets for Semantic Segmentation](https://arxiv.org/pdf/1611.09326.pdf) 35 | This implementation is based on the following reference code: 36 | - https://github.com/gpleiss/efficient_densenet_pytorch 37 | - https://github.com/liuzhuang13/DenseNet 38 | ''' 39 | from __future__ import print_function 40 | from __future__ import absolute_import 41 | from __future__ import division 42 | 43 | import warnings 44 | 45 | from keras.models import Model 46 | from keras.layers import Dense 47 | from keras.layers import Dropout 48 | from keras.layers import Activation 49 | from keras.layers import Reshape 50 | from keras.layers import Conv2D 51 | from keras.layers import Conv2DTranspose 52 | from keras.layers import UpSampling2D 53 | from keras.layers import MaxPooling2D 54 | from keras.layers import AveragePooling2D 55 | from keras.layers import GlobalMaxPooling2D 56 | from keras.layers import GlobalAveragePooling2D 57 | from keras.layers import Input 58 | from keras.layers import concatenate 59 | from keras.layers import BatchNormalization 60 | from keras.regularizers import l2 61 | from keras.utils.layer_utils import convert_all_kernels_in_model 62 | from keras.utils.data_utils import get_file 63 | from keras.engine.topology import get_source_inputs 64 | from keras.applications.imagenet_utils import _obtain_input_shape 65 | from keras.applications.imagenet_utils import decode_predictions 66 | from keras.applications.imagenet_utils import preprocess_input as _preprocess_input 67 | import keras.backend as K 68 | 69 | from convolutional import SubPixelUpscaling 70 | 71 | DENSENET_121_WEIGHTS_PATH = r'https://github.com/titu1994/DenseNet/releases/download/v3.0/DenseNet-BC-121-32.h5' 72 | DENSENET_161_WEIGHTS_PATH = r'https://github.com/titu1994/DenseNet/releases/download/v3.0/DenseNet-BC-161-48.h5' 73 | DENSENET_169_WEIGHTS_PATH = r'https://github.com/titu1994/DenseNet/releases/download/v3.0/DenseNet-BC-169-32.h5' 74 | DENSENET_121_WEIGHTS_PATH_NO_TOP = r'https://github.com/titu1994/DenseNet/releases/download/v3.0/DenseNet-BC-121-32-no-top.h5' 75 | DENSENET_161_WEIGHTS_PATH_NO_TOP = r'https://github.com/titu1994/DenseNet/releases/download/v3.0/DenseNet-BC-161-48-no-top.h5' 76 | DENSENET_169_WEIGHTS_PATH_NO_TOP = r'https://github.com/titu1994/DenseNet/releases/download/v3.0/DenseNet-BC-169-32-no-top.h5' 77 | 78 | 79 | def preprocess_input(x, data_format=None): 80 | """Preprocesses a tensor encoding a batch of images. 81 | # Arguments 82 | x: input Numpy tensor, 4D. 83 | data_format: data format of the image tensor. 84 | # Returns 85 | Preprocessed tensor. 86 | """ 87 | x = _preprocess_input(x, data_format=data_format) 88 | x *= 0.017 # scale values 89 | return x 90 | 91 | 92 | def DenseNet(input_shape=None, 93 | depth=40, 94 | nb_dense_block=3, 95 | growth_rate=12, 96 | nb_filter=-1, 97 | nb_layers_per_block=-1, 98 | bottleneck=False, 99 | reduction=0.0, 100 | dropout_rate=0.0, 101 | weight_decay=1e-4, 102 | subsample_initial_block=False, 103 | include_top=True, 104 | weights=None, 105 | input_tensor=None, 106 | pooling=None, 107 | classes=10, 108 | activation='softmax', 109 | transition_pooling='avg'): 110 | '''Instantiate the DenseNet architecture. 111 | The model and the weights are compatible with both 112 | TensorFlow and Theano. The dimension ordering 113 | convention used by the model is the one 114 | specified in your Keras config file. 115 | # Arguments 116 | input_shape: optional shape tuple, only to be specified 117 | if `include_top` is False (otherwise the input shape 118 | has to be `(224, 224, 3)` (with `channels_last` dim ordering) 119 | or `(3, 224, 224)` (with `channels_first` dim ordering). 120 | It should have exactly 3 inputs channels, 121 | and width and height should be no smaller than 8. 122 | E.g. `(224, 224, 3)` would be one valid value. 123 | depth: number or layers in the DenseNet 124 | nb_dense_block: number of dense blocks to add to end 125 | growth_rate: number of filters to add per dense block 126 | nb_filter: initial number of filters. -1 indicates initial 127 | number of filters will default to 2 * growth_rate 128 | nb_layers_per_block: number of layers in each dense block. 129 | Can be a -1, positive integer or a list. 130 | If -1, calculates nb_layer_per_block from the network depth. 131 | If positive integer, a set number of layers per dense block. 132 | If list, nb_layer is used as provided. Note that list size must 133 | be nb_dense_block 134 | bottleneck: flag to add bottleneck blocks in between dense blocks 135 | reduction: reduction factor of transition blocks. 136 | Note : reduction value is inverted to compute compression. 137 | dropout_rate: dropout rate 138 | weight_decay: weight decay rate 139 | subsample_initial_block: Changes model type to suit different datasets. 140 | Should be set to True for ImageNet, and False for CIFAR datasets. 141 | When set to True, the initial convolution will be strided and 142 | adds a MaxPooling2D before the initial dense block. 143 | include_top: whether to include the fully-connected 144 | layer at the top of the network. 145 | weights: one of `None` (random initialization) or 146 | 'imagenet' (pre-training on ImageNet).. 147 | input_tensor: optional Keras tensor (i.e. output of `layers.Input()`) 148 | to use as image input for the model. 149 | pooling: Optional pooling mode for feature extraction 150 | when `include_top` is `False`. 151 | - `None` means that the output of the model 152 | will be the 4D tensor output of the 153 | last convolutional layer. 154 | - `avg` means that global average pooling 155 | will be applied to the output of the 156 | last convolutional layer, and thus 157 | the output of the model will be a 158 | 2D tensor. 159 | - `max` means that global max pooling will 160 | be applied. 161 | classes: optional number of classes to classify images 162 | into, only to be specified if `include_top` is True, and 163 | if no `weights` argument is specified. 164 | activation: Type of activation at the top layer. Can be one of 165 | 'softmax' or 'sigmoid'. Note that if sigmoid is used, 166 | classes must be 1. 167 | transition_pooling: `avg` for avg pooling (default), `max` for max pooling, 168 | None for no pooling during scale transition blocks. Please note that this 169 | default differs from the DenseNetFCN paper in accordance with the DenseNet 170 | paper. 171 | # Returns 172 | A Keras model instance. 173 | # Raises 174 | ValueError: in case of invalid argument for `weights`, 175 | or invalid input shape. 176 | ''' 177 | 178 | if weights not in {'imagenet', None}: 179 | raise ValueError('The `weights` argument should be either ' 180 | '`None` (random initialization) or `imagenet` ' 181 | '(pre-training on ImageNet).') 182 | 183 | if weights == 'imagenet' and include_top and classes != 1000: 184 | raise ValueError('If using `weights` as ImageNet with `include_top` ' 185 | 'as true, `classes` should be 1000') 186 | 187 | if activation not in ['softmax', 'sigmoid']: 188 | raise ValueError('activation must be one of "softmax" or "sigmoid"') 189 | 190 | if activation == 'sigmoid' and classes != 1: 191 | raise ValueError('sigmoid activation can only be used when classes = 1') 192 | 193 | # Determine proper input shape 194 | input_shape = _obtain_input_shape(input_shape, 195 | default_size=32, 196 | min_size=8, 197 | data_format=K.image_data_format(), 198 | require_flatten=include_top) 199 | 200 | if input_tensor is None: 201 | img_input = Input(shape=input_shape) 202 | else: 203 | if not K.is_keras_tensor(input_tensor): 204 | img_input = Input(tensor=input_tensor, shape=input_shape) 205 | else: 206 | img_input = input_tensor 207 | 208 | x = __create_dense_net(classes, img_input, include_top, depth, nb_dense_block, 209 | growth_rate, nb_filter, nb_layers_per_block, bottleneck, 210 | reduction, dropout_rate, weight_decay, subsample_initial_block, 211 | pooling, activation, transition_pooling) 212 | 213 | # Ensure that the model takes into account 214 | # any potential predecessors of `input_tensor`. 215 | if input_tensor is not None: 216 | inputs = get_source_inputs(input_tensor) 217 | else: 218 | inputs = img_input 219 | # Create model. 220 | model = Model(inputs, x, name='densenet') 221 | 222 | # load weights 223 | if weights == 'imagenet': 224 | weights_loaded = False 225 | 226 | if (depth == 121) and (nb_dense_block == 4) and (growth_rate == 32) and (nb_filter == 64) and \ 227 | (bottleneck is True) and (reduction == 0.5) and (subsample_initial_block): 228 | if include_top: 229 | weights_path = get_file('DenseNet-BC-121-32.h5', 230 | DENSENET_121_WEIGHTS_PATH, 231 | cache_subdir='models', 232 | md5_hash='a439dd41aa672aef6daba4ee1fd54abd') 233 | else: 234 | weights_path = get_file('DenseNet-BC-121-32-no-top.h5', 235 | DENSENET_121_WEIGHTS_PATH_NO_TOP, 236 | cache_subdir='models', 237 | md5_hash='55e62a6358af8a0af0eedf399b5aea99') 238 | model.load_weights(weights_path, by_name=True) 239 | weights_loaded = True 240 | 241 | if (depth == 161) and (nb_dense_block == 4) and (growth_rate == 48) and (nb_filter == 96) and \ 242 | (bottleneck is True) and (reduction == 0.5) and (subsample_initial_block): 243 | if include_top: 244 | weights_path = get_file('DenseNet-BC-161-48.h5', 245 | DENSENET_161_WEIGHTS_PATH, 246 | cache_subdir='models', 247 | md5_hash='6c326cf4fbdb57d31eff04333a23fcca') 248 | else: 249 | weights_path = get_file('DenseNet-BC-161-48-no-top.h5', 250 | DENSENET_161_WEIGHTS_PATH_NO_TOP, 251 | cache_subdir='models', 252 | md5_hash='1a9476b79f6b7673acaa2769e6427b92') 253 | model.load_weights(weights_path, by_name=True) 254 | weights_loaded = True 255 | 256 | if (depth == 169) and (nb_dense_block == 4) and (growth_rate == 32) and (nb_filter == 64) and \ 257 | (bottleneck is True) and (reduction == 0.5) and (subsample_initial_block): 258 | if include_top: 259 | weights_path = get_file('DenseNet-BC-169-32.h5', 260 | DENSENET_169_WEIGHTS_PATH, 261 | cache_subdir='models', 262 | md5_hash='914869c361303d2e39dec640b4e606a6') 263 | else: 264 | weights_path = get_file('DenseNet-BC-169-32-no-top.h5', 265 | DENSENET_169_WEIGHTS_PATH_NO_TOP, 266 | cache_subdir='models', 267 | md5_hash='89c19e8276cfd10585d5fadc1df6859e') 268 | model.load_weights(weights_path, by_name=True) 269 | weights_loaded = True 270 | 271 | if weights_loaded: 272 | if K.backend() == 'theano': 273 | convert_all_kernels_in_model(model) 274 | 275 | if K.image_data_format() == 'channels_first' and K.backend() == 'tensorflow': 276 | warnings.warn('You are using the TensorFlow backend, yet you ' 277 | 'are using the Theano ' 278 | 'image data format convention ' 279 | '(`image_data_format="channels_first"`). ' 280 | 'For best performance, set ' 281 | '`image_data_format="channels_last"` in ' 282 | 'your Keras config ' 283 | 'at ~/.keras/keras.json.') 284 | 285 | print("Weights for the model were loaded successfully") 286 | 287 | return model 288 | 289 | 290 | def DenseNetFCN(input_shape, nb_dense_block=5, growth_rate=16, nb_layers_per_block=4, 291 | reduction=0.0, dropout_rate=0.0, weight_decay=1E-4, init_conv_filters=48, 292 | include_top=True, weights=None, input_tensor=None, classes=1, activation='softmax', 293 | upsampling_conv=128, upsampling_type='deconv', early_transition=False, 294 | transition_pooling='max', initial_kernel_size=(3, 3)): 295 | '''Instantiate the DenseNet FCN architecture. 296 | Note that when using TensorFlow, 297 | for best performance you should set 298 | `image_data_format='channels_last'` in your Keras config 299 | at ~/.keras/keras.json. 300 | # Arguments 301 | nb_dense_block: number of dense blocks to add to end (generally = 3) 302 | growth_rate: number of filters to add per dense block 303 | nb_layers_per_block: number of layers in each dense block. 304 | Can be a positive integer or a list. 305 | If positive integer, a set number of layers per dense block. 306 | If list, nb_layer is used as provided. Note that list size must 307 | be (nb_dense_block + 1) 308 | reduction: reduction factor of transition blocks. 309 | Note : reduction value is inverted to compute compression. 310 | dropout_rate: dropout rate 311 | weight_decay: weight decay factor 312 | init_conv_filters: number of layers in the initial convolution layer 313 | include_top: whether to include the fully-connected 314 | layer at the top of the network. 315 | weights: one of `None` (random initialization) or 316 | 'cifar10' (pre-training on CIFAR-10).. 317 | input_tensor: optional Keras tensor (i.e. output of `layers.Input()`) 318 | to use as image input for the model. 319 | input_shape: optional shape tuple, only to be specified 320 | if `include_top` is False (otherwise the input shape 321 | has to be `(32, 32, 3)` (with `channels_last` dim ordering) 322 | or `(3, 32, 32)` (with `channels_first` dim ordering). 323 | It should have exactly 3 inputs channels, 324 | and width and height should be no smaller than 8. 325 | E.g. `(200, 200, 3)` would be one valid value. 326 | classes: optional number of classes to classify images 327 | into, only to be specified if `include_top` is True, and 328 | if no `weights` argument is specified. 329 | activation: Type of activation at the top layer. Can be one of 'softmax' or 'sigmoid'. 330 | Note that if sigmoid is used, classes must be 1. 331 | upsampling_conv: number of convolutional layers in upsampling via subpixel convolution 332 | upsampling_type: Can be one of 'deconv', 'upsampling' and 333 | 'subpixel'. Defines type of upsampling algorithm used. 334 | batchsize: Fixed batch size. This is a temporary requirement for 335 | computation of output shape in the case of Deconvolution2D layers. 336 | Parameter will be removed in next iteration of Keras, which infers 337 | output shape of deconvolution layers automatically. 338 | early_transition: Start with an extra initial transition down and end with an extra 339 | transition up to reduce the network size. 340 | initial_kernel_size: The first Conv2D kernel might vary in size based on the 341 | application, this parameter makes it configurable. 342 | # Returns 343 | A Keras model instance. 344 | ''' 345 | 346 | if weights not in {None}: 347 | raise ValueError('The `weights` argument should be ' 348 | '`None` (random initialization) as no ' 349 | 'model weights are provided.') 350 | 351 | upsampling_type = upsampling_type.lower() 352 | 353 | if upsampling_type not in ['upsampling', 'deconv', 'subpixel']: 354 | raise ValueError('Parameter "upsampling_type" must be one of "upsampling", ' 355 | '"deconv" or "subpixel".') 356 | 357 | if input_shape is None: 358 | raise ValueError('For fully convolutional models, input shape must be supplied.') 359 | 360 | if type(nb_layers_per_block) is not list and nb_dense_block < 1: 361 | raise ValueError('Number of dense layers per block must be greater than 1. Argument ' 362 | 'value was %d.' % (nb_layers_per_block)) 363 | 364 | if activation not in ['softmax', 'sigmoid']: 365 | raise ValueError('activation must be one of "softmax" or "sigmoid"') 366 | 367 | if activation == 'sigmoid' and classes != 1: 368 | raise ValueError('sigmoid activation can only be used when classes = 1') 369 | 370 | # Determine proper input shape 371 | min_size = 2 ** nb_dense_block 372 | 373 | if K.image_data_format() == 'channels_first': 374 | if input_shape is not None: 375 | if ((input_shape[1] is not None and input_shape[1] < min_size) or 376 | (input_shape[2] is not None and input_shape[2] < min_size)): 377 | raise ValueError('Input size must be at least ' + 378 | str(min_size) + 'x' + str(min_size) + ', got ' 379 | '`input_shape=' + str(input_shape) + '`') 380 | else: 381 | input_shape = (classes, None, None) 382 | else: 383 | if input_shape is not None: 384 | if ((input_shape[0] is not None and input_shape[0] < min_size) or 385 | (input_shape[1] is not None and input_shape[1] < min_size)): 386 | raise ValueError('Input size must be at least ' + 387 | str(min_size) + 'x' + str(min_size) + ', got ' 388 | '`input_shape=' + str(input_shape) + '`') 389 | else: 390 | input_shape = (None, None, classes) 391 | 392 | if input_tensor is None: 393 | img_input = Input(shape=input_shape) 394 | else: 395 | if not K.is_keras_tensor(input_tensor): 396 | img_input = Input(tensor=input_tensor, shape=input_shape) 397 | else: 398 | img_input = input_tensor 399 | 400 | x = __create_fcn_dense_net(classes, img_input, include_top, nb_dense_block, growth_rate, 401 | reduction, dropout_rate, weight_decay, 402 | nb_layers_per_block, upsampling_conv, upsampling_type, 403 | init_conv_filters, input_shape, activation, 404 | early_transition, transition_pooling, initial_kernel_size) 405 | 406 | # Ensure that the model takes into account 407 | # any potential predecessors of `input_tensor`. 408 | if input_tensor is not None: 409 | inputs = get_source_inputs(input_tensor) 410 | else: 411 | inputs = img_input 412 | # Create model. 413 | model = Model(inputs, x, name='fcn-densenet') 414 | 415 | return model 416 | 417 | 418 | def DenseNetImageNet121(input_shape=None, 419 | bottleneck=True, 420 | reduction=0.5, 421 | dropout_rate=0.0, 422 | weight_decay=1e-4, 423 | include_top=True, 424 | weights='imagenet', 425 | input_tensor=None, 426 | pooling=None, 427 | classes=1000, 428 | activation='softmax'): 429 | return DenseNet(input_shape, depth=121, nb_dense_block=4, growth_rate=32, nb_filter=64, 430 | nb_layers_per_block=[6, 12, 24, 16], bottleneck=bottleneck, reduction=reduction, 431 | dropout_rate=dropout_rate, weight_decay=weight_decay, subsample_initial_block=True, 432 | include_top=include_top, weights=weights, input_tensor=input_tensor, 433 | pooling=pooling, classes=classes, activation=activation) 434 | 435 | 436 | def DenseNetImageNet169(input_shape=None, 437 | bottleneck=True, 438 | reduction=0.5, 439 | dropout_rate=0.0, 440 | weight_decay=1e-4, 441 | include_top=True, 442 | weights='imagenet', 443 | input_tensor=None, 444 | pooling=None, 445 | classes=1000, 446 | activation='softmax'): 447 | return DenseNet(input_shape, depth=169, nb_dense_block=4, growth_rate=32, nb_filter=64, 448 | nb_layers_per_block=[6, 12, 32, 32], bottleneck=bottleneck, reduction=reduction, 449 | dropout_rate=dropout_rate, weight_decay=weight_decay, subsample_initial_block=True, 450 | include_top=include_top, weights=weights, input_tensor=input_tensor, 451 | pooling=pooling, classes=classes, activation=activation) 452 | 453 | 454 | def DenseNetImageNet201(input_shape=None, 455 | bottleneck=True, 456 | reduction=0.5, 457 | dropout_rate=0.0, 458 | weight_decay=1e-4, 459 | include_top=True, 460 | weights=None, 461 | input_tensor=None, 462 | pooling=None, 463 | classes=1000, 464 | activation='softmax'): 465 | return DenseNet(input_shape, depth=201, nb_dense_block=4, growth_rate=32, nb_filter=64, 466 | nb_layers_per_block=[6, 12, 48, 32], bottleneck=bottleneck, reduction=reduction, 467 | dropout_rate=dropout_rate, weight_decay=weight_decay, subsample_initial_block=True, 468 | include_top=include_top, weights=weights, input_tensor=input_tensor, 469 | pooling=pooling, classes=classes, activation=activation) 470 | 471 | 472 | def DenseNetImageNet264(input_shape=None, 473 | bottleneck=True, 474 | reduction=0.5, 475 | dropout_rate=0.0, 476 | weight_decay=1e-4, 477 | include_top=True, 478 | weights=None, 479 | input_tensor=None, 480 | pooling=None, 481 | classes=1000, 482 | activation='softmax'): 483 | return DenseNet(input_shape, depth=264, nb_dense_block=4, growth_rate=32, nb_filter=64, 484 | nb_layers_per_block=[6, 12, 64, 48], bottleneck=bottleneck, reduction=reduction, 485 | dropout_rate=dropout_rate, weight_decay=weight_decay, subsample_initial_block=True, 486 | include_top=include_top, weights=weights, input_tensor=input_tensor, 487 | pooling=pooling, classes=classes, activation=activation) 488 | 489 | 490 | def DenseNetImageNet161(input_shape=None, 491 | bottleneck=True, 492 | reduction=0.5, 493 | dropout_rate=0.0, 494 | weight_decay=1e-4, 495 | include_top=True, 496 | weights='imagenet', 497 | input_tensor=None, 498 | pooling=None, 499 | classes=1000, 500 | activation='softmax'): 501 | return DenseNet(input_shape, depth=161, nb_dense_block=4, growth_rate=48, nb_filter=96, 502 | nb_layers_per_block=[6, 12, 36, 24], bottleneck=bottleneck, reduction=reduction, 503 | dropout_rate=dropout_rate, weight_decay=weight_decay, subsample_initial_block=True, 504 | include_top=include_top, weights=weights, input_tensor=input_tensor, 505 | pooling=pooling, classes=classes, activation=activation) 506 | 507 | 508 | def name_or_none(prefix, name): 509 | return prefix + name if (prefix is not None and name is not None) else None 510 | 511 | 512 | def __conv_block(ip, nb_filter, bottleneck=False, dropout_rate=None, weight_decay=1e-4, block_prefix=None): 513 | ''' 514 | Adds a convolution layer (with batch normalization and relu), 515 | and optionally a bottleneck layer. 516 | # Arguments 517 | ip: Input tensor 518 | nb_filter: integer, the dimensionality of the output space 519 | (i.e. the number output of filters in the convolution) 520 | bottleneck: if True, adds a bottleneck convolution block 521 | dropout_rate: dropout rate 522 | weight_decay: weight decay factor 523 | block_prefix: str, for unique layer naming 524 | # Input shape 525 | 4D tensor with shape: 526 | `(samples, channels, rows, cols)` if data_format='channels_first' 527 | or 4D tensor with shape: 528 | `(samples, rows, cols, channels)` if data_format='channels_last'. 529 | # Output shape 530 | 4D tensor with shape: 531 | `(samples, filters, new_rows, new_cols)` if data_format='channels_first' 532 | or 4D tensor with shape: 533 | `(samples, new_rows, new_cols, filters)` if data_format='channels_last'. 534 | `rows` and `cols` values might have changed due to stride. 535 | # Returns 536 | output tensor of block 537 | ''' 538 | with K.name_scope('ConvBlock'): 539 | concat_axis = 1 if K.image_data_format() == 'channels_first' else -1 540 | 541 | x = BatchNormalization(axis=concat_axis, epsilon=1.1e-5, name=name_or_none(block_prefix, '_bn'))(ip) 542 | x = Activation('relu')(x) 543 | 544 | if bottleneck: 545 | inter_channel = nb_filter * 4 546 | 547 | x = Conv2D(inter_channel, (1, 1), kernel_initializer='he_normal', padding='same', use_bias=False, 548 | kernel_regularizer=l2(weight_decay), name=name_or_none(block_prefix, '_bottleneck_conv2D'))(x) 549 | x = BatchNormalization(axis=concat_axis, epsilon=1.1e-5, 550 | name=name_or_none(block_prefix, '_bottleneck_bn'))(x) 551 | x = Activation('relu')(x) 552 | 553 | x = Conv2D(nb_filter, (3, 3), kernel_initializer='he_normal', padding='same', use_bias=False, 554 | name=name_or_none(block_prefix, '_conv2D'))(x) 555 | if dropout_rate: 556 | x = Dropout(dropout_rate)(x) 557 | 558 | return x 559 | 560 | 561 | def __dense_block(x, nb_layers, nb_filter, growth_rate, bottleneck=False, dropout_rate=None, 562 | weight_decay=1e-4, grow_nb_filters=True, return_concat_list=False, block_prefix=None): 563 | ''' 564 | Build a dense_block where the output of each conv_block is fed 565 | to subsequent ones 566 | # Arguments 567 | x: input keras tensor 568 | nb_layers: the number of conv_blocks to append to the model 569 | nb_filter: integer, the dimensionality of the output space 570 | (i.e. the number output of filters in the convolution) 571 | growth_rate: growth rate of the dense block 572 | bottleneck: if True, adds a bottleneck convolution block to 573 | each conv_block 574 | dropout_rate: dropout rate 575 | weight_decay: weight decay factor 576 | grow_nb_filters: if True, allows number of filters to grow 577 | return_concat_list: set to True to return the list of 578 | feature maps along with the actual output 579 | block_prefix: str, for block unique naming 580 | # Return 581 | If return_concat_list is True, returns a list of the output 582 | keras tensor, the number of filters and a list of all the 583 | dense blocks added to the keras tensor 584 | If return_concat_list is False, returns a list of the output 585 | keras tensor and the number of filters 586 | ''' 587 | with K.name_scope('DenseBlock'): 588 | concat_axis = 1 if K.image_data_format() == 'channels_first' else -1 589 | 590 | x_list = [x] 591 | 592 | for i in range(nb_layers): 593 | cb = __conv_block(x, growth_rate, bottleneck, dropout_rate, weight_decay, 594 | block_prefix=name_or_none(block_prefix, '_%i' % i)) 595 | x_list.append(cb) 596 | 597 | x = concatenate([x, cb], axis=concat_axis) 598 | 599 | if grow_nb_filters: 600 | nb_filter += growth_rate 601 | 602 | if return_concat_list: 603 | return x, nb_filter, x_list 604 | else: 605 | return x, nb_filter 606 | 607 | 608 | def __transition_block(ip, nb_filter, compression=1.0, weight_decay=1e-4, block_prefix=None, transition_pooling='max'): 609 | ''' 610 | Adds a pointwise convolution layer (with batch normalization and relu), 611 | and an average pooling layer. The number of output convolution filters 612 | can be reduced by appropriately reducing the compression parameter. 613 | # Arguments 614 | ip: input keras tensor 615 | nb_filter: integer, the dimensionality of the output space 616 | (i.e. the number output of filters in the convolution) 617 | compression: calculated as 1 - reduction. Reduces the number 618 | of feature maps in the transition block. 619 | weight_decay: weight decay factor 620 | block_prefix: str, for block unique naming 621 | # Input shape 622 | 4D tensor with shape: 623 | `(samples, channels, rows, cols)` if data_format='channels_first' 624 | or 4D tensor with shape: 625 | `(samples, rows, cols, channels)` if data_format='channels_last'. 626 | # Output shape 627 | 4D tensor with shape: 628 | `(samples, nb_filter * compression, rows / 2, cols / 2)` 629 | if data_format='channels_first' 630 | or 4D tensor with shape: 631 | `(samples, rows / 2, cols / 2, nb_filter * compression)` 632 | if data_format='channels_last'. 633 | # Returns 634 | a keras tensor 635 | ''' 636 | with K.name_scope('Transition'): 637 | concat_axis = 1 if K.image_data_format() == 'channels_first' else -1 638 | 639 | x = BatchNormalization(axis=concat_axis, epsilon=1.1e-5, name=name_or_none(block_prefix, '_bn'))(ip) 640 | x = Activation('relu')(x) 641 | x = Conv2D(int(nb_filter * compression), (1, 1), kernel_initializer='he_normal', padding='same', 642 | use_bias=False, kernel_regularizer=l2(weight_decay), name=name_or_none(block_prefix, '_conv2D'))(x) 643 | if transition_pooling == 'avg': 644 | x = AveragePooling2D((2, 2), strides=(2, 2))(x) 645 | elif transition_pooling == 'max': 646 | x = MaxPooling2D((2, 2), strides=(2, 2))(x) 647 | 648 | return x 649 | 650 | 651 | def __transition_up_block(ip, nb_filters, type='deconv', weight_decay=1E-4, block_prefix=None): 652 | '''Adds an upsampling block. Upsampling operation relies on the the type parameter. 653 | # Arguments 654 | ip: input keras tensor 655 | nb_filters: integer, the dimensionality of the output space 656 | (i.e. the number output of filters in the convolution) 657 | type: can be 'upsampling', 'subpixel', 'deconv'. Determines 658 | type of upsampling performed 659 | weight_decay: weight decay factor 660 | block_prefix: str, for block unique naming 661 | # Input shape 662 | 4D tensor with shape: 663 | `(samples, channels, rows, cols)` if data_format='channels_first' 664 | or 4D tensor with shape: 665 | `(samples, rows, cols, channels)` if data_format='channels_last'. 666 | # Output shape 667 | 4D tensor with shape: 668 | `(samples, nb_filter, rows * 2, cols * 2)` if data_format='channels_first' 669 | or 4D tensor with shape: 670 | `(samples, rows * 2, cols * 2, nb_filter)` if data_format='channels_last'. 671 | # Returns 672 | a keras tensor 673 | ''' 674 | with K.name_scope('TransitionUp'): 675 | 676 | if type == 'upsampling': 677 | x = UpSampling2D(name=name_or_none(block_prefix, '_upsampling'))(ip) 678 | elif type == 'subpixel': 679 | x = Conv2D(nb_filters, (3, 3), activation='relu', padding='same', kernel_regularizer=l2(weight_decay), 680 | use_bias=False, kernel_initializer='he_normal', name=name_or_none(block_prefix, '_conv2D'))(ip) 681 | x = SubPixelUpscaling(scale_factor=2, name=name_or_none(block_prefix, '_subpixel'))(x) 682 | x = Conv2D(nb_filters, (3, 3), activation='relu', padding='same', kernel_regularizer=l2(weight_decay), 683 | use_bias=False, kernel_initializer='he_normal', name=name_or_none(block_prefix, '_conv2D'))(x) 684 | else: 685 | x = Conv2DTranspose(nb_filters, (3, 3), activation='relu', padding='same', strides=(2, 2), 686 | kernel_initializer='he_normal', kernel_regularizer=l2(weight_decay), 687 | name=name_or_none(block_prefix, '_conv2DT'))(ip) 688 | return x 689 | 690 | 691 | def __create_dense_net(nb_classes, img_input, include_top, depth=40, nb_dense_block=3, growth_rate=12, nb_filter=-1, 692 | nb_layers_per_block=-1, bottleneck=False, reduction=0.0, dropout_rate=None, weight_decay=1e-4, 693 | subsample_initial_block=False, pooling=None, activation='softmax', transition_pooling='avg'): 694 | ''' Build the DenseNet model 695 | # Arguments 696 | nb_classes: number of classes 697 | img_input: tuple of shape (channels, rows, columns) or (rows, columns, channels) 698 | include_top: flag to include the final Dense layer 699 | depth: number or layers 700 | nb_dense_block: number of dense blocks to add to end (generally = 3) 701 | growth_rate: number of filters to add per dense block 702 | nb_filter: initial number of filters. Default -1 indicates initial number of filters is 2 * growth_rate 703 | nb_layers_per_block: number of layers in each dense block. 704 | Can be a -1, positive integer or a list. 705 | If -1, calculates nb_layer_per_block from the depth of the network. 706 | If positive integer, a set number of layers per dense block. 707 | If list, nb_layer is used as provided. Note that list size must 708 | be (nb_dense_block + 1) 709 | bottleneck: add bottleneck blocks 710 | reduction: reduction factor of transition blocks. Note : reduction value is inverted to compute compression 711 | dropout_rate: dropout rate 712 | weight_decay: weight decay rate 713 | subsample_initial_block: Changes model type to suit different datasets. 714 | Should be set to True for ImageNet, and False for CIFAR datasets. 715 | When set to True, the initial convolution will be strided and 716 | adds a MaxPooling2D before the initial dense block. 717 | pooling: Optional pooling mode for feature extraction 718 | when `include_top` is `False`. 719 | - `None` means that the output of the model 720 | will be the 4D tensor output of the 721 | last convolutional layer. 722 | - `avg` means that global average pooling 723 | will be applied to the output of the 724 | last convolutional layer, and thus 725 | the output of the model will be a 726 | 2D tensor. 727 | - `max` means that global max pooling will 728 | be applied. 729 | activation: Type of activation at the top layer. Can be one of 'softmax' or 'sigmoid'. 730 | Note that if sigmoid is used, classes must be 1. 731 | transition_pooling: `avg` for avg pooling (default), `max` for max pooling, 732 | None for no pooling during scale transition blocks. Please note that this 733 | default differs from the DenseNetFCN paper in accordance with the DenseNet 734 | paper. 735 | # Returns 736 | a keras tensor 737 | # Raises 738 | ValueError: in case of invalid argument for `reduction` 739 | or `nb_dense_block` 740 | ''' 741 | with K.name_scope('DenseNet'): 742 | concat_axis = 1 if K.image_data_format() == 'channels_first' else -1 743 | 744 | if reduction != 0.0: 745 | if not (reduction <= 1.0 and reduction > 0.0): 746 | raise ValueError('`reduction` value must lie between 0.0 and 1.0') 747 | 748 | # layers in each dense block 749 | if type(nb_layers_per_block) is list or type(nb_layers_per_block) is tuple: 750 | nb_layers = list(nb_layers_per_block) # Convert tuple to list 751 | 752 | if len(nb_layers) != (nb_dense_block): 753 | raise ValueError('If `nb_dense_block` is a list, its length must match ' 754 | 'the number of layers provided by `nb_layers`.') 755 | 756 | final_nb_layer = nb_layers[-1] 757 | nb_layers = nb_layers[:-1] 758 | else: 759 | if nb_layers_per_block == -1: 760 | assert (depth - 4) % 3 == 0, 'Depth must be 3 N + 4 if nb_layers_per_block == -1' 761 | count = int((depth - 4) / 3) 762 | 763 | if bottleneck: 764 | count = count // 2 765 | 766 | nb_layers = [count for _ in range(nb_dense_block)] 767 | final_nb_layer = count 768 | else: 769 | final_nb_layer = nb_layers_per_block 770 | nb_layers = [nb_layers_per_block] * nb_dense_block 771 | 772 | # compute initial nb_filter if -1, else accept users initial nb_filter 773 | if nb_filter <= 0: 774 | nb_filter = 2 * growth_rate 775 | 776 | # compute compression factor 777 | compression = 1.0 - reduction 778 | 779 | # Initial convolution 780 | if subsample_initial_block: 781 | initial_kernel = (7, 7) 782 | initial_strides = (2, 2) 783 | else: 784 | initial_kernel = (3, 3) 785 | initial_strides = (1, 1) 786 | 787 | x = Conv2D(nb_filter, initial_kernel, kernel_initializer='he_normal', padding='same', name='initial_conv2D', 788 | strides=initial_strides, use_bias=False, kernel_regularizer=l2(weight_decay))(img_input) 789 | 790 | if subsample_initial_block: 791 | x = BatchNormalization(axis=concat_axis, epsilon=1.1e-5, name='initial_bn')(x) 792 | x = Activation('relu')(x) 793 | x = MaxPooling2D((3, 3), strides=(2, 2), padding='same')(x) 794 | 795 | # Add dense blocks 796 | for block_idx in range(nb_dense_block - 1): 797 | x, nb_filter = __dense_block(x, nb_layers[block_idx], nb_filter, growth_rate, bottleneck=bottleneck, 798 | dropout_rate=dropout_rate, weight_decay=weight_decay, 799 | block_prefix='dense_%i' % block_idx) 800 | # add transition_block 801 | x = __transition_block(x, nb_filter, compression=compression, weight_decay=weight_decay, 802 | block_prefix='tr_%i' % block_idx, transition_pooling=transition_pooling) 803 | nb_filter = int(nb_filter * compression) 804 | 805 | # The last dense_block does not have a transition_block 806 | x, nb_filter = __dense_block(x, final_nb_layer, nb_filter, growth_rate, bottleneck=bottleneck, 807 | dropout_rate=dropout_rate, weight_decay=weight_decay, 808 | block_prefix='dense_%i' % (nb_dense_block - 1)) 809 | 810 | x = BatchNormalization(axis=concat_axis, epsilon=1.1e-5, name='final_bn')(x) 811 | x = Activation('relu')(x) 812 | 813 | if include_top: 814 | if pooling == 'avg': 815 | x = GlobalAveragePooling2D()(x) 816 | elif pooling == 'max': 817 | x = GlobalMaxPooling2D()(x) 818 | x = Dense(nb_classes, activation=activation)(x) 819 | else: 820 | if pooling == 'avg': 821 | x = GlobalAveragePooling2D()(x) 822 | elif pooling == 'max': 823 | x = GlobalMaxPooling2D()(x) 824 | 825 | return x 826 | 827 | 828 | def __create_fcn_dense_net(nb_classes, img_input, include_top, nb_dense_block=5, growth_rate=12, 829 | reduction=0.0, dropout_rate=None, weight_decay=1e-4, 830 | nb_layers_per_block=4, nb_upsampling_conv=128, upsampling_type='deconv', 831 | init_conv_filters=48, input_shape=None, activation='softmax', 832 | early_transition=False, transition_pooling='max', initial_kernel_size=(3, 3)): 833 | ''' Build the DenseNet-FCN model 834 | # Arguments 835 | nb_classes: number of classes 836 | img_input: tuple of shape (channels, rows, columns) or (rows, columns, channels) 837 | include_top: flag to include the final Dense layer 838 | nb_dense_block: number of dense blocks to add to end (generally = 3) 839 | growth_rate: number of filters to add per dense block 840 | reduction: reduction factor of transition blocks. Note : reduction value is inverted to compute compression 841 | dropout_rate: dropout rate 842 | weight_decay: weight decay 843 | nb_layers_per_block: number of layers in each dense block. 844 | Can be a positive integer or a list. 845 | If positive integer, a set number of layers per dense block. 846 | If list, nb_layer is used as provided. Note that list size must 847 | be (nb_dense_block + 1) 848 | nb_upsampling_conv: number of convolutional layers in upsampling via subpixel convolution 849 | upsampling_type: Can be one of 'upsampling', 'deconv' and 'subpixel'. Defines 850 | type of upsampling algorithm used. 851 | input_shape: Only used for shape inference in fully convolutional networks. 852 | activation: Type of activation at the top layer. Can be one of 'softmax' or 'sigmoid'. 853 | Note that if sigmoid is used, classes must be 1. 854 | early_transition: Start with an extra initial transition down and end with an extra 855 | transition up to reduce the network size. 856 | transition_pooling: 'max' for max pooling (default), 'avg' for average pooling, 857 | None for no pooling. Please note that this default differs from the DenseNet 858 | paper in accordance with the DenseNetFCN paper. 859 | initial_kernel_size: The first Conv2D kernel might vary in size based on the 860 | application, this parameter makes it configurable. 861 | # Returns 862 | a keras tensor 863 | # Raises 864 | ValueError: in case of invalid argument for `reduction`, 865 | `nb_dense_block` or `nb_upsampling_conv`. 866 | ''' 867 | with K.name_scope('DenseNetFCN'): 868 | concat_axis = 1 if K.image_data_format() == 'channels_first' else -1 869 | 870 | if concat_axis == 1: # channels_first dim ordering 871 | _, rows, cols = input_shape 872 | else: 873 | rows, cols, _ = input_shape 874 | 875 | if reduction != 0.0: 876 | if not (reduction <= 1.0 and reduction > 0.0): 877 | raise ValueError('`reduction` value must lie between 0.0 and 1.0') 878 | 879 | # check if upsampling_conv has minimum number of filters 880 | # minimum is set to 12, as at least 3 color channels are needed for correct upsampling 881 | if not (nb_upsampling_conv > 12 and nb_upsampling_conv % 4 == 0): 882 | raise ValueError('Parameter `nb_upsampling_conv` number of channels must ' 883 | 'be a positive number divisible by 4 and greater than 12') 884 | 885 | # layers in each dense block 886 | if type(nb_layers_per_block) is list or type(nb_layers_per_block) is tuple: 887 | nb_layers = list(nb_layers_per_block) # Convert tuple to list 888 | 889 | if len(nb_layers) != (nb_dense_block + 1): 890 | raise ValueError('If `nb_dense_block` is a list, its length must be ' 891 | '(`nb_dense_block` + 1)') 892 | 893 | bottleneck_nb_layers = nb_layers[-1] 894 | rev_layers = nb_layers[::-1] 895 | nb_layers.extend(rev_layers[1:]) 896 | else: 897 | bottleneck_nb_layers = nb_layers_per_block 898 | nb_layers = [nb_layers_per_block] * (2 * nb_dense_block + 1) 899 | 900 | # compute compression factor 901 | compression = 1.0 - reduction 902 | 903 | # Initial convolution 904 | x = Conv2D(init_conv_filters, initial_kernel_size, kernel_initializer='he_normal', padding='same', name='initial_conv2D', 905 | use_bias=False, kernel_regularizer=l2(weight_decay))(img_input) 906 | x = BatchNormalization(axis=concat_axis, epsilon=1.1e-5, name='initial_bn')(x) 907 | x = Activation('relu')(x) 908 | 909 | nb_filter = init_conv_filters 910 | 911 | skip_list = [] 912 | 913 | if early_transition: 914 | x = __transition_block(x, nb_filter, compression=compression, weight_decay=weight_decay, 915 | block_prefix='tr_early', transition_pooling=transition_pooling) 916 | 917 | # Add dense blocks and transition down block 918 | for block_idx in range(nb_dense_block): 919 | x, nb_filter = __dense_block(x, nb_layers[block_idx], nb_filter, growth_rate, dropout_rate=dropout_rate, 920 | weight_decay=weight_decay, block_prefix='dense_%i' % block_idx) 921 | 922 | # Skip connection 923 | skip_list.append(x) 924 | 925 | # add transition_block 926 | x = __transition_block(x, nb_filter, compression=compression, weight_decay=weight_decay, 927 | block_prefix='tr_%i' % block_idx, transition_pooling=transition_pooling) 928 | 929 | nb_filter = int(nb_filter * compression) # this is calculated inside transition_down_block 930 | 931 | # The last dense_block does not have a transition_down_block 932 | # return the concatenated feature maps without the concatenation of the input 933 | _, nb_filter, concat_list = __dense_block(x, bottleneck_nb_layers, nb_filter, growth_rate, 934 | dropout_rate=dropout_rate, weight_decay=weight_decay, 935 | return_concat_list=True, 936 | block_prefix='dense_%i' % nb_dense_block) 937 | 938 | skip_list = skip_list[::-1] # reverse the skip list 939 | 940 | # Add dense blocks and transition up block 941 | for block_idx in range(nb_dense_block): 942 | n_filters_keep = growth_rate * nb_layers[nb_dense_block + block_idx] 943 | 944 | # upsampling block must upsample only the feature maps (concat_list[1:]), 945 | # not the concatenation of the input with the feature maps (concat_list[0]. 946 | l = concatenate(concat_list[1:], axis=concat_axis) 947 | 948 | t = __transition_up_block(l, nb_filters=n_filters_keep, type=upsampling_type, weight_decay=weight_decay, 949 | block_prefix='tr_up_%i' % block_idx) 950 | 951 | # concatenate the skip connection with the transition block 952 | x = concatenate([t, skip_list[block_idx]], axis=concat_axis) 953 | 954 | # Dont allow the feature map size to grow in upsampling dense blocks 955 | x_up, nb_filter, concat_list = __dense_block(x, nb_layers[nb_dense_block + block_idx + 1], 956 | nb_filter=growth_rate, growth_rate=growth_rate, 957 | dropout_rate=dropout_rate, weight_decay=weight_decay, 958 | return_concat_list=True, grow_nb_filters=False, 959 | block_prefix='dense_%i' % (nb_dense_block + 1 + block_idx)) 960 | 961 | if early_transition: 962 | x_up = __transition_up_block(x_up, nb_filters=nb_filter, type=upsampling_type, weight_decay=weight_decay, 963 | block_prefix='tr_up_early') 964 | if include_top: 965 | x = Conv2D(nb_classes, (1, 1), activation='linear', padding='same', use_bias=False)(x_up) 966 | 967 | if K.image_data_format() == 'channels_first': 968 | channel, row, col = input_shape 969 | else: 970 | row, col, channel = input_shape 971 | 972 | x = Reshape((row * col, nb_classes))(x) 973 | x = Activation(activation)(x) 974 | x = Reshape((row, col, nb_classes))(x) 975 | else: 976 | x = x_up 977 | 978 | return x 979 | --------------------------------------------------------------------------------