├── Models ├── mod └── Models.py ├── Data_Pre-processing ├── y.npy ├── convert.py ├── parsing.py └── read_data1.py ├── README.md ├── Training_Strategies └── training_1.py └── Visitation of Activation Map ├── grad_cam.py ├── cam2.py └── GRAD_CAM_VGG.py /Models/mod: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Data_Pre-processing/y.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kabbas570/Dog-Noseprint-Recognition-and-Localization-/HEAD/Data_Pre-processing/y.npy -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Dog-Noseprint-Recognition-and-Localization- 2 | Dogs' nose have unique patterns as a human's fingerprints.It can be used to accurately identify the dogs species. 3 | The Canadian Kennel Club has been accepting dog nose prints as proof of identity since 1938. 4 | This project exploredthe idea of "Dog Noseprint Recognition and Localization", using a hybrid CNN network for both clasification and localization. 5 | ## The network has three parts: 6 | 1- CNN extracts the features from Input Image 7 | 2- Regression part estimates the position of dog’s nose 8 | 3- Classification part predicts the dog class 9 | ### Proposed Architecture 10 | ![image](https://user-images.githubusercontent.com/56618776/111267986-0ac3df00-8670-11eb-9803-e02405eb3c69.png) 11 | 12 | ![image](https://user-images.githubusercontent.com/56618776/111268159-478fd600-8670-11eb-9b11-0509a098575f.png) 13 | 14 | ### Visualization of Maximum Activations of Convolution Layers 15 | ![image](https://user-images.githubusercontent.com/56618776/111269214-a43fc080-8671-11eb-872e-7890ee68513e.png) 16 | 17 | -------------------------------------------------------------------------------- /Data_Pre-processing/convert.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import os 3 | csv_path=('/home/user01/data_ssd/Abbas/dog4/dog-export.csv') 4 | vott_df = pd.read_csv(csv_path) 5 | #print(vott_df) 6 | labels = vott_df["label"].unique() 7 | #print(labels) 8 | labeldict = dict(zip(labels, range(len(labels)))) 9 | vott_df.drop_duplicates(subset=None, keep="first", inplace=True) 10 | #print(labeldict) 11 | path='/home/user01/data_ssd/Abbas/dog4/' 12 | def convert_vott_csv_to_yolo( 13 | vott_df, 14 | labeldict, 15 | path="", 16 | target_name="data_train.txt", 17 | abs_path=False, 18 | ): 19 | # Encode labels according to labeldict if code's don't exist 20 | if not "code" in vott_df.columns: 21 | vott_df["code"] = vott_df["label"].apply(lambda x: labeldict[x]) 22 | # Round float to ints 23 | for col in vott_df[["xmin", "ymin", "xmax", "ymax"]]: 24 | vott_df[col] = (vott_df[col]).apply(lambda x: round(x)) 25 | # Create Yolo Text file 26 | last_image = "" 27 | txt_file = "" 28 | for index, row in vott_df.iterrows(): 29 | if not last_image == row["image"]: 30 | if abs_path: 31 | txt_file += "\n" + row["image_path"] + " " 32 | else: 33 | txt_file += "\n" + os.path.join(path, row["image"]) + " " 34 | txt_file += ",".join( 35 | [ 36 | str(x) 37 | for x in (row[["xmin", "ymin", "xmax", "ymax", "code"]].tolist()) 38 | ] 39 | ) 40 | else: 41 | txt_file += " " 42 | txt_file += ",".join( 43 | [ 44 | str(x) 45 | for x in (row[["xmin", "ymin", "xmax", "ymax", "code"]].tolist()) 46 | ] 47 | ) 48 | last_image = row["image"] 49 | file = open(target_name, "w") 50 | file.write(txt_file[1:]) 51 | file.close() 52 | return True 53 | _=convert_vott_csv_to_yolo(vott_df,labeldict,path) 54 | -------------------------------------------------------------------------------- /Data_Pre-processing/parsing.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | import numpy as np 4 | import csv 5 | import optparse 6 | from copy import deepcopy 7 | import sys 8 | 9 | 10 | def parsing(json_path): 11 | with open(json_path) as json_file: 12 | parsed_data = json.load(json_file, encoding='UTF-8') 13 | 14 | polygon_shapes = parsed_data['shapes'] 15 | 16 | # EACH SHAPE 17 | for polygon_data in polygon_shapes: 18 | label = polygon_data['label'] 19 | points = np.array(polygon_data['points']) 20 | path = deepcopy(json_path).replace('.json', '.jpg') 21 | return path, points, label 22 | 23 | 24 | def search(path): 25 | print(f'searching path : {path}') 26 | # check is directory. 27 | for target in os.listdir(path): 28 | 29 | target_path = os.path.join(path, target) 30 | 31 | # if path. 32 | if os.path.isdir(target_path): 33 | print(f'? next target : {target_path}') 34 | # search. 35 | search(deepcopy(target_path)) 36 | 37 | # not directory and jsonfile. 38 | elif target_path.endswith('.json'): 39 | print(f'? ?processing : {target}') 40 | # parsing. 41 | img_path, points, target_label = parsing(deepcopy(target_path)) 42 | wr.writerow([img_path, points[0, 0], points[0, 1], points[1, 0], points[1, 1], target_label]) 43 | print(f'? ?path : {img_path}, label {target_label}') 44 | else: 45 | pass 46 | 47 | 48 | if __name__ == '__main__': 49 | parser = optparse.OptionParser("LabelMeParser", version='1.0.0') 50 | parser.add_option('-p', '--target_path', action='store', dest='target_path', help='Set parent directory of target path.') 51 | parser.add_option('-o', '--output_path', action='store', dest='output_path', help='Set output path.') 52 | (options, args) = parser.parse_args(sys.argv) 53 | 54 | assert options.target_path is not None, 'Please set target path. See -h, --help options.' 55 | assert options.output_path is not None, 'Please set output path. See -h, --help options.' 56 | 57 | parent_path = options.target_path 58 | f = open(options.output_path, 'w', newline='', encoding='utf-8') 59 | wr = csv.writer(f) 60 | search(parent_path) 61 | f.close() 62 | print(f'? Finish.') 63 | -------------------------------------------------------------------------------- /Data_Pre-processing/read_data1.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import cv2 3 | import matplotlib.pyplot as plt 4 | 5 | 6 | num_calss=5 7 | 8 | def data_readV(): 9 | image_w=400 10 | image_h=400 11 | img_ = [] 12 | cor_=[] 13 | clas_=[] 14 | with open('data_train.txt') as f: 15 | content = f.readlines() 16 | # you may also want to remove whitespace characters like `\n` at the end of each line 17 | content = [x.strip() for x in content] 18 | for i in range(len(content)): 19 | coor = np.zeros([4]) # 7 x 7 x num_classes + 5 20 | clas_t=np.zeros([num_calss]) 21 | img_path=content[i].partition(" ")[0] 22 | img=cv2.imread(img_path) 23 | #img=cv2.cvtColor(img, cv2.COLOR_BGR2RGB) 24 | img = cv2.resize (img, (image_w,image_h), interpolation = cv2.INTER_AREA) 25 | img=img/255 26 | img_.append(img) 27 | q=0 28 | for j in content[i]: 29 | if j==" ": 30 | q=q+1 31 | for c in range(q): 32 | label=content[i].split(" ")[c+1] 33 | for l in label : 34 | l = label. split ( ',' ) 35 | l = np.array(l, dtype=np.int) 36 | xmin = l[0]*(image_w/3888) 37 | ymin = l[1]*(image_h/2592) 38 | xmax = l[2]*(image_h/3888) 39 | ymax = l[3]*(image_w/2592) 40 | clas = l[4] 41 | coor[0]=xmin/400 42 | coor[1]=ymin/400 43 | coor[2]=xmax/400 44 | coor[3]=ymax/400 45 | clas_t[clas]=1 46 | cor_.append(coor) 47 | clas_.append(clas_t) 48 | img_ = np.array(img_) 49 | cor_ = np.array(cor_) 50 | clas_ = np.array(clas_) 51 | return img_,cor_,clas_ 52 | 53 | 54 | # ============================================================================= 55 | # index=106 56 | # image=img_[index,:,:,:] 57 | # xmin=cor_[index][0] 58 | # ymin=cor_[index][1] 59 | # xmax=cor_[index][2] 60 | # ymax=cor_[index][3] 61 | # class_name=np.argmax(clas_[index]) 62 | # cv2.rectangle(image, (int(xmin), int(ymin)), 63 | # (int(xmax), int(ymax)), 64 | # (255, 0, 0),thickness = 2) 65 | # 66 | # font = cv2.FONT_HERSHEY_SIMPLEX 67 | # org = (int(xmin), int(ymin)) 68 | # fontScale = 1 69 | # color = (0, 0, 255) 70 | # thickness = 2 71 | # image = cv2.putText(image, str(class_name), org, font, 72 | # fontScale, color, thickness, cv2.LINE_AA) 73 | # 74 | # 75 | # plt.figure() 76 | # plt.imshow(image) 77 | # ============================================================================= 78 | 79 | 80 | 81 | 82 | def data_readVt(): 83 | image_w=400 84 | image_h=400 85 | img_ = [] 86 | cor_=[] 87 | clas_=[] 88 | with open('data_train.txt') as f: 89 | content = f.readlines() 90 | # you may also want to remove whitespace characters like `\n` at the end of each line 91 | content = [x.strip() for x in content] 92 | for i in range(len(content)): 93 | coor = np.zeros([4]) # 7 x 7 x num_classes + 5 94 | clas_t=np.zeros([num_calss]) 95 | img_path=content[i].partition(" ")[0] 96 | img=cv2.imread(img_path) 97 | img = cv2.resize (img, (image_w,image_h), interpolation = cv2.INTER_AREA) 98 | img=img/255 99 | img_.append(img) 100 | q=0 101 | for j in content[i]: 102 | if j==" ": 103 | q=q+1 104 | for c in range(q): 105 | label=content[i].split(" ")[c+1] 106 | for l in label : 107 | l = label. split ( ',' ) 108 | l = np.array(l, dtype=np.int) 109 | xmin = l[0]*(image_w/3888) 110 | ymin = l[1]*(image_h/2592) 111 | xmax = l[2]*(image_h/3888) 112 | ymax = l[3]*(image_w/2592) 113 | clas = l[4] 114 | coor[0]=xmin 115 | coor[1]=ymin 116 | coor[2]=xmax 117 | coor[3]=ymax 118 | clas_t[clas]=1 119 | cor_.append(coor) 120 | clas_.append(clas_t) 121 | img_ = np.array(img_) 122 | cor_ = np.array(cor_) 123 | clas_ = np.array(clas_) 124 | return img_,cor_,clas_ 125 | 126 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /Training_Strategies/training_1.py: -------------------------------------------------------------------------------- 1 | import os 2 | os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"; 3 | # The GPU id to use, usually either "0" or "1"; 4 | os.environ["CUDA_VISIBLE_DEVICES"] = "2"; 5 | import tensorflow as tf 6 | import matplotlib.pyplot as plt 7 | from tensorflow.compat.v1.keras.backend import set_session 8 | config = tf.compat.v1.ConfigProto() 9 | config.gpu_options.allow_growth = True # dynamically grow the memory used on the GPU 10 | config.log_device_placement = True # to log device placement (on which device the operation ran) 11 | sess = tf.compat.v1.Session(config=config) 12 | set_session(sess) 13 | from tensorflow.keras import optimizers 14 | import tensorflow.keras as keras 15 | import tensorflow.keras.backend as K 16 | 17 | 18 | from Models import Model 19 | model= Model() 20 | model.summary() 21 | 22 | from Models import Model_P 23 | model= Model_P() 24 | model.summary() 25 | 26 | 27 | from read_data1 import data_readV 28 | 29 | img_,cor_,clas_=data_readV() 30 | 31 | 32 | 33 | 34 | 35 | def Loss_clas(y_true, y_pred): 36 | 37 | alpha_factor = K.ones_like(y_true) * 0.25 38 | alpha_factor = tf.where(K.equal(y_true, 1), alpha_factor, 1 - alpha_factor) 39 | focal_weight = tf.where(K.equal(y_true, 1), 1 - y_pred, y_pred) 40 | focal_weight = alpha_factor * focal_weight ** 2 41 | cls_loss = focal_weight * K.binary_crossentropy(y_true, y_pred) 42 | normalizer = K.cast(K.shape(y_pred)[1], K.floatx()) 43 | normalizer = K.maximum(K.cast_to_floatx(1.0), normalizer) 44 | 45 | class_=K.sum(cls_loss) / normalizer 46 | 47 | return class_ 48 | 49 | def calculate_iou(target_boxes, pred_boxes): 50 | xA = K.maximum(target_boxes[..., 0], pred_boxes[..., 0]) 51 | yA = K.maximum(target_boxes[..., 1], pred_boxes[..., 1]) 52 | xB = K.minimum(target_boxes[..., 2], pred_boxes[..., 2]) 53 | yB = K.minimum(target_boxes[..., 3], pred_boxes[..., 3]) 54 | interArea = K.maximum(0.0, xB - xA) * K.maximum(0.0, yB - yA) 55 | boxAArea = (target_boxes[..., 2] - target_boxes[..., 0]) * (target_boxes[..., 3] - target_boxes[..., 1]) 56 | boxBArea = (pred_boxes[..., 2] - pred_boxes[..., 0]) * (pred_boxes[..., 3] - pred_boxes[..., 1]) 57 | iou = interArea / (boxAArea + boxBArea - interArea) 58 | return iou 59 | 60 | def custom_loss(y_true, y_pred): 61 | mse = tf.losses.mean_squared_error(y_true, y_pred) 62 | iou = calculate_iou(y_true, y_pred) 63 | return mse + (1 - iou) 64 | 65 | 66 | epochs=50 67 | Adam = optimizers.Adam(lr=0.0001, beta_1=0.9, beta_2=0.99) 68 | model.compile(optimizer=Adam, loss=[custom_loss,Loss_clas],loss_weights = [1,1]) 69 | model.fit(img_,[cor_,clas_],batch_size=2, 70 | epochs=epochs) 71 | model.save_weights("MODEL3.h5") 72 | 73 | 74 | 75 | model.load_weights("MODEL2.h5") 76 | 77 | ## Testing ### 78 | img_p,_,_=data_readV() 79 | 80 | result = model.predict(img_p) 81 | cor_p=result[0] 82 | clas_p=result[1] 83 | 84 | import numpy as np 85 | import cv2 86 | import os 87 | save_path='/home/user01/data_ssd/Abbas/Dog1/Evaluation/pred/' 88 | path_img='/home/user01/data_ssd/Abbas/Dog1/Evaluation/pred_imgs/' 89 | 90 | fontScale = 1 91 | color = (0, 0, 1) 92 | thickness = 2 93 | font = cv2.FONT_HERSHEY_SIMPLEX 94 | 95 | for i in range(35,37): 96 | name=str(i) 97 | file = os.path.join(save_path, name +".txt") 98 | file = open(file, "w") 99 | class_name=np.argmax(clas_p[i]) 100 | class_prob=np.max(clas_p[i]) 101 | xmin=cor_p[i][0]*400 102 | ymin=cor_p[i][1]*400 103 | xmax=cor_p[i][2]*400 104 | ymax=cor_p[i][3]*400 105 | file.write(str(class_name) + ' ') 106 | file.write(str(class_prob) + ' ') 107 | file.write(str(xmin) + ' ') 108 | file.write(str(ymin ) + ' ') 109 | file.write(str(xmax ) + ' ') 110 | file.write(str(ymax)) 111 | file.close() 112 | org = (int(xmin), int(ymin)) 113 | image=img_p[i,:,:,:] 114 | cv2.rectangle(image, (int(xmin), int(ymin)), 115 | (int(xmax), int(ymax)), 116 | (1, 0, 0),thickness = 2) 117 | image = cv2.putText(image, str(class_name), org, font, 118 | fontScale, color, thickness, cv2.LINE_AA) 119 | org1 = (int(xmin+20), int(ymin-10)) 120 | image = cv2.putText(image, str(class_prob), org1, font, 121 | 0.5, color, 1, cv2.LINE_AA) 122 | cv2.imwrite(os.path.join(path_img , str(i)+".png"),image*255) 123 | 124 | 125 | 126 | ### write Grond Truths ## 127 | import numpy as np 128 | import cv2 129 | import os 130 | save_path='/home/user01/data_ssd/Abbas/Dog1/Evaluation/ground/' 131 | path_img='/home/user01/data_ssd/Abbas/Dog1/Evaluation/ground_imgs/' 132 | fontScale = 1 133 | color = (0, 0, 1) 134 | thickness = 2 135 | font = cv2.FONT_HERSHEY_SIMPLEX 136 | 137 | for i in range(50,55): 138 | name=str(i) 139 | file = os.path.join(save_path, name +".txt") 140 | file = open(file, "w") 141 | class_name=np.argmax(clas_[i]) 142 | class_prob=np.max(clas_[i]) 143 | xmin=cor_[i][0]*400 144 | ymin=cor_[i][1]*400 145 | xmax=cor_[i][2]*400 146 | ymax=cor_[i][3]*400 147 | file.write(str(class_name) + ' ') 148 | file.write(str(xmin) + ' ') 149 | file.write(str(ymin ) + ' ') 150 | file.write(str(xmax ) + ' ') 151 | file.write(str(ymax)) 152 | file.close() 153 | org = (int(xmin), int(ymin)) 154 | image=img_[i,:,:,:] 155 | cv2.rectangle(image, (int(xmin), int(ymin)), 156 | (int(xmax), int(ymax)), 157 | (1, 0, 0),thickness = 2) 158 | 159 | image = cv2.putText(image, str(class_name), org, font, 160 | fontScale, color, thickness, cv2.LINE_AA) 161 | cv2.imwrite(os.path.join(path_img , str(i)+".png"),image*255) 162 | 163 | 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /Visitation of Activation Map/grad_cam.py: -------------------------------------------------------------------------------- 1 | import os 2 | os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"; 3 | # The GPU id to use, usually either "0" or "1"; 4 | os.environ["CUDA_VISIBLE_DEVICES"] = "3"; 5 | import tensorflow as tf 6 | import matplotlib.pyplot as plt 7 | from tensorflow.compat.v1.keras.backend import set_session 8 | config = tf.compat.v1.ConfigProto() 9 | config.gpu_options.allow_growth = True # dynamically grow the memory used on the GPU 10 | config.log_device_placement = True # to log device placement (on which device the operation ran) 11 | sess = tf.compat.v1.Session(config=config) 12 | set_session(sess) 13 | from tensorflow.keras import optimizers 14 | import tensorflow.keras as keras 15 | import tensorflow.keras.backend as K 16 | 17 | import tensorflow.keras as keras 18 | import tensorflow as tf 19 | import matplotlib.pyplot as plt 20 | import numpy as np 21 | print("keras {}".format(keras.__version__)) 22 | print("tensorflow {}".format(tf.__version__)) 23 | 24 | 25 | 26 | 27 | 28 | from tensorflow.keras.applications.vgg16 import VGG16, preprocess_input 29 | model = VGG16(weights='imagenet') 30 | model.summary() 31 | for ilayer, layer in enumerate(model.layers): 32 | print("{:3.0f} {:10}".format(ilayer, layer.name)) 33 | 34 | 35 | from tensorflow.vis.utils import utils 36 | # Utility to search for layer index by name. 37 | # Alternatively we can specify this as -1 since it corresponds to the last layer. 38 | layer_idx = utils.find_layer_idx(model, 'predictions') 39 | # Swap softmax with linear 40 | model.layers[layer_idx].activation = tf.keras.activations.linear 41 | model = utils.apply_modifications(model) 42 | 43 | from vis.visualization import visualize_cam 44 | 45 | from keras.vis.utils import utils 46 | from vis.losses import ActivationMaximization 47 | 48 | import tensorflow.keras.utils as utils 49 | 50 | 51 | 52 | import vis 53 | 54 | import vis.utils as utils 55 | 56 | layer_idx = utils.find_layer_idx(model, 'predictions') 57 | # Swap softmax with linear 58 | model.layers[layer_idx].activation = keras.activations.linear 59 | model = utils.apply_modifications(model) 60 | 61 | model.layers[10].activation = keras.activations.linear 62 | model = utils.apply_modifications(model) 63 | 64 | 65 | 66 | from vis.visualization import visualize_cam 67 | 68 | from vis.visualization import visualize_saliency 69 | 70 | 71 | 72 | 73 | 74 | 75 | import cv2 76 | import numpy as np 77 | import tensorflow as tf 78 | 79 | IMAGE_PATH = '/home/user01/data_ssd/Abbas/dog3/train/1/file_4.jpg' 80 | LAYER_NAME = 'block5_conv3' 81 | CAT_CLASS_INDEX = 0 82 | 83 | img = tf.keras.preprocessing.image.load_img(IMAGE_PATH, target_size=(400, 400)) 84 | img = tf.keras.preprocessing.image.img_to_array(img) 85 | 86 | #model = tf.keras.applications.vgg16.VGG16(weights='imagenet', include_top=True) 87 | 88 | from Models import Model_P 89 | model= Model_P() 90 | model.summary() 91 | model.load_weights("MODEL1.h5") 92 | 93 | 94 | for i in range(len(model.layers)): 95 | layer = model.layers[i] 96 | # check for convolutional layer 97 | # summarize output shape 98 | print(i, layer.name, layer.output.shape) 99 | 100 | grad_model = tf.keras.models.Model([model.inputs], [model.get_layer(LAYER_NAME).output, model.output]) 101 | 102 | print(grad_model) 103 | with tf.GradientTape() as tape: 104 | conv_outputs, predictions = grad_model(np.array([img])) 105 | predictions=predictions[1] 106 | print(predictions) 107 | loss = predictions[:, 0] 108 | 109 | output = conv_outputs[0] 110 | grads = tape.gradient(loss, conv_outputs)[0] 111 | 112 | gate_f = tf.cast(output > 0, 'float32') 113 | gate_r = tf.cast(grads > 0, 'float32') 114 | guided_grads = tf.cast(output > 0, 'float32') * tf.cast(grads > 0, 'float32') * grads 115 | 116 | weights = tf.reduce_mean(guided_grads, axis=(0, 1)) 117 | 118 | cam = np.ones(output.shape[0: 2], dtype = np.float32) 119 | 120 | for i, w in enumerate(weights): 121 | cam += w * output[:, :, i] 122 | 123 | cam = cv2.resize(cam.numpy(), (400, 400)) 124 | cam = np.maximum(cam, 0) 125 | heatmap = (cam - cam.min()) / (cam.max() - cam.min()) 126 | 127 | cam = cv2.applyColorMap(np.uint8(255*heatmap), cv2.COLORMAP_JET) 128 | 129 | output_image = cv2.addWeighted(cv2.cvtColor(img.astype('uint8'), cv2.COLOR_RGB2BGR), 0.5, cam, 1, 0) 130 | 131 | cv2.imwrite('cam.png', output_image) 132 | 133 | 134 | plt.figure() 135 | plt.imshow(cam) 136 | 137 | 138 | import cv2 139 | import numpy as np 140 | import tensorflow as tf 141 | 142 | IMAGE_PATH = '/home/user01/data_ssd/Abbas/dog3/train/10/file_3.jpg' 143 | 144 | LAYER_NAME = 'block5_conv3' 145 | CAT_CLASS_INDEX = 281 146 | 147 | img = tf.keras.preprocessing.image.load_img(IMAGE_PATH, target_size=(224, 224)) 148 | img = tf.keras.preprocessing.image.img_to_array(img) 149 | 150 | model = tf.keras.applications.vgg16.VGG16(weights='imagenet', include_top=True) 151 | 152 | grad_model = tf.keras.models.Model([model.inputs], [model.get_layer(LAYER_NAME).output, model.output]) 153 | 154 | with tf.GradientTape() as tape: 155 | conv_outputs, predictions = grad_model(np.array([img])) 156 | print(conv_outputs) 157 | print(predictions) 158 | loss = predictions[:, 10] 159 | 160 | output = conv_outputs[0] 161 | grads = tape.gradient(loss, conv_outputs)[0] 162 | 163 | gate_f = tf.cast(output > 0, 'float32') 164 | gate_r = tf.cast(grads > 0, 'float32') 165 | guided_grads = tf.cast(output > 0, 'float32') * tf.cast(grads > 0, 'float32') * grads 166 | 167 | weights = tf.reduce_mean(guided_grads, axis=(0, 1)) 168 | 169 | cam = np.ones(output.shape[0: 2], dtype = np.float32) 170 | 171 | for i, w in enumerate(weights): 172 | cam += w * output[:, :, i] 173 | 174 | cam = cv2.resize(cam.numpy(), (224, 224)) 175 | cam = np.maximum(cam, 0) 176 | heatmap = (cam - cam.min()) / (cam.max() - cam.min()) 177 | 178 | cam = cv2.applyColorMap(np.uint8(255*heatmap), cv2.COLORMAP_JET) 179 | 180 | output_image = cv2.addWeighted(cv2.cvtColor(img.astype('uint8'), cv2.COLOR_RGB2BGR), 0.5, cam, 1, 0) 181 | 182 | cv2.imwrite('cam1.png', output_image) -------------------------------------------------------------------------------- /Visitation of Activation Map/cam2.py: -------------------------------------------------------------------------------- 1 | from tensorflow.keras.applications.vgg16 import ( 2 | VGG16, preprocess_input, decode_predictions) 3 | from tensorflow.keras.preprocessing import image 4 | from tensorflow.keras.layers import Lambda 5 | from tensorflow.keras.models import Sequential 6 | from tensorflow.python.framework import ops 7 | import tensorflow.keras.backend as K 8 | import tensorflow as tf 9 | import numpy as np 10 | import sys 11 | import cv2 12 | 13 | import os 14 | os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"; 15 | # The GPU id to use, usually either "0" or "1"; 16 | os.environ["CUDA_VISIBLE_DEVICES"] = "3"; 17 | import tensorflow as tf 18 | import matplotlib.pyplot as plt 19 | from tensorflow.compat.v1.keras.backend import set_session 20 | config = tf.compat.v1.ConfigProto() 21 | config.gpu_options.allow_growth = True # dynamically grow the memory used on the GPU 22 | config.log_device_placement = True # to log device placement (on which device the operation ran) 23 | sess = tf.compat.v1.Session(config=config) 24 | set_session(sess) 25 | from tensorflow.keras import optimizers 26 | import tensorflow.keras as keras 27 | import tensorflow.keras.backend as K 28 | 29 | def target_category_loss(x, category_index, nb_classes): 30 | return tf.multiply(x, K.one_hot([category_index], nb_classes)) 31 | 32 | def target_category_loss_output_shape(input_shape): 33 | return input_shape 34 | 35 | def normalize(x): 36 | # utility function to normalize a tensor by its L2 norm 37 | return x / (K.sqrt(K.mean(K.square(x))) + 1e-5) 38 | 39 | def load_image(img_path): 40 | img = image.load_img(img_path, target_size=(224, 224)) 41 | x = image.img_to_array(img) 42 | x = np.expand_dims(x, axis=0) 43 | x = preprocess_input(x) 44 | return x 45 | 46 | def register_gradient(): 47 | if "GuidedBackProp" not in ops._gradient_registry._registry: 48 | @ops.RegisterGradient("GuidedBackProp") 49 | def _GuidedBackProp(op, grad): 50 | dtype = op.inputs[0].dtype 51 | return grad * tf.cast(grad > 0., dtype) * \ 52 | tf.cast(op.inputs[0] > 0., dtype) 53 | 54 | def compile_saliency_function(model, activation_layer='block5_conv3'): 55 | input_img = model.input 56 | layer_dict = dict([(layer.name, layer) for layer in model.layers[1:]]) 57 | layer_output = layer_dict[activation_layer].output 58 | max_output = K.max(layer_output, axis=3) 59 | saliency = K.gradients(K.sum(max_output), input_img)[0] 60 | return K.function([input_img, K.learning_phase()], [saliency]) 61 | 62 | def modify_backprop(model, name): 63 | g = tf.get_default_graph() 64 | with g.gradient_override_map({'Relu': name}): 65 | 66 | # get layers that have an activation 67 | layer_dict = [layer for layer in model.layers[1:] 68 | if hasattr(layer, 'activation')] 69 | 70 | # replace relu activation 71 | for layer in layer_dict: 72 | if layer.activation == keras.activations.relu: 73 | layer.activation = tf.nn.relu 74 | 75 | # re-instanciate a new model 76 | new_model = VGG16(weights='imagenet') 77 | return new_model 78 | 79 | def deprocess_image(x): 80 | ''' 81 | Same normalization as in: 82 | https://github.com/fchollet/keras/blob/master/examples/conv_filter_visualization.py 83 | ''' 84 | if np.ndim(x) > 3: 85 | x = np.squeeze(x) 86 | # normalize tensor: center on 0., ensure std is 0.1 87 | x -= x.mean() 88 | x /= (x.std() + 1e-5) 89 | x *= 0.1 90 | 91 | # clip to [0, 1] 92 | x += 0.5 93 | x = np.clip(x, 0, 1) 94 | 95 | # convert to RGB array 96 | x *= 255 97 | if K.image_dim_ordering() == 'th': 98 | x = x.transpose((1, 2, 0)) 99 | x = np.clip(x, 0, 255).astype('uint8') 100 | return x 101 | 102 | def grad_cam(input_model, image, category_index, layer_name): 103 | model = Sequential() 104 | model.add(input_model) 105 | 106 | nb_classes = 1000 107 | target_layer = lambda x: target_category_loss(x, category_index, nb_classes) 108 | model.add(Lambda(target_layer, 109 | output_shape = target_category_loss_output_shape)) 110 | 111 | #loss = K.sum(model.layers[-1].output) 112 | #conv_output = [l for l in model.layers[0].layers if l.name is layer_name][0].output 113 | #grads = tf.GradientTape(loss, conv_output)[0] 114 | #grads = normalize(K.gradients(loss, conv_output)[0]) 115 | grad_model = tf.keras.models.Model([model.inputs], [model.get_layer(layer_name).output, model.output]) 116 | with tf.GradientTape() as tape: 117 | conv_outputs, predictions = grad_model(np.array([image])) 118 | loss = predictions[:, category_index] 119 | grads = tape.gradient(loss, conv_outputs)[0] 120 | gradient_function = K.function([model.layers[0].input], [conv_outputs, grads]) 121 | 122 | output, grads_val = gradient_function([image]) 123 | output, grads_val = output[0, :], grads_val[0, :, :, :] 124 | 125 | weights = np.mean(grads_val, axis = (0, 1)) 126 | cam = np.ones(output.shape[0 : 2], dtype = np.float32) 127 | 128 | for i, w in enumerate(weights): 129 | cam += w * output[:, :, i] 130 | 131 | cam = cv2.resize(cam, (224, 224)) 132 | cam = np.maximum(cam, 0) 133 | heatmap = cam / np.max(cam) 134 | 135 | #Return to BGR [0..255] from the preprocessed image 136 | image = image[0, :] 137 | image -= np.min(image) 138 | image = np.minimum(image, 255) 139 | 140 | cam = cv2.applyColorMap(np.uint8(255*heatmap), cv2.COLORMAP_JET) 141 | cam = np.float32(cam) + np.float32(image) 142 | cam = 255 * cam / np.max(cam) 143 | return np.uint8(cam), heatmap 144 | 145 | preprocessed_input = load_image('/home/user01/data_ssd/Abbas/dog3/train/1/file_4.jpg') 146 | 147 | model = VGG16(weights='imagenet') 148 | model = tf.keras.applications.vgg16.VGG16(weights='imagenet', include_top=True) 149 | 150 | for i in range(len(model.layers)): 151 | layer = model.layers[i] 152 | # check for convolutional layer 153 | # summarize output shape 154 | print(i, layer.name, layer.output.shape) 155 | 156 | predictions = model.predict(preprocessed_input) 157 | top_1 = decode_predictions(predictions)[0][0] 158 | print('Predicted class:') 159 | print('%s (%s) with probability %.2f' % (top_1[1], top_1[0], top_1[2])) 160 | 161 | predicted_class = np.argmax(predictions) 162 | cam, heatmap = grad_cam(model, preprocessed_input, predicted_class, "block5_conv3") 163 | cv2.imwrite("gradcam.jpg", cam) 164 | 165 | register_gradient() 166 | guided_model = modify_backprop(model, 'GuidedBackProp') 167 | saliency_fn = compile_saliency_function(guided_model) 168 | saliency = saliency_fn([preprocessed_input, 0]) 169 | gradcam = saliency[0] * heatmap[..., np.newaxis] 170 | cv2.imwrite("guided_gradcam.jpg", deprocess_image(gradcam)) -------------------------------------------------------------------------------- /Visitation of Activation Map/GRAD_CAM_VGG.py: -------------------------------------------------------------------------------- 1 | import os 2 | os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"; 3 | # The GPU id to use, usually either "0" or "1"; 4 | os.environ["CUDA_VISIBLE_DEVICES"] = "3"; 5 | import tensorflow as tf 6 | from tensorflow.compat.v1.keras.backend import set_session 7 | config = tf.compat.v1.ConfigProto() 8 | config.gpu_options.allow_growth = True # dynamically grow the memory used on the GPU 9 | config.log_device_placement = True # to log device placement (on which device the operation ran) 10 | sess = tf.compat.v1.Session(config=config) 11 | set_session(sess) 12 | import matplotlib.pyplot as plt 13 | import cv2 14 | import numpy as np 15 | import tensorflow.keras.backend as K 16 | import matplotlib.cm as cm 17 | 18 | 19 | import tensorflow.keras as keras 20 | 21 | # ============================================================================= 22 | # from tensorflow.keras.applications.vgg16 import VGG16 23 | # model = VGG16(weights='imagenet', input_shape=(224, 224, 3)) 24 | # image = cv2.imread('/home/user01/data_ssd/Abbas/dog3/dog_img.PNG') 25 | # image = cv2.resize(image, (224,224), interpolation = cv2.INTER_AREA) 26 | # image=image/255 27 | # image_1= np.expand_dims(image, axis=0) 28 | # image_1 = tf.convert_to_tensor(image_1, np.float32) 29 | # predict = model.predict(image_1) 30 | # ============================================================================= 31 | 32 | 33 | 34 | 35 | model_builder = keras.applications.VGG16 36 | img_size = (224, 224) 37 | preprocess_input = keras.applications.xception.preprocess_input 38 | decode_predictions = keras.applications.vgg16.decode_predictions 39 | 40 | model = model_builder(weights="imagenet") 41 | model.summary() 42 | 43 | last_conv_layer_name = "block5_conv3" 44 | classifier_layer_names = [ 45 | "predictions" 46 | ] 47 | 48 | 49 | 50 | 51 | def get_img_array(img_path, size): 52 | # `img` is a PIL image of size 299x299 53 | img = keras.preprocessing.image.load_img(img_path, target_size=size) 54 | # `array` is a float32 Numpy array of shape (299, 299, 3) 55 | array = keras.preprocessing.image.img_to_array(img) 56 | # We add a dimension to transform our array into a "batch" 57 | # of size (1, 299, 299, 3) 58 | array = np.expand_dims(array, axis=0) 59 | return array 60 | 61 | 62 | def make_gradcam_heatmap( 63 | img_array, model, last_conv_layer_name, classifier_layer_names 64 | ): 65 | # First, we create a model that maps the input image to the activations 66 | # of the last conv layer 67 | last_conv_layer = model.get_layer(last_conv_layer_name) 68 | last_conv_layer_model = keras.Model(model.inputs, last_conv_layer.output) 69 | 70 | # Second, we create a model that maps the activations of the last conv 71 | # layer to the final class predictions 72 | classifier_input = keras.Input(shape=last_conv_layer.output.shape[1:]) 73 | x = classifier_input 74 | for layer_name in classifier_layer_names: 75 | x = model.get_layer(layer_name)(x) 76 | classifier_model = keras.Model(classifier_input, x) 77 | 78 | # Then, we compute the gradient of the top predicted class for our input image 79 | # with respect to the activations of the last conv layer 80 | with tf.GradientTape() as tape: 81 | # Compute activations of the last conv layer and make the tape watch it 82 | last_conv_layer_output = last_conv_layer_model(img_array) 83 | tape.watch(last_conv_layer_output) 84 | # Compute class predictions 85 | preds = classifier_model(last_conv_layer_output) 86 | top_pred_index = tf.argmax(preds[0]) 87 | top_class_channel = preds[:, top_pred_index] 88 | 89 | # This is the gradient of the top predicted class with regard to 90 | # the output feature map of the last conv layer 91 | grads = tape.gradient(top_class_channel, last_conv_layer_output) 92 | 93 | # This is a vector where each entry is the mean intensity of the gradient 94 | # over a specific feature map channel 95 | pooled_grads = tf.reduce_mean(grads, axis=(0, 1, 2)) 96 | 97 | # We multiply each channel in the feature map array 98 | # by "how important this channel is" with regard to the top predicted class 99 | last_conv_layer_output = last_conv_layer_output.numpy()[0] 100 | pooled_grads = pooled_grads.numpy() 101 | for i in range(pooled_grads.shape[-1]): 102 | last_conv_layer_output[:, :, i] *= pooled_grads[i] 103 | 104 | # The channel-wise mean of the resulting feature map 105 | # is our heatmap of class activation 106 | heatmap = np.mean(last_conv_layer_output, axis=-1) 107 | 108 | # For visualization purpose, we will also normalize the heatmap between 0 & 1 109 | heatmap = np.maximum(heatmap, 0) / np.max(heatmap) 110 | return heatmap 111 | 112 | 113 | 114 | img_path = '/home/user01/data_ssd/Abbas/dog3/11.png' 115 | img_array = preprocess_input(get_img_array(img_path, size=img_size)) 116 | 117 | # Make model 118 | model = model_builder(weights="imagenet") 119 | 120 | # Print what the top predicted class is 121 | preds = model.predict(img_array) 122 | print("Predicted:", decode_predictions(preds, top=1)[0]) 123 | 124 | # Generate class activation heatmap 125 | heatmap = make_gradcam_heatmap( 126 | img_array, model, last_conv_layer_name, classifier_layer_names 127 | ) 128 | 129 | # Display heatmap 130 | plt.matshow(heatmap) 131 | plt.show() 132 | 133 | 134 | # We load the original image 135 | img = keras.preprocessing.image.load_img(img_path) 136 | img = keras.preprocessing.image.img_to_array(img) 137 | 138 | # We rescale heatmap to a range 0-255 139 | heatmap = np.uint8(255 * heatmap) 140 | 141 | # We use jet colormap to colorize heatmap 142 | jet = cm.get_cmap("jet") 143 | 144 | # We use RGB values of the colormap 145 | jet_colors = jet(np.arange(256))[:, :3] 146 | jet_heatmap = jet_colors[heatmap] 147 | 148 | # We create an image with RGB colorized heatmap 149 | jet_heatmap = keras.preprocessing.image.array_to_img(jet_heatmap) 150 | jet_heatmap = jet_heatmap.resize((img.shape[1], img.shape[0])) 151 | jet_heatmap = keras.preprocessing.image.img_to_array(jet_heatmap) 152 | 153 | # Superimpose the heatmap on original image 154 | superimposed_img = jet_heatmap * 0.7 + img*.3 155 | superimposed_img = keras.preprocessing.image.array_to_img(superimposed_img) 156 | 157 | # Save the superimposed image 158 | save_path = "elephant_cam1.jpg" 159 | superimposed_img.save(save_path) 160 | 161 | # Display Grad CAM 162 | 163 | 164 | plt.matshow(jet_heatmap) 165 | plt.show() 166 | 167 | 168 | plt.matshow(superimposed_img) 169 | plt.show() 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | # ============================================================================= 178 | # import cv2 179 | # img_path = '/home/user01/data_ssd/Abbas/dog3/elephent.PNG' 180 | # img=cv2.imread(img_path) 181 | # 182 | # flipVertical = cv2.flip(img, 1) 183 | # 184 | # plt.matshow(flipVertical) 185 | # plt.show() 186 | # 187 | # save_path = "/home/user01/data_ssd/Abbas/dog3/" 188 | # 189 | # cv2.imwrite(os.path.join(save_path , str(11)+".png"),flipVertical) 190 | # ============================================================================= 191 | -------------------------------------------------------------------------------- /Models/Models.py: -------------------------------------------------------------------------------- 1 | import tensorflow.keras as keras 2 | 3 | classes=5 4 | def Model(input_size = (400,400,3)): 5 | inputs=keras.layers.Input(input_size) 6 | # Block 1 7 | x = keras.layers.Conv2D(16, (3, 3),activation='relu',padding='same',name='block1_conv1')(inputs) 8 | x = keras.layers.Conv2D(16, (3, 3),activation='relu',padding='same',name='block1_conv2')(x) 9 | x=keras.layers.BatchNormalization()(x) 10 | x = keras.layers.MaxPooling2D((2, 2), strides=(2, 2), name='block1_pool')(x) 11 | # Block 2 12 | x = keras.layers.Conv2D(64, (3, 3), activation='relu',padding='same',name='block2_conv1')(x) 13 | x = keras.layers.Conv2D(64, (3, 3),activation='relu',padding='same',name='block2_conv2')(x) 14 | x=keras.layers.BatchNormalization()(x) 15 | x = keras.layers.MaxPooling2D((2, 2), strides=(2, 2), name='block2_pool')(x) 16 | # Block 3 17 | x = keras.layers.Conv2D(128, (3, 3),activation='relu',padding='same',name='block3_conv1')(x) 18 | x = keras.layers.Conv2D(128, (3, 3),activation='relu',padding='same',name='block3_conv2')(x) 19 | x=keras.layers.BatchNormalization()(x) 20 | x = keras.layers.MaxPooling2D((2, 2), strides=(2, 2), name='block3_pool')(x) 21 | # Block 4 22 | x = keras.layers.Conv2D(256, (3, 3),activation='relu',padding='same',name='block4_conv2')(x) 23 | x = keras.layers.Conv2D(256, (3, 3),activation='relu',padding='same',name='block4_conv3')(x) 24 | x=keras.layers.BatchNormalization()(x) 25 | x = keras.layers.MaxPooling2D((2, 2), strides=(2, 2), name='block4_pool')(x) 26 | 27 | # Block 5 28 | x = keras.layers.Conv2D(512, (3, 3),activation='relu',padding='same',name='block5_conv1')(x) 29 | x = keras.layers.Conv2D(512, (3, 3),activation='relu',padding='same',name='block5_conv2')(x) 30 | x=keras.layers.BatchNormalization()(x) 31 | x = keras.layers.MaxPooling2D((2, 2), strides=(2, 2), name='block5_pool')(x) 32 | #x = keras.layers.Dropout(0.5)(x) 33 | #fully connected 34 | x1 = keras.layers.Flatten(name='flatten')(x) 35 | x = keras.layers.Dense(4096, activation='relu', name='fc1')(x1) 36 | x = keras.layers.Dense(1000, activation='relu', name='fc2')(x) 37 | x = keras.layers.Dense(100, activation='relu', name='fc3')(x) 38 | x = keras.layers.Dense(4, activation='linear', name='coordinates')(x) 39 | 40 | 41 | 42 | y= keras.layers.Dense(4096, activation='relu', name='fc4')(x1) 43 | y=keras.layers.BatchNormalization()(y) 44 | y = keras.layers.Dense(1000, activation='relu', name='fc5')(y) 45 | y=keras.layers.BatchNormalization()(y) 46 | y = keras.layers.Dense(100, activation='relu', name='fc6')(y) 47 | y=keras.layers.BatchNormalization()(y) 48 | y = keras.layers.Dense(classes, activation='softmax', name='class')(y) 49 | model = keras.models.Model(inputs, [x,y]) 50 | return model 51 | classes=5 52 | def Model_j(input_size = (400,400,3)): 53 | inputs=keras.layers.Input(input_size) 54 | # Block 1 55 | x = keras.layers.Conv2D(16, (3, 3),activation='relu',padding='same',name='block1_conv1')(inputs) 56 | x = keras.layers.Conv2D(16, (3, 3),activation='relu',padding='same',name='block1_conv2')(x) 57 | x=keras.layers.BatchNormalization()(x) 58 | x = keras.layers.MaxPooling2D((2, 2), strides=(2, 2), name='block1_pool')(x) 59 | # Block 2 60 | x = keras.layers.Conv2D(64, (3, 3), activation='relu',padding='same',name='block2_conv1')(x) 61 | x = keras.layers.Conv2D(64, (3, 3),activation='relu',padding='same',name='block2_conv2')(x) 62 | x=keras.layers.BatchNormalization()(x) 63 | x = keras.layers.MaxPooling2D((2, 2), strides=(2, 2), name='block2_pool')(x) 64 | # Block 3 65 | x = keras.layers.Conv2D(128, (3, 3),activation='relu',padding='same',name='block3_conv1')(x) 66 | x = keras.layers.Conv2D(128, (3, 3),activation='relu',padding='same',name='block3_conv2')(x) 67 | x=keras.layers.BatchNormalization()(x) 68 | x = keras.layers.MaxPooling2D((2, 2), strides=(2, 2), name='block3_pool')(x) 69 | # Block 4 70 | x = keras.layers.Conv2D(256, (3, 3),activation='relu',padding='same',name='block4_conv2')(x) 71 | x = keras.layers.Conv2D(256, (3, 3),activation='relu',padding='same',name='block4_conv3')(x) 72 | x=keras.layers.BatchNormalization()(x) 73 | x = keras.layers.MaxPooling2D((2, 2), strides=(2, 2), name='block4_pool')(x) 74 | 75 | # Block 5 76 | x = keras.layers.Conv2D(512, (3, 3),activation='relu',padding='same',name='block5_conv1')(x) 77 | x = keras.layers.Conv2D(512, (3, 3),activation='relu',padding='same',name='block5_conv2')(x) 78 | x=keras.layers.BatchNormalization()(x) 79 | x = keras.layers.MaxPooling2D((2, 2), strides=(2, 2), name='block5_pool')(x) 80 | x = keras.layers.Dropout(0.5)(x) 81 | #fully connected 82 | x1 = keras.layers.Flatten(name='flatten')(x) 83 | x = keras.layers.Dense(4096, activation='relu', name='fc1')(x1) 84 | x=keras.layers.BatchNormalization()(x) 85 | x = keras.layers.Dense(1000, activation='relu', name='fc2')(x) 86 | x = keras.layers.Dense(100, activation='relu', name='fc3')(x) 87 | x = keras.layers.Dense(25, activation='relu', name='coordinates')(x) 88 | model = keras.models.Model(inputs,x) 89 | return model 90 | 91 | def Model_P(input_size = (400,400,3)): 92 | inputs=keras.layers.Input(input_size) 93 | # Block 1 94 | x = keras.layers.Conv2D(16, (3, 3),activation='relu',padding='same',name='block1_conv1')(inputs) 95 | x = keras.layers.Conv2D(16, (3, 3),activation='relu',padding='same',name='block1_conv2')(x) 96 | x = keras.layers.Conv2D(16, (3, 3),activation='relu',strides=(2, 2),padding='same')(x) 97 | x=keras.layers.BatchNormalization()(x) 98 | 99 | # Block 2 100 | x = keras.layers.Conv2D(64, (3, 3), activation='relu',padding='same',name='block2_conv1')(x) 101 | x = keras.layers.Conv2D(64, (3, 3),activation='relu',padding='same',name='block2_conv2')(x) 102 | x = keras.layers.Conv2D(64, (3, 3),activation='relu',strides=(2, 2),padding='same')(x) 103 | x=keras.layers.BatchNormalization()(x) 104 | # Block 3 105 | x = keras.layers.Conv2D(128, (3, 3),activation='relu',padding='same',name='block3_conv1')(x) 106 | x = keras.layers.Conv2D(128, (3, 3),activation='relu',padding='same',name='block3_conv2')(x) 107 | x = keras.layers.Conv2D(128, (3, 3),activation='relu',strides=(2, 2),padding='same')(x) 108 | x=keras.layers.BatchNormalization()(x) 109 | # Block 4 110 | x = keras.layers.Conv2D(256, (3, 3),activation='relu',padding='same',name='block4_conv2')(x) 111 | x = keras.layers.Conv2D(256, (3, 3),activation='relu',padding='same',name='block4_conv3')(x) 112 | x = keras.layers.Conv2D(256, (3, 3),activation='relu',strides=(2, 2),padding='same')(x) 113 | x=keras.layers.BatchNormalization()(x) 114 | 115 | # Block 5 116 | x = keras.layers.Conv2D(512, (3, 3),activation='relu',padding='same',name='block5_conv1')(x) 117 | x = keras.layers.Conv2D(512, (3, 3),activation='relu',padding='same',name='block5_conv2')(x) 118 | x = keras.layers.Conv2D(512, (3, 3),activation='relu',strides=(2, 2),padding='same')(x) 119 | x=keras.layers.BatchNormalization()(x) 120 | #fully connected 121 | x1 = keras.layers.Flatten(name='flatten')(x) 122 | x = keras.layers.Dense(4096, activation='relu', name='fc1')(x1) 123 | x = keras.layers.Dense(1000, activation='relu', name='fc2')(x) 124 | x = keras.layers.Dense(100, activation='relu', name='fc3')(x) 125 | x = keras.layers.Dense(4, activation='linear', name='coordinates')(x) 126 | 127 | 128 | y= keras.layers.Dense(4096, activation='relu', name='fc4')(x1) 129 | y=keras.layers.BatchNormalization()(y) 130 | y = keras.layers.Dense(1000, activation='relu', name='fc5')(y) 131 | y=keras.layers.BatchNormalization()(y) 132 | y = keras.layers.Dense(100, activation='relu', name='fc6')(y) 133 | y=keras.layers.BatchNormalization()(y) 134 | y = keras.layers.Dense(classes, activation='softmax', name='class')(y) 135 | model = keras.models.Model(inputs, [x,y]) 136 | return model 137 | --------------------------------------------------------------------------------