├── README.md ├── classification └── classify.py ├── detection └── detect.py ├── leaf_full.prototxt ├── leaf_full_iter_50000.caffemodel ├── leaf_full_iter_50000.solverstate ├── leaf_full_solver.prototxt ├── leaf_full_train_test.prototxt ├── preProcessing ├── convert_cifar_data.cpp ├── convert_protomean.py ├── create_leaf.sh ├── make_leaf_mean.sh ├── multiDataProcessing.py ├── multipleLeaf.sh └── resize.py └── train_full.sh /README.md: -------------------------------------------------------------------------------- 1 | # leaf 2 | 基于OverFeat的病斑检测系统: 3 | (1)基于keras训练Alexnet网络 4 | (2)遍历搜索,合并结果框 5 | -------------------------------------------------------------------------------- /classification/classify.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | classify.py is an out-of-the-box image classifer callable from the command line. 4 | 5 | By default it configures and runs the Caffe reference ImageNet model. 6 | """ 7 | import numpy as np 8 | import os 9 | import sys 10 | import argparse 11 | import glob 12 | import time 13 | 14 | import caffe 15 | 16 | 17 | def main(argv): 18 | pycaffe_dir = os.path.dirname(__file__) 19 | 20 | parser = argparse.ArgumentParser() 21 | # Required arguments: input and output files. 22 | parser.add_argument( 23 | "input_file", 24 | help="Input image, directory, or npy." 25 | ) 26 | parser.add_argument( 27 | "label_file", 28 | help="label txt for test data" 29 | ) 30 | 31 | # Optional arguments. 32 | parser.add_argument( 33 | "--model_def", 34 | default=os.path.join(pycaffe_dir, 35 | "leaf_full.prototxt"), 36 | help="Model definition file." 37 | ) 38 | 39 | parser.add_argument( 40 | "--pretrained_model", 41 | default=os.path.join(pycaffe_dir, 42 | "leaf_full_iter_50000.caffemodel"), 43 | help="Trained model weights file." 44 | ) 45 | 46 | parser.add_argument( 47 | "--gpu", 48 | action='store_true', 49 | help="Switch for gpu computation." 50 | ) 51 | 52 | parser.add_argument( 53 | "--center_only", 54 | action='store_true', 55 | help="Switch for prediction from center crop alone instead of " + 56 | "averaging predictions across crops (default)." 57 | ) 58 | 59 | parser.add_argument( 60 | "--images_dim", 61 | default='32,32', 62 | help="Canonical 'height,width' dimensions of input images." 63 | ) 64 | 65 | parser.add_argument( 66 | "--mean_file", 67 | default=os.path.join(pycaffe_dir, 68 | 'leaf_mean.npy'), 69 | help="Data set image mean of [Channels x Height x Width] dimensions " + 70 | "(numpy array). Set to '' for no mean subtraction." 71 | ) 72 | 73 | parser.add_argument( 74 | "--input_scale", 75 | type=float, 76 | help="Multiply input features by this scale to finish preprocessing." 77 | ) 78 | 79 | parser.add_argument( 80 | "--raw_scale", 81 | type=float, 82 | default=255.0, 83 | help="Multiply raw input by this scale before preprocessing." 84 | ) 85 | 86 | parser.add_argument( 87 | "--channel_swap", 88 | default='2,1,0', 89 | help="Order to permute input channels. The default converts " + 90 | "RGB -> BGR since BGR is the Caffe default by way of OpenCV." 91 | ) 92 | 93 | parser.add_argument( 94 | "--ext", 95 | default='jpg', 96 | help="Image file extension to take as input when a directory " + 97 | "is given as the input file." 98 | ) 99 | 100 | args = parser.parse_args() 101 | 102 | image_dims = [int(s) for s in args.images_dim.split(',')] 103 | 104 | mean, channel_swap = None, None 105 | if args.mean_file: 106 | mean = np.load(args.mean_file) 107 | if args.channel_swap: 108 | channel_swap = [int(s) for s in args.channel_swap.split(',')] 109 | 110 | #if args.gpu: 111 | caffe.set_mode_gpu() 112 | print("GPU mode") 113 | #else: 114 | #caffe.set_mode_cpu() 115 | #print("CPU mode") 116 | 117 | # Make classifier. 118 | classifier = caffe.Classifier(args.model_def, args.pretrained_model, 119 | image_dims=image_dims, mean=mean, 120 | input_scale=args.input_scale, raw_scale=args.raw_scale, 121 | channel_swap=channel_swap) 122 | 123 | # Read label file 124 | with open(args.label_file, 'r') as file: 125 | label = [] 126 | image_list = [] 127 | for line in file.readlines(): 128 | temp = line.strip('\n').split(' ') 129 | image_list.append(args.input_file + '/' + temp[0]) 130 | label.append(temp[1]) 131 | 132 | # Load numpy array (.npy), directory glob (*.jpg), or image file. 133 | args.input_file = os.path.expanduser(args.input_file) 134 | if args.input_file.endswith('npy'): 135 | print("Loading file: %s" % args.input_file) 136 | inputs = np.load(args.input_file) 137 | elif os.path.isdir(args.input_file): 138 | print("Loading folder: %s" % args.input_file) 139 | inputs =[caffe.io.load_image(im_f) 140 | for im_f in image_list] 141 | else: 142 | print("Loading file: %s" % args.input_file) 143 | inputs = [caffe.io.load_image(args.input_file)] 144 | 145 | print("Classifying %d inputs." % len(inputs)) 146 | 147 | iteration = 10000 148 | start = time.time() 149 | correct = 0.0 150 | wrong = 0.0 151 | for num in range(iteration): 152 | # Classify. 153 | start = time.time() 154 | print len(inputs[1]), np.shape(inputs[1]) 155 | predictions = classifier.predict(inputs, not args.center_only) 156 | sys.stdout.write("Iteration " + str(num) + " in %.2f s." % (time.time() - start)) 157 | print(' ') 158 | i = 0 159 | count = 0 160 | for output in predictions: 161 | answer = '3' 162 | if (float(output[0]) > float(output[1])): 163 | answer = '0' 164 | else: 165 | answer = '1' 166 | 167 | if (answer == label[i]): 168 | correct = correct + 1 169 | else: 170 | wrong = wrong + 1 171 | print output, image_list[i], label[i] 172 | count = count + 1 173 | i = i + 1 174 | print count 175 | 176 | sys.stdout.write("Accuracy rate is %.4f" % (correct/(correct+wrong))) 177 | print(' ') 178 | 179 | 180 | 181 | if __name__ == '__main__': 182 | main(sys.argv) 183 | -------------------------------------------------------------------------------- /detection/detect.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | classify.py is an out-of-the-box image classifer callable from the command line. 5 | 6 | By default it configures and runs the Caffe reference ImageNet model. 7 | """ 8 | import numpy as np 9 | import copy 10 | import shutil 11 | import os 12 | import sys 13 | import argparse 14 | import glob 15 | import time 16 | import cv2 17 | 18 | import caffe 19 | 20 | threshold = 0.95 21 | window_threshold = 150 22 | areaThreshold = 0.8 23 | initial_window_scale = 32 24 | scale_step = 10 25 | height_step = 8 26 | width_step = 8 27 | save_Path='/home/ganlinhao/DeepLearning/caffe/examples/leaf/Image' 28 | 29 | def main(argv): 30 | pycaffe_dir = os.path.dirname(__file__) 31 | 32 | parser = argparse.ArgumentParser() 33 | # Required arguments: input and output files. 34 | parser.add_argument( 35 | "input_file", 36 | help="Input image, directory, or npy." 37 | ) 38 | 39 | # Optional arguments. 40 | parser.add_argument( 41 | "--model_def", 42 | default=os.path.join(pycaffe_dir, 43 | "leaf_full.prototxt"), 44 | help="Model definition file." 45 | ) 46 | 47 | parser.add_argument( 48 | "--pretrained_model", 49 | default=os.path.join(pycaffe_dir, 50 | "leaf_full_iter_40000.caffemodel"), 51 | help="Trained model weights file." 52 | ) 53 | 54 | parser.add_argument( 55 | "--gpu", 56 | action='store_true', 57 | help="Switch for gpu computation." 58 | ) 59 | 60 | parser.add_argument( 61 | "--center_only", 62 | action='store_true', 63 | help="Switch for prediction from center crop alone instead of " + 64 | "averaging predictions across crops (default)." 65 | ) 66 | 67 | parser.add_argument( 68 | "--images_dim", 69 | default='32,32', 70 | help="Canonical 'height,width' dimensions of input images." 71 | ) 72 | 73 | parser.add_argument( 74 | "--mean_file", 75 | default=os.path.join(pycaffe_dir, 76 | 'leaf_mean.npy'), 77 | help="Data set image mean of [Channels x Height x Width] dimensions " + 78 | "(numpy array). Set to '' for no mean subtraction." 79 | ) 80 | 81 | parser.add_argument( 82 | "--input_scale", 83 | type=float, 84 | help="Multiply input features by this scale to finish preprocessing." 85 | ) 86 | 87 | parser.add_argument( 88 | "--raw_scale", 89 | type=float, 90 | default=255.0, 91 | help="Multiply raw input by this scale before preprocessing." 92 | ) 93 | 94 | parser.add_argument( 95 | "--channel_swap", 96 | default='2,1,0', 97 | help="Order to permute input channels. The default converts " + 98 | "RGB -> BGR since BGR is the Caffe default by way of OpenCV." 99 | ) 100 | 101 | parser.add_argument( 102 | "--ext", 103 | default='jpg', 104 | help="Image file extension to take as input when a directory " + 105 | "is given as the input file." 106 | ) 107 | 108 | args = parser.parse_args() 109 | 110 | image_dims = [int(s) for s in args.images_dim.split(',')] 111 | 112 | mean, channel_swap = None, None 113 | if args.mean_file: 114 | mean = np.load(args.mean_file) 115 | if args.channel_swap: 116 | channel_swap = [int(s) for s in args.channel_swap.split(',')] 117 | 118 | caffe.set_device(1) 119 | caffe.set_mode_gpu() 120 | print("GPU mode") 121 | 122 | # Make classifier. 123 | classifier = caffe.Classifier(args.model_def, args.pretrained_model, 124 | image_dims=image_dims, mean=mean, 125 | input_scale=args.input_scale, raw_scale=args.raw_scale, 126 | channel_swap=channel_swap) 127 | 128 | # Load numpy array (.npy), directory glob (*.jpg), or image file. 129 | args.input_file = os.path.expanduser(args.input_file) 130 | if os.path.isdir(args.input_file): 131 | print("Loading folder: %s" % args.input_file) 132 | inputs = glob.glob(args.input_file + '/*') 133 | else: 134 | print("Loading file: %s" % args.input_file) 135 | inputs = glob.glob(args.input_file) 136 | 137 | print("Loaded %d inputs." % len(inputs)) 138 | 139 | if os.path.exists(save_Path): 140 | shutil.rmtree(save_Path) 141 | os.mkdir(save_Path) 142 | start = time.time() 143 | im_num = 0 144 | for image in inputs: 145 | im = caffe.io.load_image(image) 146 | window_scale = initial_window_scale 147 | detections = [] 148 | num = 0 149 | while(window_scale < window_threshold): 150 | # ymin xmin ymax xmax 151 | window=[0, 0, window_scale, window_scale] 152 | flag = True 153 | while(flag == True): 154 | # Crop image 155 | crop = im[window[0]:window[2], window[1]:window[3]] 156 | imgs = caffe.io.resize_image(crop, (32, 32)) 157 | imgs_list = [] 158 | imgs_list.append(imgs) 159 | # predict 160 | prediction = classifier.predict(imgs_list, not args.center_only) 161 | 162 | # chose the rectangle window 163 | if prediction[0][1] > threshold: 164 | isAdd = True 165 | if len(detections) == 0: 166 | detections.append(copy.copy(window)) 167 | else: 168 | for win in detections: 169 | isOverlap, window = merge_rectangle(win, window) 170 | if isOverlap: 171 | detections.remove(win) 172 | result = copy.copy(window) 173 | isAdd = False 174 | if isAdd: 175 | detections.append(copy.copy(window)) 176 | else: 177 | detections.append(copy.copy(result)) 178 | num += 1 179 | window, flag = move_window(window, np.shape(im), window_scale) 180 | window_scale = window_scale + scale_step 181 | 182 | # recheck the overlap rectangle 183 | remove = [] 184 | for i in range(0, len(detections)): 185 | for j in range(i+1, len(detections)): 186 | isRepeated, newWin = merge_rectangle(detections[i], detections[j]) 187 | if isRepeated: 188 | remove.append(copy.copy(detections[i])) 189 | for win in remove: 190 | if win in detections: 191 | detections.remove(win) 192 | 193 | # draw the rectangles 194 | draw_rectangle(detections, image) 195 | print detections 196 | print ('the No.' + str(im_num) + ' image is completed:') 197 | print (' ' + str(len(detections)) + ' windows are detected!') 198 | im_num += 1 199 | 200 | 201 | 202 | def move_window(window, shape, window_scale): 203 | flag = True 204 | if (window[3] + (width_step)) < shape[1]: 205 | #window[1] = window[1] + (window_scale/2) 206 | window[1] = window[1] + width_step 207 | #window[3] = window[3] + (window_scale/2) 208 | window[3] = window[3] + width_step 209 | else: 210 | window[1] = 0 211 | window[3] = window_scale 212 | if (window[2]+ (height_step)) < shape[0]: 213 | window[0] = window[0] + height_step 214 | #window[0] = window[0] + (window_scale/2) 215 | window[2] = window[2] + height_step 216 | # window[2] = window[2] + (window_scale/2) 217 | else: 218 | flag = False 219 | 220 | return window, flag 221 | 222 | 223 | def draw_rectangle(detectedList, image): 224 | # read the image 225 | im = cv2.imread(image) 226 | if not len(detectedList) == 0: 227 | # draw the rectangle 228 | for window in detectedList: 229 | cv2.rectangle(im, (window[1], window[2]), (window[3], window[0]), (0,0,255), 5) 230 | # save the image 231 | cv2.imwrite(save_Path + '/' + image.split('/')[len(image.split('/'))-1], im) 232 | 233 | 234 | def merge_rectangle(window1, window2): 235 | isOverlap = False 236 | result = copy.copy(window2) 237 | # find the overlap area 238 | if not ((window1[1] > window2[3]) | (window2[1] > window1[3]) | (window1[0] > window2[2]) | (window2[0] > window1[2])): 239 | for i in range(4): 240 | if window1[i] > window2[i]: 241 | result[i] = window1[i] 242 | else: 243 | result[i] = window2[i] 244 | 245 | # compute the area of rectangles 246 | overlapArea = float((result[2] - result[0]) * (result[3] - result[1])) 247 | Area1 = float((window1[2] - window1[0]) * (window1[3] - window1[1])) 248 | Area2 = float((window2[2] - window2[0]) * (window2[3] - window2[1])) 249 | 250 | # select the window 251 | if ((overlapArea/Area1) > areaThreshold) | ((overlapArea/Area2) > areaThreshold): 252 | if ((window1[3]-window1[1]) * (window1[2]-window1[0]) > (window2[3]-window2[1]) * (window2[2]-window2[0])): 253 | for j in range(4): 254 | result[j] = copy.copy(window1[j]) 255 | else: 256 | for j in range(4): 257 | result[j] = copy.copy(window2[j]) 258 | isOverlap = True 259 | 260 | return isOverlap, result 261 | 262 | 263 | 264 | if __name__ == '__main__': 265 | main(sys.argv) 266 | -------------------------------------------------------------------------------- /leaf_full.prototxt: -------------------------------------------------------------------------------- 1 | name: "CIFAR10_full_deploy" 2 | # N.B. input image must be in CIFAR-10 format 3 | # as described at http://www.cs.toronto.edu/~kriz/cifar.html 4 | input: "data" 5 | input_shape { 6 | dim: 1 7 | dim: 3 8 | dim: 32 9 | dim: 32 10 | } 11 | layer { 12 | name: "conv1" 13 | type: "Convolution" 14 | bottom: "data" 15 | top: "conv1" 16 | param { 17 | lr_mult: 1 18 | } 19 | param { 20 | lr_mult: 2 21 | } 22 | convolution_param { 23 | num_output: 32 24 | pad: 2 25 | kernel_size: 5 26 | stride: 1 27 | } 28 | } 29 | layer { 30 | name: "pool1" 31 | type: "Pooling" 32 | bottom: "conv1" 33 | top: "pool1" 34 | pooling_param { 35 | pool: MAX 36 | kernel_size: 3 37 | stride: 2 38 | } 39 | } 40 | layer { 41 | name: "relu1" 42 | type: "ReLU" 43 | bottom: "pool1" 44 | top: "pool1" 45 | } 46 | layer { 47 | name: "norm1" 48 | type: "LRN" 49 | bottom: "pool1" 50 | top: "norm1" 51 | lrn_param { 52 | local_size: 3 53 | alpha: 5e-05 54 | beta: 0.75 55 | norm_region: WITHIN_CHANNEL 56 | } 57 | } 58 | layer { 59 | name: "conv2" 60 | type: "Convolution" 61 | bottom: "norm1" 62 | top: "conv2" 63 | param { 64 | lr_mult: 1 65 | } 66 | param { 67 | lr_mult: 2 68 | } 69 | convolution_param { 70 | num_output: 32 71 | pad: 2 72 | kernel_size: 5 73 | stride: 1 74 | } 75 | } 76 | layer { 77 | name: "relu2" 78 | type: "ReLU" 79 | bottom: "conv2" 80 | top: "conv2" 81 | } 82 | layer { 83 | name: "pool2" 84 | type: "Pooling" 85 | bottom: "conv2" 86 | top: "pool2" 87 | pooling_param { 88 | pool: AVE 89 | kernel_size: 3 90 | stride: 2 91 | } 92 | } 93 | layer { 94 | name: "norm2" 95 | type: "LRN" 96 | bottom: "pool2" 97 | top: "norm2" 98 | lrn_param { 99 | local_size: 3 100 | alpha: 5e-05 101 | beta: 0.75 102 | norm_region: WITHIN_CHANNEL 103 | } 104 | } 105 | layer { 106 | name: "conv3" 107 | type: "Convolution" 108 | bottom: "norm2" 109 | top: "conv3" 110 | convolution_param { 111 | num_output: 64 112 | pad: 2 113 | kernel_size: 5 114 | stride: 1 115 | } 116 | } 117 | layer { 118 | name: "relu3" 119 | type: "ReLU" 120 | bottom: "conv3" 121 | top: "conv3" 122 | } 123 | layer { 124 | name: "pool3" 125 | type: "Pooling" 126 | bottom: "conv3" 127 | top: "pool3" 128 | pooling_param { 129 | pool: AVE 130 | kernel_size: 3 131 | stride: 2 132 | } 133 | } 134 | layer { 135 | name: "ip1" 136 | type: "InnerProduct" 137 | bottom: "pool3" 138 | top: "ip1" 139 | param { 140 | lr_mult: 1 141 | decay_mult: 250 142 | } 143 | param { 144 | lr_mult: 2 145 | decay_mult: 0 146 | } 147 | inner_product_param { 148 | num_output: 2 149 | } 150 | } 151 | layer { 152 | name: "prob" 153 | type: "Softmax" 154 | bottom: "ip1" 155 | top: "prob" 156 | } 157 | -------------------------------------------------------------------------------- /leaf_full_iter_50000.caffemodel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GumpCode/leaf/c27e331fa158bf9ce6d9bb9dbf28e667a6c860f3/leaf_full_iter_50000.caffemodel -------------------------------------------------------------------------------- /leaf_full_iter_50000.solverstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GumpCode/leaf/c27e331fa158bf9ce6d9bb9dbf28e667a6c860f3/leaf_full_iter_50000.solverstate -------------------------------------------------------------------------------- /leaf_full_solver.prototxt: -------------------------------------------------------------------------------- 1 | # reduce learning rate after 120 epochs (60000 iters) by factor 0f 10 2 | # then another factor of 10 after 10 more epochs (5000 iters) 3 | 4 | # The train/test net protocol buffer definition 5 | net: "/home/ganlinhao/DeepLearning/caffe/examples/leaf/leaf_full_train_test.prototxt" 6 | # test_iter specifies how many forward passes the test should carry out. 7 | # In the case of CIFAR10, we have test batch size 100 and 100 test iterations, 8 | # covering the full 10,000 testing images. 9 | test_iter: 100 10 | # Carry out testing every 1000 training iterations. 11 | test_interval: 1000 12 | # The base learning rate, momentum and the weight decay of the network. 13 | base_lr: 0.001 14 | momentum: 0.9 15 | weight_decay: 0.004 16 | # The learning rate policy 17 | lr_policy: "fixed" 18 | # Display every 200 iterations 19 | display: 1000 20 | # The maximum number of iterations 21 | max_iter: 50000 22 | # snapshot intermediate results 23 | snapshot: 10000 24 | snapshot_format: BINARYPROTO 25 | snapshot_prefix: "/home/ganlinhao/DeepLearning/caffe/examples/leaf/leaf_full" 26 | # solver mode: CPU or GPU 27 | solver_mode: GPU 28 | -------------------------------------------------------------------------------- /leaf_full_train_test.prototxt: -------------------------------------------------------------------------------- 1 | name: "CIFAR10_full" 2 | layer { 3 | name: "cifar" 4 | type: "Data" 5 | top: "data" 6 | top: "label" 7 | include { 8 | phase: TRAIN 9 | } 10 | transform_param { 11 | mean_file: "/home/ganlinhao/DeepLearning/caffe/examples/leaf/leaf_mean.binaryproto" 12 | } 13 | data_param { 14 | source: "/home/ganlinhao/DeepLearning/caffe/examples/leaf/leaf_train_lmdb" 15 | batch_size: 90 16 | backend: LMDB 17 | } 18 | } 19 | layer { 20 | name: "cifar" 21 | type: "Data" 22 | top: "data" 23 | top: "label" 24 | include { 25 | phase: TEST 26 | } 27 | transform_param { 28 | mean_file: "/home/ganlinhao/DeepLearning/caffe/examples/leaf/leaf_mean.binaryproto" 29 | } 30 | data_param { 31 | source: "/home/ganlinhao/DeepLearning/caffe/examples/leaf/leaf_val_lmdb" 32 | batch_size: 40 33 | backend: LMDB 34 | } 35 | } 36 | layer { 37 | name: "conv1" 38 | type: "Convolution" 39 | bottom: "data" 40 | top: "conv1" 41 | param { 42 | lr_mult: 1 43 | } 44 | param { 45 | lr_mult: 2 46 | } 47 | convolution_param { 48 | num_output: 32 49 | pad: 2 50 | kernel_size: 5 51 | stride: 1 52 | weight_filler { 53 | type: "gaussian" 54 | std: 0.0001 55 | } 56 | bias_filler { 57 | type: "constant" 58 | } 59 | } 60 | } 61 | layer { 62 | name: "pool1" 63 | type: "Pooling" 64 | bottom: "conv1" 65 | top: "pool1" 66 | pooling_param { 67 | pool: MAX 68 | kernel_size: 3 69 | stride: 2 70 | } 71 | } 72 | layer { 73 | name: "relu1" 74 | type: "ReLU" 75 | bottom: "pool1" 76 | top: "pool1" 77 | } 78 | layer { 79 | name: "norm1" 80 | type: "LRN" 81 | bottom: "pool1" 82 | top: "norm1" 83 | lrn_param { 84 | local_size: 3 85 | alpha: 5e-05 86 | beta: 0.75 87 | norm_region: WITHIN_CHANNEL 88 | } 89 | } 90 | layer { 91 | name: "conv2" 92 | type: "Convolution" 93 | bottom: "norm1" 94 | top: "conv2" 95 | param { 96 | lr_mult: 1 97 | } 98 | param { 99 | lr_mult: 2 100 | } 101 | convolution_param { 102 | num_output: 32 103 | pad: 2 104 | kernel_size: 5 105 | stride: 1 106 | weight_filler { 107 | type: "gaussian" 108 | std: 0.01 109 | } 110 | bias_filler { 111 | type: "constant" 112 | } 113 | } 114 | } 115 | layer { 116 | name: "relu2" 117 | type: "ReLU" 118 | bottom: "conv2" 119 | top: "conv2" 120 | } 121 | layer { 122 | name: "pool2" 123 | type: "Pooling" 124 | bottom: "conv2" 125 | top: "pool2" 126 | pooling_param { 127 | pool: AVE 128 | kernel_size: 3 129 | stride: 2 130 | } 131 | } 132 | layer { 133 | name: "norm2" 134 | type: "LRN" 135 | bottom: "pool2" 136 | top: "norm2" 137 | lrn_param { 138 | local_size: 3 139 | alpha: 5e-05 140 | beta: 0.75 141 | norm_region: WITHIN_CHANNEL 142 | } 143 | } 144 | layer { 145 | name: "conv3" 146 | type: "Convolution" 147 | bottom: "norm2" 148 | top: "conv3" 149 | convolution_param { 150 | num_output: 64 151 | pad: 2 152 | kernel_size: 5 153 | stride: 1 154 | weight_filler { 155 | type: "gaussian" 156 | std: 0.01 157 | } 158 | bias_filler { 159 | type: "constant" 160 | } 161 | } 162 | } 163 | layer { 164 | name: "relu3" 165 | type: "ReLU" 166 | bottom: "conv3" 167 | top: "conv3" 168 | } 169 | layer { 170 | name: "pool3" 171 | type: "Pooling" 172 | bottom: "conv3" 173 | top: "pool3" 174 | pooling_param { 175 | pool: AVE 176 | kernel_size: 3 177 | stride: 2 178 | } 179 | } 180 | layer { 181 | name: "ip1" 182 | type: "InnerProduct" 183 | bottom: "pool3" 184 | top: "ip1" 185 | param { 186 | lr_mult: 1 187 | decay_mult: 250 188 | } 189 | param { 190 | lr_mult: 2 191 | decay_mult: 0 192 | } 193 | inner_product_param { 194 | num_output: 2 195 | weight_filler { 196 | type: "gaussian" 197 | std: 0.01 198 | } 199 | bias_filler { 200 | type: "constant" 201 | } 202 | } 203 | } 204 | layer { 205 | name: "accuracy" 206 | type: "Accuracy" 207 | bottom: "ip1" 208 | bottom: "label" 209 | top: "accuracy" 210 | include { 211 | phase: TEST 212 | } 213 | } 214 | layer { 215 | name: "loss" 216 | type: "SoftmaxWithLoss" 217 | bottom: "ip1" 218 | bottom: "label" 219 | top: "loss" 220 | } 221 | -------------------------------------------------------------------------------- /preProcessing/convert_cifar_data.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // This script converts the CIFAR dataset to the leveldb format used 3 | // by caffe to perform classification. 4 | // Usage: 5 | // convert_cifar_data input_folder output_db_file 6 | // The CIFAR dataset could be downloaded at 7 | // http://www.cs.toronto.edu/~kriz/cifar.html 8 | 9 | #include // NOLINT(readability/streams) 10 | #include 11 | 12 | #include "boost/scoped_ptr.hpp" 13 | #include "glog/logging.h" 14 | #include "google/protobuf/text_format.h" 15 | #include "stdint.h" 16 | 17 | #include "caffe/proto/caffe.pb.h" 18 | #include "caffe/util/db.hpp" 19 | 20 | using caffe::Datum; 21 | using boost::scoped_ptr; 22 | using std::string; 23 | namespace db = caffe::db; 24 | 25 | const int kCIFARSize = 32; 26 | const int kCIFARImageNBytes = 3072; 27 | const int kCIFARBatchSize = 10000; 28 | const int kCIFARTrainBatches = 5; 29 | 30 | void read_image(std::ifstream* file, int* label, char* buffer) { 31 | char label_char; 32 | file->read(&label_char, 1); 33 | *label = label_char; 34 | file->read(buffer, kCIFARImageNBytes); 35 | return; 36 | } 37 | 38 | void convert_dataset(const string& input_folder, const string& output_folder, 39 | const string& db_type) { 40 | scoped_ptr train_db(db::GetDB(db_type)); 41 | train_db->Open(output_folder + "/cifar10_train_" + db_type, db::NEW); 42 | scoped_ptr txn(train_db->NewTransaction()); 43 | // Data buffer 44 | int label; 45 | char str_buffer[kCIFARImageNBytes]; 46 | Datum datum; 47 | datum.set_channels(3); 48 | datum.set_height(kCIFARSize); 49 | datum.set_width(kCIFARSize); 50 | 51 | LOG(INFO) << "Writing Training data"; 52 | for (int fileid = 0; fileid < kCIFARTrainBatches; ++fileid) { 53 | // Open files 54 | LOG(INFO) << "Training Batch " << fileid + 1; 55 | snprintf(str_buffer, kCIFARImageNBytes, "/data_batch_%d.bin", fileid + 1); 56 | std::ifstream data_file((input_folder + str_buffer).c_str(), 57 | std::ios::in | std::ios::binary); 58 | CHECK(data_file) << "Unable to open train file #" << fileid + 1; 59 | for (int itemid = 0; itemid < kCIFARBatchSize; ++itemid) { 60 | read_image(&data_file, &label, str_buffer); 61 | datum.set_label(label); 62 | datum.set_data(str_buffer, kCIFARImageNBytes); 63 | int length = snprintf(str_buffer, kCIFARImageNBytes, "%05d", 64 | fileid * kCIFARBatchSize + itemid); 65 | string out; 66 | CHECK(datum.SerializeToString(&out)); 67 | txn->Put(string(str_buffer, length), out); 68 | } 69 | } 70 | txn->Commit(); 71 | train_db->Close(); 72 | 73 | LOG(INFO) << "Writing Testing data"; 74 | scoped_ptr test_db(db::GetDB(db_type)); 75 | test_db->Open(output_folder + "/cifar10_test_" + db_type, db::NEW); 76 | txn.reset(test_db->NewTransaction()); 77 | // Open files 78 | std::ifstream data_file((input_folder + "/test_batch.bin").c_str(), 79 | std::ios::in | std::ios::binary); 80 | CHECK(data_file) << "Unable to open test file."; 81 | for (int itemid = 0; itemid < kCIFARBatchSize; ++itemid) { 82 | read_image(&data_file, &label, str_buffer); 83 | datum.set_label(label); 84 | datum.set_data(str_buffer, kCIFARImageNBytes); 85 | int length = snprintf(str_buffer, kCIFARImageNBytes, "%05d", itemid); 86 | string out; 87 | CHECK(datum.SerializeToString(&out)); 88 | txn->Put(string(str_buffer, length), out); 89 | } 90 | txn->Commit(); 91 | test_db->Close(); 92 | } 93 | 94 | int main(int argc, char** argv) { 95 | if (argc != 4) { 96 | printf("This script converts the CIFAR dataset to the leveldb format used\n" 97 | "by caffe to perform classification.\n" 98 | "Usage:\n" 99 | " convert_cifar_data input_folder output_folder db_type\n" 100 | "Where the input folder should contain the binary batch files.\n" 101 | "The CIFAR dataset could be downloaded at\n" 102 | " http://www.cs.toronto.edu/~kriz/cifar.html\n" 103 | "You should gunzip them after downloading.\n"); 104 | } else { 105 | google::InitGoogleLogging(argv[0]); 106 | convert_dataset(string(argv[1]), string(argv[2]), string(argv[3])); 107 | } 108 | return 0; 109 | } 110 | -------------------------------------------------------------------------------- /preProcessing/convert_protomean.py: -------------------------------------------------------------------------------- 1 | import caffe 2 | import numpy as np 3 | import sys 4 | 5 | if len(sys.argv) != 3: 6 | print "Usage: python convert_protomean.py proto.mean out.npy" 7 | sys.exit() 8 | 9 | blob = caffe.proto.caffe_pb2.BlobProto() 10 | data = open( sys.argv[1] , 'rb' ).read() 11 | blob.ParseFromString(data) 12 | arr = np.array( caffe.io.blobproto_to_array(blob) ) 13 | out = arr[0] 14 | np.save( sys.argv[2] , out ) 15 | -------------------------------------------------------------------------------- /preProcessing/create_leaf.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # Create the imagenet lmdb inputs 3 | # N.B. set the path to the imagenet train + val data dirs 4 | MyHome=~/DeepLearning/caffe 5 | DATA=$MyHome/examples/leaf 6 | TOOLS=$MyHome/build/tools 7 | 8 | TRAIN_DATA_ROOT=$MyHome/examples/leaf/leaf_train_data/ 9 | VAL_DATA_ROOT=$MyHome/examples/leaf/leaf_val_data/ 10 | EXAMPLE=$DATA 11 | # Set RESIZE=true to resize the images to 256x256. Leave as false if images have 12 | # already been resized using another tool. 13 | RESIZE=true 14 | if $RESIZE; then 15 | RESIZE_HEIGHT=32 16 | RESIZE_WIDTH=32 17 | else 18 | RESIZE_HEIGHT=0 19 | RESIZE_WIDTH=0 20 | fi 21 | 22 | if [ ! -d "$TRAIN_DATA_ROOT" ]; then 23 | echo "Error: TRAIN_DATA_ROOT is not a path to a directory: $TRAIN_DATA_ROOT" 24 | echo "Set the TRAIN_DATA_ROOT variable in create_imagenet.sh to the path" \ 25 | "where the ImageNet training data is stored." 26 | exit 1 27 | fi 28 | 29 | if [ ! -d "$VAL_DATA_ROOT" ]; then 30 | echo "Error: VAL_DATA_ROOT is not a path to a directory: $VAL_DATA_ROOT" 31 | echo "Set the VAL_DATA_ROOT variable in create_imagenet.sh to the path" \ 32 | "where the ImageNet validation data is stored." 33 | exit 1 34 | fi 35 | 36 | echo "$EXAMPLE/leaf_train_lmdb" 37 | 38 | 39 | if [ -d $EXAMPLE/leaf_train_lmdb ]; then 40 | rm -rf $EXAMPLE/leaf_train_lmdb 41 | echo "leaf_train_lmdb is removed!" 42 | fi 43 | 44 | if [ -d $EXAMPLE/leaf_val_lmdb ]; then 45 | rm -rf $EXAMPLE/leaf_val_lmdb 46 | echo "leaf_val_lmdb is removed!" 47 | fi 48 | 49 | echo "Creating train lmdb..." 50 | GLOG_logtostderr=1 $TOOLS/convert_imageset \ 51 | --resize_height=$RESIZE_HEIGHT \ 52 | --resize_width=$RESIZE_WIDTH \ 53 | --shuffle \ 54 | $TRAIN_DATA_ROOT \ 55 | $DATA/train_Label.txt \ 56 | $EXAMPLE/leaf_train_lmdb 57 | 58 | echo "Creating val lmdb..." 59 | 60 | GLOG_logtostderr=1 $TOOLS/convert_imageset \ 61 | --resize_height=$RESIZE_HEIGHT \ 62 | --resize_width=$RESIZE_WIDTH \ 63 | --shuffle \ 64 | $VAL_DATA_ROOT \ 65 | $DATA/val_Label.txt \ 66 | $EXAMPLE/leaf_val_lmdb 67 | -------------------------------------------------------------------------------- /preProcessing/make_leaf_mean.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # Compute the mean image from the imagenet training lmdb 3 | # N.B. this is available in data/ilsvrc12 4 | 5 | MyHome=~/DeepLearning/caffe 6 | EXAMPLE=$MyHome/examples/leaf 7 | DATA=$MyHome/examples/leaf 8 | TOOLS=$MyHome/build/tools 9 | 10 | echo "starting making binaryproto..." 11 | 12 | if [ -f $DATA/leaf_mean.binaryproto ]; then 13 | rm $DATA/leaf_mean.binaryproto 14 | echo "leaf_mean.binaryproto is removed!" 15 | fi 16 | 17 | $TOOLS/compute_image_mean $EXAMPLE/leaf_train_lmdb \ 18 | $DATA/leaf_mean.binaryproto 19 | 20 | echo "making binaryproto is Done." 21 | -------------------------------------------------------------------------------- /preProcessing/multiDataProcessing.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import random 4 | import shutil 5 | import copy 6 | from PIL import Image 7 | 8 | def main(argv): 9 | classList = os.listdir(argv[1]) 10 | classNum = len(classList) 11 | trainList = [] 12 | valList = [] 13 | 14 | # make train&val dir 15 | os.mkdir(argv[2]) 16 | os.mkdir(argv[3]) 17 | 18 | #rename option 19 | for item in classList: 20 | count = 0 21 | imageDir = argv[1] + '/' + item 22 | imageList = os.listdir(imageDir) 23 | # shuffle the image list 24 | random.shuffle(imageList) 25 | # divide data into training and valuating 26 | for im in imageList: 27 | src = imageDir + '/' + im 28 | #image_name = item + '_' + im 29 | image_name = item + '_' + str(count) + '.jpg' 30 | # training data 31 | trainNum = int(float(argv[6]) * len(imageList)) 32 | if count < trainNum: 33 | dst = argv[2] + '/' + image_name 34 | shutil.copy(src, dst) 35 | train = [image_name, item] 36 | trainList.append(copy.copy(train)) 37 | count += 1 38 | 39 | # valuating data 40 | else: 41 | dst = argv[3] + '/' + image_name 42 | shutil.copy(src, dst) 43 | val = [image_name, item] 44 | valList.append(copy.copy(val)) 45 | count += 1 46 | 47 | # make label txt 48 | with open(argv[4], 'w') as file: 49 | for item in trainList: 50 | file.write(item[0] + ' ' + item[1] + '\n') 51 | with open(argv[5], 'w') as file: 52 | for item in valList: 53 | file.write(item[0] + ' ' + item[1] + '\n') 54 | 55 | if __name__ == '__main__': 56 | main(sys.argv) 57 | -------------------------------------------------------------------------------- /preProcessing/multipleLeaf.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | #processing the data of training 3 | 4 | HomeDir=~/DeepLearning/caffe/examples/mutipleLeaf 5 | TOOLS=~/DeepLearning/caffe/build/tools 6 | DataDir=~/DeepLearning/DataProcessing/mixSamples 7 | TrainingDir=$HomeDir/leaf_train_data 8 | ValuatingDir=$HomeDir/leaf_val_data 9 | LabelOfPos=$HomeDir/train_Label.txt 10 | LabelOfNeg=$HomeDir/val_Label.txt 11 | trainingRate=0.66 12 | 13 | echo "Starting Pre-processing the training data..." 14 | 15 | if [ -d $HomeDir/leaf_train_data ]; then 16 | rm -rf $HomeDir/leaf_train_data 17 | echo "Old leaf_train_data is removed!" 18 | fi 19 | 20 | if [ -d $HomeDir/leaf_val_data ]; then 21 | rm -rf $HomeDir/leaf_val_data 22 | echo "Old leaf_val_data is removed!" 23 | fi 24 | 25 | python DataProcessing.py $DataDir \ 26 | $TrainingDir $ValuatingDir \ 27 | $LabelOfPos $LabelOfNeg \ 28 | $trainingRate 29 | echo "Pre-processing is finished!" 30 | 31 | echo "Starting creating the input data..." 32 | sh $HomeDir/create_leaf.sh 33 | echo "Creating data is finished!" 34 | 35 | echo "Starting making binaryproto..." 36 | if [ -f $HomeDir/leaf_mean.binaryproto ]; then 37 | rm $HomeDir/leaf_mean.binaryproto 38 | echo "old leaf_mean.binaryproto is removed!" 39 | fi 40 | 41 | $TOOLS/compute_image_mean $HomeDir/leaf_train_lmdb \ 42 | $HomeDir/leaf_mean.binaryproto 43 | echo "making binaryproto is finished!" 44 | 45 | echo "Starting making data of npy..." 46 | if [ -f $HomeDir/leaf_mean.npy ]; then 47 | rm $HomeDir/leaf_mean.npy 48 | fi 49 | 50 | python $HomeDir/convert_protomean.py $HomeDir/leaf_mean.binaryproto \ 51 | $HomeDir/leaf_mean.npy 52 | 53 | if [ -f $HomeDir/leaf_mean.npy ]; then 54 | echo "leaf_mean.npy is finished!" 55 | fi 56 | 57 | echo "All completed!" 58 | -------------------------------------------------------------------------------- /preProcessing/resize.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import os 3 | import sys 4 | 5 | " 6 | input: dim dim srcDir distDir 7 | " 8 | 9 | def main(argv): 10 | list = os.listdir(argv[3]) 11 | 12 | if not os.path.exists(argv[4]): 13 | os.mkdir(argv[4]) 14 | 15 | num = 0 16 | for items in list: 17 | im = cv2.imread(argv[3] + '/' + items) 18 | src = cv2.resize(im, (int(argv[1]), int(argv[2]))) 19 | cv2.imwrite(argv[4] + '/' + items, src) 20 | num = num + 1 21 | 22 | print(str(num) + ' pictures were processed!') 23 | 24 | if __name__ == '__main__': 25 | main(sys.argv) 26 | -------------------------------------------------------------------------------- /train_full.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | TOOLS=~/DeepLearning/caffe/build/tools 4 | 5 | $TOOLS/caffe train \ 6 | --solver=/home/ganlinhao/DeepLearning/caffe/examples/leaf/leaf_full_solver.prototxt 7 | 8 | 9 | 10 | # reduce learning rate by factor of 10 11 | #$TOOLS/caffe train \ 12 | # --solver=examples/cifar10/cifar10_full_solver_lr1.prototxt \ 13 | # --snapshot=examples/cifar10/cifar10_full_iter_60000.solverstate.h5 14 | 15 | # reduce learning rate by factor of 10 16 | #$TOOLS/caffe train \ 17 | # --solver=examples/cifar10/cifar10_full_solver_lr2.prototxt \ 18 | # --snapshot=examples/cifar10/cifar10_full_iter_65000.solverstate.h5 19 | --------------------------------------------------------------------------------