From bd06e66e865d823304cf3ae27b0cd901f38261b8 Mon Sep 17 00:00:00 2001 From: dominik dienlin Date: Mon, 5 Aug 2019 13:25:31 +0200 Subject: [PATCH 01/18] add python3 support (converted using 2to3) --- .../cocoapi/PythonAPI/pycocotools/coco.py | 24 +++++++++---------- .../cocoapi/PythonAPI/pycocotools/cocoeval.py | 12 +++++----- eval_city/eval_script/coco.py | 20 ++++++++-------- eval_city/eval_script/eval_MR_multisetup.py | 4 ++-- eval_city/eval_script/eval_demo.py | 2 +- generate_cache_caltech.py | 8 +++---- generate_cache_city.py | 8 +++---- generate_cache_wider.py | 8 +++---- keras_csp/bbox_process.py | 6 ++--- keras_csp/data_augment.py | 2 +- keras_csp/data_generators.py | 12 +++++----- keras_csp/mobilenet.py | 6 ++--- keras_csp/nms_wrapper.py | 4 ++-- keras_csp/parallel_model.py | 8 +++---- keras_csp/resnet50.py | 6 ++--- keras_csp/utilsfunc.py | 2 +- test_caltech.py | 14 +++++------ test_city.py | 14 +++++------ test_wider_ms.py | 14 +++++------ train_caltech.py | 24 +++++++++---------- train_city.py | 22 ++++++++--------- train_wider.py | 22 ++++++++--------- 22 files changed, 121 insertions(+), 121 deletions(-) diff --git a/eval_city/cocoapi/PythonAPI/pycocotools/coco.py b/eval_city/cocoapi/PythonAPI/pycocotools/coco.py index dc9972b..7b8b37e 100755 --- a/eval_city/cocoapi/PythonAPI/pycocotools/coco.py +++ b/eval_city/cocoapi/PythonAPI/pycocotools/coco.py @@ -58,7 +58,7 @@ import sys PYTHON_VERSION = sys.version_info[0] if PYTHON_VERSION == 2: - from urllib import urlretrieve + from urllib.request import urlretrieve elif PYTHON_VERSION == 3: from urllib.request import urlretrieve @@ -83,7 +83,7 @@ def __init__(self, annotation_file=None): tic = time.time() dataset = json.load(open(annotation_file, 'r')) assert type(dataset)==dict, 'annotation file format {} not supported'.format(type(dataset)) - print('Done (t={:0.2f}s)'.format(time.time()- tic)) + print(('Done (t={:0.2f}s)'.format(time.time()- tic))) self.dataset = dataset self.createIndex() @@ -123,8 +123,8 @@ def info(self): Print information about the annotation file. :return: """ - for key, value in self.dataset['info'].items(): - print('{}: {}'.format(key, value)) + for key, value in list(self.dataset['info'].items()): + print(('{}: {}'.format(key, value))) def getAnnIds(self, imgIds=[], catIds=[], areaRng=[], iscrowd=None): """ @@ -187,7 +187,7 @@ def getImgIds(self, imgIds=[], catIds=[]): catIds = catIds if _isArrayLike(catIds) else [catIds] if len(imgIds) == len(catIds) == 0: - ids = self.imgs.keys() + ids = list(self.imgs.keys()) else: ids = set(imgIds) for i, catId in enumerate(catIds): @@ -292,7 +292,7 @@ def showAnns(self, anns): ax.add_collection(p) elif datasetType == 'captions': for ann in anns: - print(ann['caption']) + print((ann['caption'])) def loadRes(self, resFile): """ @@ -305,7 +305,7 @@ def loadRes(self, resFile): print('Loading and preparing results...') tic = time.time() - if type(resFile) == str or type(resFile) == unicode: + if type(resFile) == str or type(resFile) == str: anns = json.load(open(resFile)) elif type(resFile) == np.ndarray: anns = self.loadNumpyAnnotations(resFile) @@ -349,7 +349,7 @@ def loadRes(self, resFile): ann['area'] = (x1-x0)*(y1-y0) ann['id'] = id + 1 ann['bbox'] = [x0,y0,x1-x0,y1-y0] - print('DONE (t={:0.2f}s)'.format(time.time()- tic)) + print(('DONE (t={:0.2f}s)'.format(time.time()- tic))) res.dataset['annotations'] = anns res.createIndex() @@ -366,7 +366,7 @@ def download(self, tarDir = None, imgIds = [] ): print('Please specify target directory') return -1 if len(imgIds) == 0: - imgs = self.imgs.values() + imgs = list(self.imgs.values()) else: imgs = self.loadImgs(imgIds) N = len(imgs) @@ -377,7 +377,7 @@ def download(self, tarDir = None, imgIds = [] ): fname = os.path.join(tarDir, img['file_name']) if not os.path.exists(fname): urlretrieve(img['coco_url'], fname) - print('downloaded {}/{} images (t={:0.1f}s)'.format(i, N, time.time()- tic)) + print(('downloaded {}/{} images (t={:0.1f}s)'.format(i, N, time.time()- tic))) def loadNumpyAnnotations(self, data): """ @@ -387,13 +387,13 @@ def loadNumpyAnnotations(self, data): """ print('Converting ndarray to lists...') assert(type(data) == np.ndarray) - print(data.shape) + print((data.shape)) assert(data.shape[1] == 7) N = data.shape[0] ann = [] for i in range(N): if i % 1000000 == 0: - print('{}/{}'.format(i,N)) + print(('{}/{}'.format(i,N))) ann += [{ 'image_id' : int(data[i, 0]), 'bbox' : [ data[i, 1], data[i, 2], data[i, 3], data[i, 4] ], diff --git a/eval_city/cocoapi/PythonAPI/pycocotools/cocoeval.py b/eval_city/cocoapi/PythonAPI/pycocotools/cocoeval.py index 7a4b4ad..84ab931 100755 --- a/eval_city/cocoapi/PythonAPI/pycocotools/cocoeval.py +++ b/eval_city/cocoapi/PythonAPI/pycocotools/cocoeval.py @@ -130,8 +130,8 @@ def evaluate(self): # add backward compatibility if useSegm is specified in params if not p.useSegm is None: p.iouType = 'segm' if p.useSegm == 1 else 'bbox' - print('useSegm (deprecated) is not None. Running {} evaluation'.format(p.iouType)) - print('Evaluate annotation type *{}*'.format(p.iouType)) + print(('useSegm (deprecated) is not None. Running {} evaluation'.format(p.iouType))) + print(('Evaluate annotation type *{}*'.format(p.iouType))) p.imgIds = list(np.unique(p.imgIds)) if p.useCats: p.catIds = list(np.unique(p.catIds)) @@ -159,7 +159,7 @@ def evaluate(self): ] self._paramsEval = copy.deepcopy(self.params) toc = time.time() - print('DONE (t={:0.2f}s).'.format(toc-tic)) + print(('DONE (t={:0.2f}s).'.format(toc-tic))) def computeIoU(self, imgId, catId): p = self.params @@ -346,7 +346,7 @@ def accumulate(self, p = None): # get inds to evaluate k_list = [n for n, k in enumerate(p.catIds) if k in setK] m_list = [m for n, m in enumerate(p.maxDets) if m in setM] - a_list = [n for n, a in enumerate(map(lambda x: tuple(x), p.areaRng)) if a in setA] + a_list = [n for n, a in enumerate([tuple(x) for x in p.areaRng]) if a in setA] i_list = [n for n, i in enumerate(p.imgIds) if i in setI] I0 = len(_pe.imgIds) A0 = len(_pe.areaRng) @@ -418,7 +418,7 @@ def accumulate(self, p = None): 'scores': scores, } toc = time.time() - print('DONE (t={:0.2f}s).'.format( toc-tic)) + print(('DONE (t={:0.2f}s).'.format( toc-tic))) def summarize(self): ''' @@ -454,7 +454,7 @@ def _summarize( ap=1, iouThr=None, areaRng='all', maxDets=100 ): mean_s = -1 else: mean_s = np.mean(s[s>-1]) - print(iStr.format(titleStr, typeStr, iouStr, areaRng, maxDets, mean_s)) + print((iStr.format(titleStr, typeStr, iouStr, areaRng, maxDets, mean_s))) return mean_s def _summarizeDets(): stats = np.zeros((12,)) diff --git a/eval_city/eval_script/coco.py b/eval_city/eval_script/coco.py index f870138..576371a 100755 --- a/eval_city/eval_script/coco.py +++ b/eval_city/eval_script/coco.py @@ -58,7 +58,7 @@ import sys PYTHON_VERSION = sys.version_info[0] if PYTHON_VERSION == 2: - from urllib import urlretrieve + from urllib.request import urlretrieve elif PYTHON_VERSION == 3: from urllib.request import urlretrieve @@ -118,8 +118,8 @@ def info(self): Print information about the annotation file. :return: """ - for key, value in self.dataset['info'].items(): - print('{}: {}'.format(key, value)) + for key, value in list(self.dataset['info'].items()): + print(('{}: {}'.format(key, value))) def getAnnIds(self, imgIds=[], catIds=[], areaRng=[], iscrowd=None): """ @@ -182,7 +182,7 @@ def getImgIds(self, imgIds=[], catIds=[]): catIds = catIds if type(catIds) == list else [catIds] if len(imgIds) == len(catIds) == 0: - ids = self.imgs.keys() + ids = list(self.imgs.keys()) else: ids = set(imgIds) for i, catId in enumerate(catIds): @@ -287,7 +287,7 @@ def showAnns(self, anns): ax.add_collection(p) elif datasetType == 'captions': for ann in anns: - print(ann['caption']) + print((ann['caption'])) def loadRes(self, resFile): """ @@ -300,7 +300,7 @@ def loadRes(self, resFile): # print('Loading and preparing results...') tic = time.time() - if type(resFile) == str or type(resFile) == unicode: + if type(resFile) == str or type(resFile) == str: anns = json.load(open(resFile)) elif type(resFile) == np.ndarray: anns = self.loadNumpyAnnotations(resFile) @@ -364,7 +364,7 @@ def download(self, tarDir = None, imgIds = [] ): print('Please specify target directory') return -1 if len(imgIds) == 0: - imgs = self.imgs.values() + imgs = list(self.imgs.values()) else: imgs = self.loadImgs(imgIds) N = len(imgs) @@ -375,7 +375,7 @@ def download(self, tarDir = None, imgIds = [] ): fname = os.path.join(tarDir, img['file_name']) if not os.path.exists(fname): urlretrieve(img['coco_url'], fname) - print('downloaded {}/{} images (t={:0.1f}s)'.format(i, N, time.time()- tic)) + print(('downloaded {}/{} images (t={:0.1f}s)'.format(i, N, time.time()- tic))) def loadNumpyAnnotations(self, data): """ @@ -385,13 +385,13 @@ def loadNumpyAnnotations(self, data): """ print('Converting ndarray to lists...') assert(type(data) == np.ndarray) - print(data.shape) + print((data.shape)) assert(data.shape[1] == 7) N = data.shape[0] ann = [] for i in range(N): if i % 1000000 == 0: - print('{}/{}'.format(i,N)) + print(('{}/{}'.format(i,N))) ann += [{ 'image_id' : int(data[i, 0]), 'bbox' : [ data[i, 1], data[i, 2], data[i, 3], data[i, 4] ], diff --git a/eval_city/eval_script/eval_MR_multisetup.py b/eval_city/eval_script/eval_MR_multisetup.py index 1173b71..e16fc3d 100755 --- a/eval_city/eval_script/eval_MR_multisetup.py +++ b/eval_city/eval_script/eval_MR_multisetup.py @@ -122,7 +122,7 @@ def evaluate(self, id_setup): # add backward compatibility if useSegm is specified in params if not p.useSegm is None: p.iouType = 'segm' if p.useSegm == 1 else 'bbox' - print('useSegm (deprecated) is not None. Running {} evaluation'.format(p.iouType)) + print(('useSegm (deprecated) is not None. Running {} evaluation'.format(p.iouType))) # print('Evaluate annotation type *{}*'.format(p.iouType)) p.imgIds = list(np.unique(p.imgIds)) if p.useCats: @@ -446,7 +446,7 @@ def _summarize(iouThr=None, maxDets=100 ): mean_s = np.log(mrs[mrs<2]) mean_s = np.mean(mean_s) mean_s = np.exp(mean_s) - print(iStr.format(titleStr, typeStr,setupStr, iouStr, heightStr, occlStr, mean_s*100)) + print((iStr.format(titleStr, typeStr,setupStr, iouStr, heightStr, occlStr, mean_s*100))) # res_file.write(iStr.format(titleStr, typeStr,setupStr, iouStr, heightStr, occlStr, mean_s*100)) res_file.write(str(mean_s * 100)) res_file.write('\n') diff --git a/eval_city/eval_script/eval_demo.py b/eval_city/eval_script/eval_demo.py index b32ae63..7d7c6d5 100755 --- a/eval_city/eval_script/eval_demo.py +++ b/eval_city/eval_script/eval_demo.py @@ -8,7 +8,7 @@ annFile = '../val_gt.json' main_path = '../../output/valresults/city/h/off' for f in sorted(os.listdir(main_path)): - print f + print(f) # initialize COCO detections api dt_path = os.path.join(main_path, f) resFile = os.path.join(dt_path,'val_dt.json') diff --git a/generate_cache_caltech.py b/generate_cache_caltech.py index cad6ec8..30fb028 100755 --- a/generate_cache_caltech.py +++ b/generate_cache_caltech.py @@ -1,5 +1,5 @@ import os -import cPickle +import pickle import numpy as np import matplotlib.pyplot as plt @@ -53,11 +53,11 @@ else: image_data_gt.append(annotation) valid_count += 1 -print '{} images and {} valid images, {} valid gt and {} ignored gt'.format(len(files), valid_count, box_count, iggt_count) +print('{} images and {} valid images, {} valid gt and {} ignored gt'.format(len(files), valid_count, box_count, iggt_count)) if not os.path.exists(res_path_gt): with open(res_path_gt, 'wb') as fid: - cPickle.dump(image_data_gt, fid, cPickle.HIGHEST_PROTOCOL) + pickle.dump(image_data_gt, fid, pickle.HIGHEST_PROTOCOL) if not os.path.exists(res_path_nogt): with open(res_path_nogt, 'wb') as fid: - cPickle.dump(image_data_nogt, fid, cPickle.HIGHEST_PROTOCOL) \ No newline at end of file + pickle.dump(image_data_nogt, fid, pickle.HIGHEST_PROTOCOL) \ No newline at end of file diff --git a/generate_cache_city.py b/generate_cache_city.py index 8172b6e..7e21f39 100755 --- a/generate_cache_city.py +++ b/generate_cache_city.py @@ -1,7 +1,7 @@ -from __future__ import division + import os import cv2 -import cPickle +import pickle import numpy as np from scipy import io as scio import time @@ -64,5 +64,5 @@ image_data.append(annotation) if not os.path.exists(res_path): with open(res_path, 'wb') as fid: - cPickle.dump(image_data, fid, cPickle.HIGHEST_PROTOCOL) - print '{} has {} images and {} valid images, {} valid gt and {} ignored gt'.format(type, len(annos[index][0]), valid_count, box_count, iggt_count) + pickle.dump(image_data, fid, pickle.HIGHEST_PROTOCOL) + print('{} has {} images and {} valid images, {} valid gt and {} ignored gt'.format(type, len(annos[index][0]), valid_count, box_count, iggt_count)) diff --git a/generate_cache_wider.py b/generate_cache_wider.py index cc37f8b..a76c940 100755 --- a/generate_cache_wider.py +++ b/generate_cache_wider.py @@ -1,6 +1,6 @@ import os import cv2 -import cPickle +import pickle import numpy as np import matplotlib.pyplot as plt @@ -24,7 +24,7 @@ filename = lines[index].strip() img_count += 1 if img_count%1000 == 0: - print img_count + print(img_count) num_obj = int(lines[index+1]) filepath = os.path.join(img_path, filename) img = cv2.imread(filepath) @@ -48,6 +48,6 @@ image_data.append(annotation) index += (2+num_obj) -print '{} images and {} valid images and {} boxes'.format(img_count, valid_count,box_count) +print('{} images and {} valid images and {} boxes'.format(img_count, valid_count,box_count)) with open(res_path, 'wb') as fid: - cPickle.dump(image_data, fid, cPickle.HIGHEST_PROTOCOL) \ No newline at end of file + pickle.dump(image_data, fid, pickle.HIGHEST_PROTOCOL) \ No newline at end of file diff --git a/keras_csp/bbox_process.py b/keras_csp/bbox_process.py index 97a8107..d3bd29b 100644 --- a/keras_csp/bbox_process.py +++ b/keras_csp/bbox_process.py @@ -1,6 +1,6 @@ -from __future__ import division + import numpy as np -from nms_wrapper import nms +from .nms_wrapper import nms def parse_det(Y, C, score=0.1, down=4,scale='h'): seman = Y[0][0, :, :, 0] @@ -103,7 +103,7 @@ def parse_wider_offset(Y, C, score=0.1,down=4,nmsthre=0.5): boxs = np.asarray(boxs, dtype=np.float32) #keep = nms(boxs, nmsthre, usegpu=False, gpu_id=0) #boxs = boxs[keep, :] - boxs = soft_bbox_vote(boxs,thre=nmsthre) + boxs = soft_bbox_vote(boxs,thre=nmsthre) return boxs def soft_bbox_vote(det,thre=0.35,score=0.05): diff --git a/keras_csp/data_augment.py b/keras_csp/data_augment.py index 599d69b..2c014a8 100644 --- a/keras_csp/data_augment.py +++ b/keras_csp/data_augment.py @@ -1,4 +1,4 @@ -from __future__ import division + import cv2 import numpy as np import copy diff --git a/keras_csp/data_generators.py b/keras_csp/data_generators.py index 37018b5..2cd76ad 100644 --- a/keras_csp/data_generators.py +++ b/keras_csp/data_generators.py @@ -1,5 +1,5 @@ -from __future__ import absolute_import -from __future__ import division + + # import numpy as np # import cv2 import random @@ -165,7 +165,7 @@ def get_data(ped_data, C, batchsize = 8): if C.offset: y_offset_batch.append(np.expand_dims(y_offset, axis=0)) except Exception as e: - print ('get_batch_gt:',e) + print(('get_batch_gt:',e)) x_img_batch = np.concatenate(x_img_batch,axis=0) y_seman_batch = np.concatenate(y_seman_batch, axis=0) y_height_batch = np.concatenate(y_height_batch, axis=0) @@ -215,7 +215,7 @@ def get_data_hybrid(ped_data, emp_data, C, batchsize = 8,hyratio=0.5): y_offset_batch.append(np.expand_dims(y_offset, axis=0)) except Exception as e: - print ('get_batch_gt:',e) + print(('get_batch_gt:',e)) for img_data in emp_data[current_emp:current_emp + batchsize_emp]: try: img_data, x_img = data_augment.augment(img_data, C) @@ -240,7 +240,7 @@ def get_data_hybrid(ped_data, emp_data, C, batchsize = 8,hyratio=0.5): if C.offset: y_offset_batch.append(np.expand_dims(y_offset, axis=0)) except Exception as e: - print ('get_batch_gt_emp:',e) + print(('get_batch_gt_emp:',e)) x_img_batch = np.concatenate(x_img_batch,axis=0) y_seman_batch = np.concatenate(y_seman_batch, axis=0) y_height_batch = np.concatenate(y_height_batch, axis=0) @@ -279,7 +279,7 @@ def get_data_wider(ped_data, C, batchsize = 8): if C.offset: y_offset_batch.append(np.expand_dims(y_offset, axis=0)) except Exception as e: - print ('get_batch_gt:',e) + print(('get_batch_gt:',e)) x_img_batch = np.concatenate(x_img_batch,axis=0) y_seman_batch = np.concatenate(y_seman_batch, axis=0) y_height_batch = np.concatenate(y_height_batch, axis=0) diff --git a/keras_csp/mobilenet.py b/keras_csp/mobilenet.py index d5b936d..f028352 100644 --- a/keras_csp/mobilenet.py +++ b/keras_csp/mobilenet.py @@ -1,6 +1,6 @@ -from __future__ import print_function -from __future__ import absolute_import -from __future__ import division + + + from keras.layers import * from keras import backend as K import numpy as np diff --git a/keras_csp/nms_wrapper.py b/keras_csp/nms_wrapper.py index c34cb15..9a9ea28 100644 --- a/keras_csp/nms_wrapper.py +++ b/keras_csp/nms_wrapper.py @@ -5,8 +5,8 @@ # Written by Ross Girshick # -------------------------------------------------------- -from nms.gpu_nms import gpu_nms -from nms.cpu_nms import cpu_nms +from .nms.gpu_nms import gpu_nms +from .nms.cpu_nms import cpu_nms import numpy as np def soft_nms(dets, sigma=0.5, Nt=0.3, threshold=0.001, method=1): diff --git a/keras_csp/parallel_model.py b/keras_csp/parallel_model.py index d5d42b2..01c7af8 100644 --- a/keras_csp/parallel_model.py +++ b/keras_csp/parallel_model.py @@ -71,8 +71,8 @@ def make_parallel(self): with tf.device('/gpu:%d' % i): with tf.name_scope('tower_%d' % i): # Run a slice of inputs through this replica - zipped_inputs = zip(self.inner_model.input_names, - self.inner_model.inputs) + zipped_inputs = list(zip(self.inner_model.input_names, + self.inner_model.inputs)) inputs = [ KL.Lambda(lambda s: input_slices[name][i], output_shape=lambda s: (None,)+s[1:])(tensor) @@ -146,8 +146,8 @@ def build_model(x_train, num_classes): x_train = np.expand_dims(x_train, -1).astype('float32') / 255 x_test = np.expand_dims(x_test, -1).astype('float32') / 255 - print('x_train shape:', x_train.shape) - print('x_test shape:', x_test.shape) + print(('x_train shape:', x_train.shape)) + print(('x_test shape:', x_test.shape)) # Build data generator and model datagen = ImageDataGenerator() diff --git a/keras_csp/resnet50.py b/keras_csp/resnet50.py index 64591fc..037e60d 100644 --- a/keras_csp/resnet50.py +++ b/keras_csp/resnet50.py @@ -1,9 +1,9 @@ # -*- coding: utf-8 -*- -from __future__ import print_function -from __future__ import absolute_import -from __future__ import division + + + from keras.layers import * from keras import backend as K from .keras_layer_L2Normalization import L2Normalization diff --git a/keras_csp/utilsfunc.py b/keras_csp/utilsfunc.py index ce05628..bee2111 100644 --- a/keras_csp/utilsfunc.py +++ b/keras_csp/utilsfunc.py @@ -1,4 +1,4 @@ -from __future__ import division + import cv2 import numpy as np diff --git a/test_caltech.py b/test_caltech.py index 8ece107..506d8fb 100644 --- a/test_caltech.py +++ b/test_caltech.py @@ -1,7 +1,7 @@ -from __future__ import division + import os import time -import cPickle +import pickle from keras.layers import Input from keras.models import Model from keras_csp import config, bbox_process @@ -13,9 +13,9 @@ C.offset = True cache_path = 'data/cache/caltech/test' with open(cache_path, 'rb') as fid: - val_data = cPickle.load(fid) + val_data = pickle.load(fid) num_imgs = len(val_data) -print 'num of val samples: {}'.format(num_imgs) +print('num of val samples: {}'.format(num_imgs)) C.size_test = (480, 640) input_shape_img = (C.size_test[0], C.size_test[1], 3) @@ -42,11 +42,11 @@ cur_file = f break weight1 = os.path.join(w_path, cur_file) - print 'load weights from {}'.format(weight1) + print('load weights from {}'.format(weight1)) model.load_weights(weight1, by_name=True) res_path = os.path.join(out_path, '%03d'%int(str(w_ind))) - print res_path + print(res_path) if not os.path.exists(res_path): os.mkdir(res_path) for st in range(6, 11): @@ -83,4 +83,4 @@ res_all += np.concatenate((f_res, boxes), axis=-1).tolist() if frame_number_next == 30 or f == num_imgs - 1: np.savetxt(video_path, np.array(res_all), fmt='%6f') - print time.time() - start_time + print(time.time() - start_time) diff --git a/test_city.py b/test_city.py index 644659d..a3c5838 100644 --- a/test_city.py +++ b/test_city.py @@ -1,7 +1,7 @@ -from __future__ import division + import os import time -import cPickle +import pickle from keras.layers import Input from keras.models import Model from keras_csp import config, bbox_process @@ -12,9 +12,9 @@ C.offset = True cache_path = 'data/cache/cityperson/val_500' with open(cache_path, 'rb') as fid: - val_data = cPickle.load(fid) + val_data = pickle.load(fid) num_imgs = len(val_data) -print 'num of val samples: {}'.format(num_imgs) +print('num of val samples: {}'.format(num_imgs)) C.size_test = (1024, 2048) input_shape_img = (C.size_test[0], C.size_test[1], 3) @@ -48,12 +48,12 @@ cur_file = f break weight1 = os.path.join(w_path, cur_file) - print 'load weights from {}'.format(weight1) + print('load weights from {}'.format(weight1)) model.load_weights(weight1, by_name=True) res_path = os.path.join(out_path, '%03d'%int(str(w_ind))) if not os.path.exists(res_path): os.makedirs(res_path) - print res_path + print(res_path) res_file = os.path.join(res_path, 'val_det.txt') res_all = [] start_time = time.time() @@ -72,4 +72,4 @@ boxes[:, [2, 3]] -= boxes[:, [0, 1]] res_all += np.concatenate((f_res, boxes), axis=-1).tolist() np.savetxt(res_file, np.array(res_all), fmt='%6f') - print time.time() - start_time + print(time.time() - start_time) diff --git a/test_wider_ms.py b/test_wider_ms.py index 4e02316..ef36024 100644 --- a/test_wider_ms.py +++ b/test_wider_ms.py @@ -1,7 +1,7 @@ -from __future__ import division + import os import time -import cPickle +import pickle from keras.layers import Input from keras.models import Model from keras_csp import config, bbox_process @@ -14,9 +14,9 @@ C.num_scale = 2 cache_path = 'data/cache/widerface/val' with open(cache_path, 'rb') as fid: - val_data = cPickle.load(fid) + val_data = pickle.load(fid) num_imgs = len(val_data) -print 'num of val samples: {}'.format(num_imgs) +print('num of val samples: {}'.format(num_imgs)) C.size_test = [0, 0] input_shape_img = (None, None, 3) @@ -44,12 +44,12 @@ cur_file = f break weight1 = os.path.join(w_path, cur_file) - print 'load weights from {}'.format(weight1) + print('load weights from {}'.format(weight1)) model.load_weights(weight1, by_name=True) res_path = os.path.join(out_path, '%03d'%int(str(w_ind))) if not os.path.exists(res_path): os.makedirs(res_path) - print res_path + print(res_path) start_time = time.time() for f in range(num_imgs): @@ -160,4 +160,4 @@ def im_det_ms_pyramid(image, max_im_shrink): for line in dets: f.write('{:.0f} {:.0f} {:.0f} {:.0f} {:.3f}\n'. format(line[0], line[1], line[2] - line[0] + 1, line[3] - line[1] + 1, line[4])) - print time.time() - start_time \ No newline at end of file + print(time.time() - start_time) \ No newline at end of file diff --git a/train_caltech.py b/train_caltech.py index 7359d8a..05af949 100644 --- a/train_caltech.py +++ b/train_caltech.py @@ -1,9 +1,9 @@ -from __future__ import division + import random import sys, os import time import numpy as np -import cPickle +import pickle from keras.utils import generic_utils from keras.optimizers import Adam from keras.layers import Input @@ -28,12 +28,12 @@ cache_ped = 'data/cache/caltech/train_gt' cache_emp = 'data/cache/caltech/train_nogt' with open(cache_ped, 'rb') as fid: - ped_data = cPickle.load(fid) + ped_data = pickle.load(fid) with open(cache_emp, 'rb') as fid: - emp_data = cPickle.load(fid) + emp_data = pickle.load(fid) num_imgs_ped = len(ped_data) num_imgs_emp = len(emp_data) -print ('num of ped and emp samples: {} {}'.format(num_imgs_ped,num_imgs_emp)) +print(('num of ped and emp samples: {} {}'.format(num_imgs_ped,num_imgs_emp))) data_gen_train = data_generators.get_data_hybrid(ped_data, emp_data, C, batchsize=batchsize, hyratio=0.5) # define the base network (resnet here, can be MobileNet, etc) @@ -61,7 +61,7 @@ model.load_weights(weight_path, by_name=True) model_tea.load_weights(weight_path, by_name=True) -print 'load weights from {}'.format(weight_path) +print('load weights from {}'.format(weight_path)) if C.offset: out_path = 'output/valmodels/caltech/%s/off2' % (C.scale) @@ -89,12 +89,12 @@ losses = np.zeros((epoch_length, 3)) best_loss = np.Inf -print('Starting training with lr {} and alpha {}'.format(C.init_lr, C.alpha)) +print(('Starting training with lr {} and alpha {}'.format(C.init_lr, C.alpha))) start_time = time.time() total_loss_r, cls_loss_r1, regr_loss_r1, offset_loss_r1 = [], [], [], [] for epoch_num in range(C.num_epochs): progbar = generic_utils.Progbar(epoch_length) - print('Epoch {}/{}'.format(epoch_num + 1 + add_epoch, C.num_epochs + C.add_epoch)) + print(('Epoch {}/{}'.format(epoch_num + 1 + add_epoch, C.num_epochs + C.add_epoch))) while True: try: X, Y = next(data_gen_train) @@ -131,19 +131,19 @@ cls_loss_r1.append(cls_loss1) regr_loss_r1.append(regr_loss1) offset_loss_r1.append(offset_loss1) - print('Total loss: {}'.format(total_loss)) - print('Elapsed time: {}'.format(time.time() - start_time)) + print(('Total loss: {}'.format(total_loss))) + print(('Elapsed time: {}'.format(time.time() - start_time))) iter_num = 0 start_time = time.time() if total_loss < best_loss: - print('Total loss decreased from {} to {}, saving weights'.format(best_loss, total_loss)) + print(('Total loss decreased from {} to {}, saving weights'.format(best_loss, total_loss))) best_loss = total_loss model_tea.save_weights(os.path.join(out_path, 'net_e{}_l{}.hdf5'.format(epoch_num + 1 + add_epoch, total_loss))) break except Exception as e: - print ('Exception: {}'.format(e)) + print(('Exception: {}'.format(e))) continue records = np.concatenate((np.asarray(total_loss_r).reshape((-1, 1)), np.asarray(cls_loss_r1).reshape((-1, 1)), diff --git a/train_city.py b/train_city.py index 8eb64ac..3b79d54 100644 --- a/train_city.py +++ b/train_city.py @@ -1,9 +1,9 @@ -from __future__ import division + import random import sys, os import time import numpy as np -import cPickle +import pickle from keras.utils import generic_utils from keras.optimizers import Adam from keras.layers import Input @@ -27,10 +27,10 @@ # get the training data cache_path = 'data/cache/cityperson/train_h50' with open(cache_path, 'rb') as fid: - train_data = cPickle.load(fid) + train_data = pickle.load(fid) num_imgs_train = len(train_data) random.shuffle(train_data) -print 'num of training samples: {}'.format(num_imgs_train) +print('num of training samples: {}'.format(num_imgs_train)) data_gen_train = data_generators.get_data(train_data, C, batchsize=batchsize) # define the base network (resnet here, can be MobileNet, etc) @@ -53,7 +53,7 @@ model.load_weights(weight_path, by_name=True) model_tea.load_weights(weight_path, by_name=True) -print 'load weights from {}'.format(weight_path) +print('load weights from {}'.format(weight_path)) if C.offset: out_path = 'output/valmodels/city/%s/off' % (C.scale) @@ -79,12 +79,12 @@ losses = np.zeros((epoch_length, 3)) best_loss = np.Inf -print('Starting training with lr {} and alpha {}'.format(C.init_lr, C.alpha)) +print(('Starting training with lr {} and alpha {}'.format(C.init_lr, C.alpha))) start_time = time.time() total_loss_r, cls_loss_r1, regr_loss_r1, offset_loss_r1 = [], [], [], [] for epoch_num in range(C.num_epochs): progbar = generic_utils.Progbar(epoch_length) - print('Epoch {}/{}'.format(epoch_num + 1 + add_epoch, C.num_epochs + C.add_epoch)) + print(('Epoch {}/{}'.format(epoch_num + 1 + add_epoch, C.num_epochs + C.add_epoch))) while True: try: X, Y = next(data_gen_train) @@ -121,19 +121,19 @@ cls_loss_r1.append(cls_loss1) regr_loss_r1.append(regr_loss1) offset_loss_r1.append(offset_loss1) - print('Total loss: {}'.format(total_loss)) - print('Elapsed time: {}'.format(time.time() - start_time)) + print(('Total loss: {}'.format(total_loss))) + print(('Elapsed time: {}'.format(time.time() - start_time))) iter_num = 0 start_time = time.time() if total_loss < best_loss: - print('Total loss decreased from {} to {}, saving weights'.format(best_loss, total_loss)) + print(('Total loss decreased from {} to {}, saving weights'.format(best_loss, total_loss))) best_loss = total_loss model_tea.save_weights(os.path.join(out_path, 'net_e{}_l{}.hdf5'.format(epoch_num + 1 + add_epoch, total_loss))) break except Exception as e: - print ('Exception: {}'.format(e)) + print(('Exception: {}'.format(e))) continue records = np.concatenate((np.asarray(total_loss_r).reshape((-1, 1)), np.asarray(cls_loss_r1).reshape((-1, 1)), diff --git a/train_wider.py b/train_wider.py index 404b2fe..c5df94a 100644 --- a/train_wider.py +++ b/train_wider.py @@ -1,9 +1,9 @@ -from __future__ import division + import random import sys, os import time import numpy as np -import cPickle +import pickle from keras.utils import generic_utils from keras.optimizers import Adam from keras.layers import Input @@ -29,9 +29,9 @@ # get the training data cache_path = 'data/cache/widerface/train' with open(cache_path, 'rb') as fid: - train_data = cPickle.load(fid) + train_data = pickle.load(fid) num_imgs_train = len(train_data) -print 'num of training samples: {}'.format(num_imgs_train) +print('num of training samples: {}'.format(num_imgs_train)) data_gen_train = data_generators.get_data_wider(train_data, C, batchsize=batchsize) # define the base network (resnet here, can be MobileNet, etc) @@ -54,7 +54,7 @@ model.load_weights(weight_path, by_name=True) model_tea.load_weights(weight_path, by_name=True) -print 'load weights from {}'.format(weight_path) +print('load weights from {}'.format(weight_path)) if C.offset: out_path = 'output/valmodels/wider/%s/off' % (C.scale) @@ -76,12 +76,12 @@ losses = np.zeros((epoch_length, 3)) best_loss = np.Inf -print('Starting training with lr {} and alpha {}'.format(C.init_lr, C.alpha)) +print(('Starting training with lr {} and alpha {}'.format(C.init_lr, C.alpha))) start_time = time.time() total_loss_r, cls_loss_r1, regr_loss_r1, offset_loss_r1 = [], [], [], [] for epoch_num in range(C.num_epochs): progbar = generic_utils.Progbar(epoch_length) - print('Epoch {}/{}'.format(epoch_num + 1 + add_epoch, C.num_epochs + C.add_epoch)) + print(('Epoch {}/{}'.format(epoch_num + 1 + add_epoch, C.num_epochs + C.add_epoch))) while True: try: X, Y = next(data_gen_train) @@ -118,19 +118,19 @@ cls_loss_r1.append(cls_loss1) regr_loss_r1.append(regr_loss1) offset_loss_r1.append(offset_loss1) - print('Total loss: {}'.format(total_loss)) - print('Elapsed time: {}'.format(time.time() - start_time)) + print(('Total loss: {}'.format(total_loss))) + print(('Elapsed time: {}'.format(time.time() - start_time))) iter_num = 0 start_time = time.time() if total_loss < best_loss: - print('Total loss decreased from {} to {}, saving weights'.format(best_loss, total_loss)) + print(('Total loss decreased from {} to {}, saving weights'.format(best_loss, total_loss))) best_loss = total_loss model_tea.save_weights(os.path.join(out_path, 'net_e{}_l{}.hdf5'.format(epoch_num + 1 + add_epoch, total_loss))) break except Exception as e: - print ('Exception: {}'.format(e)) + print(('Exception: {}'.format(e))) continue records = np.concatenate((np.asarray(total_loss_r).reshape((-1, 1)), np.asarray(cls_loss_r1).reshape((-1, 1)), From 8e7a0187b87eb5dbc044965e287e276ca8d33a30 Mon Sep 17 00:00:00 2001 From: dominik dienlin Date: Mon, 5 Aug 2019 19:05:16 +0200 Subject: [PATCH 02/18] remove usage of tabs for python3 compatibility --- keras_csp/bbox_process.py | 2 +- keras_csp/bbox_transform.py | 4 ++-- keras_csp/nms_wrapper.py | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/keras_csp/bbox_process.py b/keras_csp/bbox_process.py index d3bd29b..6cd190b 100644 --- a/keras_csp/bbox_process.py +++ b/keras_csp/bbox_process.py @@ -1,6 +1,6 @@ import numpy as np -from .nms_wrapper import nms +from keras_csp.nms_wrapper import nms def parse_det(Y, C, score=0.1, down=4,scale='h'): seman = Y[0][0, :, :, 0] diff --git a/keras_csp/bbox_transform.py b/keras_csp/bbox_transform.py index b7992ea..c216440 100644 --- a/keras_csp/bbox_transform.py +++ b/keras_csp/bbox_transform.py @@ -68,9 +68,9 @@ def compute_targets(ex_rois, gt_rois, classifier_regr_std,std): assert gt_rois.shape[1] == 4 targets = bbox_transform(ex_rois, gt_rois) - # Optionally normalize targets by a precomputed mean and stdev + # Optionally normalize targets by a precomputed mean and stdev if std: - targets = targets/np.array(classifier_regr_std) + targets = targets/np.array(classifier_regr_std) return targets def clip_boxes(boxes, im_shape): diff --git a/keras_csp/nms_wrapper.py b/keras_csp/nms_wrapper.py index 9a9ea28..7bde7d0 100644 --- a/keras_csp/nms_wrapper.py +++ b/keras_csp/nms_wrapper.py @@ -4,9 +4,9 @@ # Licensed under The MIT License [see LICENSE for details] # Written by Ross Girshick # -------------------------------------------------------- - -from .nms.gpu_nms import gpu_nms -from .nms.cpu_nms import cpu_nms +import pyximport; pyximport.install() +from keras_csp.nms.gpu_nms import gpu_nms +from keras_csp.nms.cpu_nms import cpu_nms import numpy as np def soft_nms(dets, sigma=0.5, Nt=0.3, threshold=0.001, method=1): From 0b369651304e13feba095b36ad06962103c82895 Mon Sep 17 00:00:00 2001 From: dominik dienlin Date: Mon, 5 Aug 2019 19:05:32 +0200 Subject: [PATCH 03/18] added script to download resnet50 weights --- download_weights.sh | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 download_weights.sh diff --git a/download_weights.sh b/download_weights.sh new file mode 100644 index 0000000..8f263fa --- /dev/null +++ b/download_weights.sh @@ -0,0 +1,2 @@ +mkdir -p data/models +wget -O ./data/models/resnet50_weights_tf_dim_ordering_tf_kernels.h5 https://github.com/fchollet/deep-learning-models/releases/download/v0.2/resnet50_weights_tf_dim_ordering_tf_kernels.h5 --no-check-certificate From 0df60849250d4eb0409ae935ecae2639aa5c9a63 Mon Sep 17 00:00:00 2001 From: dominik dienlin Date: Mon, 5 Aug 2019 19:19:20 +0200 Subject: [PATCH 04/18] add encoding for pickle to load python2 pickled files --- train_city.py | 99 +++++++++++++++++++++++++-------------------------- 1 file changed, 48 insertions(+), 51 deletions(-) diff --git a/train_city.py b/train_city.py index 3b79d54..d1e7f1e 100644 --- a/train_city.py +++ b/train_city.py @@ -27,7 +27,7 @@ # get the training data cache_path = 'data/cache/cityperson/train_h50' with open(cache_path, 'rb') as fid: - train_data = pickle.load(fid) + train_data = pickle.load(fid, encoding='latin1') num_imgs_train = len(train_data) random.shuffle(train_data) print('num of training samples: {}'.format(num_imgs_train)) @@ -86,59 +86,56 @@ progbar = generic_utils.Progbar(epoch_length) print(('Epoch {}/{}'.format(epoch_num + 1 + add_epoch, C.num_epochs + C.add_epoch))) while True: - try: - X, Y = next(data_gen_train) - loss_s1 = model.train_on_batch(X, Y) - - for l in model_tea.layers: - weights_tea = l.get_weights() - if len(weights_tea)>0: - if num_gpu > 1: - weights_stu = model_stu.get_layer(name=l.name).get_weights() - else: - weights_stu = model.get_layer(name=l.name).get_weights() - weights_tea = [C.alpha*w_tea + (1-C.alpha)*w_stu for (w_tea, w_stu) in zip(weights_tea, weights_stu)] - l.set_weights(weights_tea) - # print loss_s1 - losses[iter_num, 0] = loss_s1[1] - losses[iter_num, 1] = loss_s1[2] - if C.offset: - losses[iter_num, 2] = loss_s1[3] - else: - losses[iter_num, 2] = 0 - - iter_num += 1 - if iter_num % 20 == 0: - progbar.update(iter_num, - [('cls', np.mean(losses[:iter_num, 0])), ('regr_h', np.mean(losses[:iter_num, 1])), ('offset', np.mean(losses[:iter_num, 2]))]) - if iter_num == epoch_length: - cls_loss1 = np.mean(losses[:, 0]) - regr_loss1 = np.mean(losses[:, 1]) - offset_loss1 = np.mean(losses[:, 2]) - total_loss = cls_loss1+regr_loss1+offset_loss1 - - total_loss_r.append(total_loss) - cls_loss_r1.append(cls_loss1) - regr_loss_r1.append(regr_loss1) - offset_loss_r1.append(offset_loss1) - print(('Total loss: {}'.format(total_loss))) - print(('Elapsed time: {}'.format(time.time() - start_time))) - - iter_num = 0 - start_time = time.time() - - if total_loss < best_loss: - print(('Total loss decreased from {} to {}, saving weights'.format(best_loss, total_loss))) - best_loss = total_loss - model_tea.save_weights(os.path.join(out_path, 'net_e{}_l{}.hdf5'.format(epoch_num + 1 + add_epoch, total_loss))) - break - except Exception as e: - print(('Exception: {}'.format(e))) - continue + X, Y = next(data_gen_train) + loss_s1 = model.train_on_batch(X, Y) + + for l in model_tea.layers: + weights_tea = l.get_weights() + if len(weights_tea)>0: + if num_gpu > 1: + weights_stu = model_stu.get_layer(name=l.name).get_weights() + else: + weights_stu = model.get_layer(name=l.name).get_weights() + weights_tea = [C.alpha*w_tea + (1-C.alpha)*w_stu for (w_tea, w_stu) in zip(weights_tea, weights_stu)] + l.set_weights(weights_tea) + # print loss_s1 + losses[iter_num, 0] = loss_s1[1] + losses[iter_num, 1] = loss_s1[2] + if C.offset: + losses[iter_num, 2] = loss_s1[3] + else: + losses[iter_num, 2] = 0 + + iter_num += 1 + if iter_num % 20 == 0: + progbar.update(iter_num, + [('cls', np.mean(losses[:iter_num, 0])), ('regr_h', np.mean(losses[:iter_num, 1])), ('offset', np.mean(losses[:iter_num, 2]))]) + if iter_num == epoch_length: + cls_loss1 = np.mean(losses[:, 0]) + regr_loss1 = np.mean(losses[:, 1]) + offset_loss1 = np.mean(losses[:, 2]) + total_loss = cls_loss1+regr_loss1+offset_loss1 + + total_loss_r.append(total_loss) + cls_loss_r1.append(cls_loss1) + regr_loss_r1.append(regr_loss1) + offset_loss_r1.append(offset_loss1) + print(('Total loss: {}'.format(total_loss))) + print(('Elapsed time: {}'.format(time.time() - start_time))) + + iter_num = 0 + start_time = time.time() + + if total_loss < best_loss: + print(('Total loss decreased from {} to {}, saving weights'.format(best_loss, total_loss))) + best_loss = total_loss + model_tea.save_weights(os.path.join(out_path, 'net_e{}_l{}.hdf5'.format(epoch_num + 1 + add_epoch, total_loss))) + break + records = np.concatenate((np.asarray(total_loss_r).reshape((-1, 1)), np.asarray(cls_loss_r1).reshape((-1, 1)), np.asarray(regr_loss_r1).reshape((-1, 1)), np.asarray(offset_loss_r1).reshape((-1, 1)),), axis=-1) np.savetxt(res_file, np.array(records), fmt='%.6f') -print('Training complete, exiting.') \ No newline at end of file +print('Training complete, exiting.') From 604a33b3f7e79582fc22a1af996a4f98a72c1da5 Mon Sep 17 00:00:00 2001 From: dominik dienlin Date: Tue, 6 Aug 2019 13:23:25 +0200 Subject: [PATCH 05/18] replaced tabs with spaces --- keras_csp/mobilenet.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/keras_csp/mobilenet.py b/keras_csp/mobilenet.py index f028352..e8855f8 100644 --- a/keras_csp/mobilenet.py +++ b/keras_csp/mobilenet.py @@ -477,12 +477,13 @@ def nn_p2p3p4p5(img_input=None, alpha=1.0, depth_multiplier=1, trainable=True): return [x_class, x_regr] + # focal loss like def prior_probability_onecls(num_class=1, probability=0.01): - def f(shape, dtype=keras.backend.floatx()): - assert(shape[0] % num_class == 0) - # set bias to -log((1 - p)/p) for foregound - result = np.ones(shape, dtype=dtype) * -math.log((1 - probability) / probability) - # set bias to -log(p/(1 - p)) for background - return result - return f + def f(shape, dtype=keras.backend.floatx()): + assert(shape[0] % num_class == 0) + # set bias to -log((1 - p)/p) for foregound + result = np.ones(shape, dtype=dtype) * -math.log((1 - probability) / probability) + # set bias to -log(p/(1 - p)) for background + return result + return f From 29ecbedcbcef14b13005df421ab4a4c3f42496da Mon Sep 17 00:00:00 2001 From: dominik dienlin Date: Tue, 6 Aug 2019 13:24:27 +0200 Subject: [PATCH 06/18] updated requirements --- requirements.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/requirements.txt b/requirements.txt index 002965c..06f8421 100755 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ -tensorflow-gpu==1.4.1 +tensorflow-gpu==1.14.0 easydict==1.6 joblib==0.10.3 -numpy==1.12.0 -opencv-python==3.4.1.15 -Pillow==4.0.0 +numpy==1.16.2 +opencv-python==4.1.0.25 +Pillow==6.1.0 keras==2.0.6 From 5958a078e2a30804fa440d266743256563e22275 Mon Sep 17 00:00:00 2001 From: dominik dienlin Date: Tue, 6 Aug 2019 13:25:00 +0200 Subject: [PATCH 07/18] updated train_city.py to support resuming from saved checkpoint --- train_city.py | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/train_city.py b/train_city.py index d1e7f1e..8231c7a 100644 --- a/train_city.py +++ b/train_city.py @@ -1,4 +1,4 @@ - +import glob import random import sys, os import time @@ -38,14 +38,31 @@ from keras_csp import resnet50 as nn weight_path = 'data/models/resnet50_weights_tf_dim_ordering_tf_kernels.h5' + +if C.offset: + out_path = 'output/valmodels/city/%s/off' % (C.scale) +else: + out_path = 'output/valmodels/city/%s/nooff' % (C.scale) +if not os.path.exists(out_path): + os.makedirs(out_path) + epoch = 0 +else: + int_strings = [*map(str, range(10))] + checkpoint_paths = glob.glob(out_path + "/net*.hdf5") + checkpoint_names = [f.split("/")[-1] for f in checkpoint_paths] + epochs = [*map(int, [f.split("net_e")[1].split("_")[0] for f in checkpoint_names if "net_e" in f])] + epoch = np.argmax(epochs) + weight_path = checkpoint_paths[epoch] + + input_shape_img = (C.size_train[0], C.size_train[1], 3) img_input = Input(shape=input_shape_img) # define the network prediction preds = nn.nn_p3p4p5(img_input, offset=C.offset, num_scale=C.num_scale, trainable=True) preds_tea = nn.nn_p3p4p5(img_input, offset=C.offset, num_scale=C.num_scale, trainable=True) - model = Model(img_input, preds) -if num_gpu>1: + +if num_gpu > 1: from keras_csp.parallel_model import ParallelModel model = ParallelModel(model, int(num_gpu)) model_stu = Model(img_input, preds) @@ -55,12 +72,6 @@ model_tea.load_weights(weight_path, by_name=True) print('load weights from {}'.format(weight_path)) -if C.offset: - out_path = 'output/valmodels/city/%s/off' % (C.scale) -else: - out_path = 'output/valmodels/city/%s/nooff' % (C.scale) -if not os.path.exists(out_path): - os.makedirs(out_path) res_file = os.path.join(out_path,'records.txt') optimizer = Adam(lr=C.init_lr) @@ -82,7 +93,7 @@ print(('Starting training with lr {} and alpha {}'.format(C.init_lr, C.alpha))) start_time = time.time() total_loss_r, cls_loss_r1, regr_loss_r1, offset_loss_r1 = [], [], [], [] -for epoch_num in range(C.num_epochs): +for epoch_num in range(epoch, C.num_epochs): progbar = generic_utils.Progbar(epoch_length) print(('Epoch {}/{}'.format(epoch_num + 1 + add_epoch, C.num_epochs + C.add_epoch))) while True: From f438c135a165a5c3a1f668401a39d789eaca365c Mon Sep 17 00:00:00 2001 From: dominik dienlin Date: Tue, 6 Aug 2019 18:00:11 +0200 Subject: [PATCH 08/18] cleanup --- eval_city/eval_script/coco.pyc | Bin 15109 -> 0 bytes eval_city/eval_script/eval_MR_multisetup.pyc | Bin 14533 -> 0 bytes keras_csp/__init__.pyc | Bin 156 -> 0 bytes keras_csp/bbox_process.pyc | Bin 8556 -> 0 bytes keras_csp/bbox_transform.pyc | Bin 3326 -> 0 bytes keras_csp/config.pyc | Bin 1145 -> 0 bytes keras_csp/data_augment.pyc | Bin 8172 -> 0 bytes keras_csp/data_generators.pyc | Bin 11841 -> 0 bytes keras_csp/keras_layer_L2Normalization.pyc | Bin 3195 -> 0 bytes keras_csp/losses.pyc | Bin 3378 -> 0 bytes keras_csp/mobilenet.pyc | Bin 16221 -> 0 bytes keras_csp/nms/__init__.pyc | Bin 160 -> 0 bytes keras_csp/nms_wrapper.pyc | Bin 1105 -> 0 bytes keras_csp/parallel_model.pyc | Bin 7247 -> 0 bytes keras_csp/resnet50.pyc | Bin 22160 -> 0 bytes keras_csp/utilsfunc.pyc | Bin 7701 -> 0 bytes 16 files changed, 0 insertions(+), 0 deletions(-) delete mode 100755 eval_city/eval_script/coco.pyc delete mode 100644 eval_city/eval_script/eval_MR_multisetup.pyc delete mode 100644 keras_csp/__init__.pyc delete mode 100644 keras_csp/bbox_process.pyc delete mode 100644 keras_csp/bbox_transform.pyc delete mode 100644 keras_csp/config.pyc delete mode 100644 keras_csp/data_augment.pyc delete mode 100644 keras_csp/data_generators.pyc delete mode 100644 keras_csp/keras_layer_L2Normalization.pyc delete mode 100644 keras_csp/losses.pyc delete mode 100644 keras_csp/mobilenet.pyc delete mode 100644 keras_csp/nms/__init__.pyc delete mode 100644 keras_csp/nms_wrapper.pyc delete mode 100644 keras_csp/parallel_model.pyc delete mode 100644 keras_csp/resnet50.pyc delete mode 100644 keras_csp/utilsfunc.pyc diff --git a/eval_city/eval_script/coco.pyc b/eval_city/eval_script/coco.pyc deleted file mode 100755 index 1f3d2b2e13aa6b6fb1877107c8bfe7a2112c1775..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15109 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 RieChBZQykT%MCuc{{@Wtw}}7% diff --git a/eval_city/eval_script/eval_MR_multisetup.pyc b/eval_city/eval_script/eval_MR_multisetup.pyc deleted file mode 100644 index a0c9e6b02f335ce570f2dbe4e8072e9bc2456d81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14533 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 Ob)&1X8Urt0TpmX@bx z>K7E{XQd{W6zgZF79|$zCTEsZ7Niyx=jZ7rr{bLS89wLQ&WGb9ZsIm^GfV?aO9p5|TPR;?QzrAZfDXD9v_yj}*S<+^Yx}zQ zUN_FjUbQ1uEPxd(83~Cki;(~ciGRQXfnb4Huwa8&%nyL)dC&FraonV(Q#3*%v0tBi z&U?PzbDsBk&$*coX7m4C{@&X)mHcJ#dwo@@=toG@@zJWGR8y;Mtu&t<)o|2yM#?g( zkyXu{+RmXYtLiybpHTHl^(dpZkwDIrdW5QzlAf0Il%%1VSC7!p^x$zu)eBNFuj;d^ zKBwyQqJaFOdZg5LfqmaxJArZe|H9vzMk=1-F#QL9%T1qi zimAO<%Rw&SJB{zwDyI1}N2#7nvy7>7f=a#XSP89mvZ~zAsUD`|sC$kILlrA^S4+K& zI=0?JXk}EXFV^TyAT_C4zm>Lf($;VO^R^~cPYk+(R$CouYeL$(te;_APf;Z!CKyZw z6M#8k07vy;6__NeQ1-T?`ctYut#*~_=T)3hy(#9ys!#}j>U961;_NUVMX!GMPpUto zU>2zMW>mR1Ek8RB3|`^bcd>P`+-wQiP%Na`TC#g{YB$F@>-z`#7EOe) zU^`EXx$-E{v`ZV9(z0A(V?vt9e1E=ToxwGnx11f-1rJ0iEFtEd*Bb3(Ts?3>=BTD9SsLa$kEN&kDE zzq=Qk;rjJ>PeyW3smX5_zii=7(2b;NUo7WxlJXqMw7VDO=is6!-}Aio8Wfa>=*vj0 z?*&b7z2SHEJ%7C&26w$$9IbEN{AQ&QU`*@xys#QoYEgUr4!Wv9qvl1?h4z8iqg@Rn zuToD&et}KvbGo1}>sd=)(JOjFFX*yfmj5^OoA_P9bB)8D$2WCa@56vkkD@&(D=P(6K3%bkP%dAgl zC_W!JEddR{=(r-B0#=k@HkDZmA2;ieSC0#}#7ND=H3vMzxnFm=gyE*o)YDCiSh?hBV7cIPO#RWLrKfYy4@tklAw z?UFWK0!_f@E+Vx?MYlw8lHwFanc_6X3ltxtc#+}^1)YST$6aOW;}oBu_$0)00}ZE= zf~FD&Z4Mx!AaKs5Ksl@PfXL=CK>5{24V3qF_wVCC`Ta)?6zqC3;{U-SU~$i4XZ=qh zq=*3z5ppMpk)Ti64cdiUzn+=NhyYzgfb3An^2N49iALr6~Ihj2H~DVihbkX z$HPxViKscAj~LPpOA$>j36mwEX=a4YlInAo4n~ydFhJ}tkjEIFB3N7yWFl!x(;>jTZkQJ8T6;7jmD<_tTZI)Owdsa~{n5OSuD zVo~)=3df@!FpG05qSVAOAgeUUGU2Y%7iBmL9B-+gR)nW|TxB??Bs+!_T5(~?zEZz$}IRQT*0+yIo_*`P) zH0+J}7zI0VMUH3>g4kOVU-1~PA!k+GAhFM(2XR->g3BP+eVO6~iX-FWPqXwh6sr_z zr2O21WXAF)1lafMURW{S;#@z!2P0YVAn0=$gIXHNpBPt#8yTpUaGwW{&Vwoj znFsm@W92+dn~0AQrVO=sKV@r~=BNdtL|evf77l5dAyW$n#Z-&_#%{}umRfLfGA^($ z{mO)rsj)=v)G%U}z_UyaOMopngc(FFIOgIbex!__7nkt3yh3k>MgcxVH8AYpBwuDU zgQY!uT9q3wl>Ev#%t^(8&J8QyXZ%A$%P!>04JG+ZrK_11k)X|0ik2c&P~ ziw~Z0IfflVe`sBKC3^_Vi3_&n(shO5dTPsG`iQ21z#$bHw%sakl?;x zyRf2N3|q@(FpF^^jYTMpl*@I7sV>99I@r|>9B76`u?_s+yjTS;7M)=&Y;CKta&n!Z zNnMBa>_MUJ6*%n2PH4k8^I@3`X9HFlES-Va2N`yPb%Sk6gLNy>J&!DDS~OhJlC`9_ zu$tVcF!9;qi+GS(xzSR;FYd*KZCs<=mGDy%;68s>^K+>L@T7G{zRT#ow9PSd3Q z7SnQPBR7_H50{vp+zf`nekF>lwR3`fm|Xr zy>Qp7_^rCvH7{EbKv!$E4$cO^QSwmngHFtA8)4W%Zk!+FnCgr~VVa7$+8wFSsiE|F z+_}0J*bTnXx7ngz)LFf*PvLU)l(U_(;%R*vw?|8vGD`CLq_e0qxN6NHJ>eAe1^qI# zZ|gI9Ue}RY)XR=3pL5t&jpkx(k#gh%SQTD!fURfdNH{(;WW9i*^MT7{e4A0-*>R4% z&#WQ#o+C%f+nOhGq|Ky9bEIL?Cvl|Bq(^h4VN%0{;HKP=36En>6ONbo!U-SLMl6FL zaO4a*5-}?LAUF~PI>M3g(^wI_MjFtDtO(8qP&dqovXmKT4{d?hEM`RfGdJ+CnUopl zxUd#8T5ODFM+pkNZx`EKFd!(q+^Q}F1%9)OhXge*v%#AvLr{kHVF+8>YHXCC4(Zv0 z5`roYO=nMN1M~-yPt9tme`ClxFjsNhTt&-Vx4|o#Go1&&$yYg{7yd_t0|0VWb|{Iojin`rFjcCO&x1F|Q zHnI;8_Rejeg~#9x_7RYH0QjnU9M3pTPQ=c%ySje5rn|ncJEecNH~;wa-OoN{9~Zyh z;L)dO0{l7DC;G{uz@^{OaVaQCr$j+nI%Ntf(y6fVMRN^~;lKEt`yA{ko(i7t@aT6A z(bUEzdW%>NUAlBo7;^F~p-$ZMUoRhq(}Om)1(-fWYm7^pxhL3%=l z=*pp~yyD)CL$j^<5axsl4{gg3RuaxnXu3tyZMrNIR97XsA)4*bbO-ykjtx2wdCNjP z)a8cg@3XLkpAZ{2A9{b*EJHGE8YPC+{kUs*-`{BC`PZh(>eP#L5^L4u3NRd9jXP-^ zYUy{4?XxMyM`2)k+H6{>r^0T}XtQBO-=v*!UYN)X2$6Gxly`%;aLa^=#5Z2rRYrG$ zaZy~-j*8lzWS#jokrzp$e?ae~7Z21)KOBx!c#@>?mGX@~xmKyCkNnU~5|!#WI`UOy zRBFdNm#H5`C$C?}udu>FM%01|1-oGoD$uUb$qffFQF zP%oi#eMt>83i#Mb7>!qVO(w1ZwJV1A8N`Cl70Md0y<&Kup^m_C+hE{gRaRKl82#3& zDpsKA6=^XczzT$b7W&-AGZkzSFZ&kN>R^Rie^d|m=d0QRld#$LvRQF;TZ?G>g=oc9 z&P6Ml6<50@G{tZ@7lsl}LTw^1#+WIi=f}xJIIKutne_fFWTPhYia6??m#8)*EB>O= zShs5|GKxGcae0PUUSBJrfJlwJF-VMQPmL4HZfpW5D=mJ3>KpiSh>W0^{pRe%ww9Xa zy@^mM_=p)b$fS{#dO|}-@uE&`;qeQ$pP><+|5j_28aRKS zrg7TdWhEY4i(Z;~lcqRu4sGrkHu3u&X1okl+TrOt+5}RJ_-*rcJmPNiN$%Tq=w$DE zh9S*|7L^*#fpg$K#cA}+o<>~GoVIM|3)~>=b%oodi(PgN1j+D@xm3sQfO62@JzrY) zMzQAt_7<)WL=m(5qu67Eqdb_4nB5;`aV2~(7cpz$B`;*FbHrwEVvL3+H?}aCM+Tsu z!EhjCGzcT^H+iMoFVM&>DI9c!*dDPGn1%d)m~@0-euSiXh&Eoi@^$3j0O8nZI7lXv rzOC@jVAlSen^QE49HsZa-={V(M{5uV!@l~O`MEeL4tS?4+|1EB6<>calvDVySXH&?PR)Vrjyy8VY-LK;7!FJ zAowrDs|OGM0?Adph~O!L2M=C6SXCpgf;XL|zWu7YtNN>cRK9lGo$VKQeE9iQ@PCMA z*AOIt0tiYVOYj)r5x~waI%SyjXr8Mhj1m**@K=5bLpRav5&|aEe4ymrGK?oZ8ukgu zsKyA*zC^$!9s&p?WhR(cVNwQJWl{lIV^RfKXHo;%U{VL!WYPfHV$uZJX3_$Af=L@( zK{_Bi9O;7WGFbq3lF1^-6(&m{Pcu0M5;@{BgoU1EYG~41Ma`Rz+St&Gi26AJ8t9`2 zK)60Sd;Ia*+9166boJfaZ(jzkiDQ|vM!BmSymh`ZPGwvp(o{)T3Cai|8h#%JdJ6~i z8-#HGwR?8v`_3@D|LN%b`^$HS;pf}0&OJH4H{{cpr~FZ%N8Y?jZv|b40wGLup`~Rd ziBagfHik_;6)H{q$hsD~o|J{_7SPkESEOh>gUe{6orp76qseg^c^t(iXGwOz(KOM< zF|)oGD=tf`6dvW>@?xtBAwhu5(LTszW;m94Qs@`P z1r@zj&46LD3Zv z!gy091h*r^G?96X?wB6rT;V^-9Fr)z7nY!2+T=@89Kas6$rJw5V!S8Ui#BfXqO|%C DzS#NW diff --git a/keras_csp/data_augment.pyc b/keras_csp/data_augment.pyc deleted file mode 100644 index 50299090b10fea47f5feecd89d464ed6ca41a9ff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8172 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 Vm73F2{IzBm7Z#`9ohqET@NanTj$Z%( diff --git a/keras_csp/data_generators.pyc b/keras_csp/data_generators.pyc deleted file mode 100644 index dbe5135651763d40f233d7cf4aae60cdf0962653..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11841 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 GZT$iWKUr1) diff --git a/keras_csp/losses.pyc b/keras_csp/losses.pyc deleted file mode 100644 index 47003c550c8443d0d274694709397d251cc97d76..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3378 zcmchaL2nyH6vyAp+D@FNG&Bxzp%M~3;0v)T5L^HU<-nm*gtig~3t`#b@n)0tuGtxr z25bqGBJOa46Q6)PLfrTU91!9_;mRcv9{~PuW}7(0#M>%j<(<5lee-5^=l6dz@&3BH za;x_Fdwt3;iND*pb&4XuPf$!W6x5a^xGpL7Xjr0liG-50U#4TUdUPNud&~AHQCy++ z5+!IaQ+t_$3f(7aS1DMs#tH??*0@4J)f%f5l<00_1!G2k<7x<4W(h^F+doiA;2P>^ z=y#0@(=6(D<4!+IwN{DA($SIOnVZ3G_|neJKmU03*;bz$I3kDH!L5HpR712cXd>)P zi9VC_3_*hu-I!qh_BY>2TBl=4Q%Qwfr`{qzulTt2X^AEtf3`yJQpZZH*QRBflx&}i zU(LOL9qYDUD-_;Euh0YoRA_U$L|Bgfh3}hxLP1kNa@uE!CX#B$f@&PZ&3Bpbp*N;g znpDBbGFEdpLO~HPa>TTRTqQbb{y4le= zjC_j`W0R?1+*chv9$FBG-Fwk+JhY6O3Z5TzOg2`zIfAzh*^j$gM+4w#qBQBm0Mu0B zJxXZEivb%(=q2L*8tAR6q8p2EDTv^nUTTbOG^| zAojdNiBM&`%#oo{t0hZSw0Ixo{q|=BTT|=sS^ku(~~MSX765 zDpRHeD^^2dU=|b-k*xni}et^k=Q-s;*G^FUG7?djsU!Z~&lreBDMz%SffUHmiP(P0*N2xcDeoaX-x zd`|vJ%c6{ouibIv6ndX?pTnCs5WmL79MJs@e(($mCkmv~OQo4r;%GkHg6VJ;Uy3h8 zTg=D#@PELW)9u3bn&s$m@Px>UB-D#=^JZ|9Hm!m{5cj0GfmFw}Bd*33@Qb|tpU7dc za6Nc7mCUb_Z)c@ll6U|Lemv7{}^Oo}%W-uZcBzU0jnD LuUfCJR;&L2bdYR= diff --git a/keras_csp/mobilenet.pyc b/keras_csp/mobilenet.pyc deleted file mode 100644 index 71946eb22deb93e204ae1e783c666d992f9cc589..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16221 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 diff --git a/keras_csp/nms/__init__.pyc b/keras_csp/nms/__init__.pyc deleted file mode 100644 index f3d0bba64ae43e803f05d309170a96cb7edfa05a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 160 zcmZSn%*!=l=k(}g1}I1X8Urt0TpmX@bx z>K7E{XQd{W6zgZF79|$zCTEsZ7Niyx=jZ7rr{esm6%Ayq#L*Qjr8Q!r~;L3{PTrP ziegCo=a)7vDPmBru}jIW>*6{cUmFC6;!yO&J&`bFo-BkH{sjTjd*vm6L=AHhfPDyb zgHux3K4xWUpVX)3sY&ZVOsUGowFzMAn}bujV=^zbD`QO3KAOJLm@3;pJ%7_Tw*QKj z@!7Pm^DRz=Rto;tx%@NH1z5v4@pY z)Q%oh+f itGYu6C!F?%`G26#9G~V!R+)On*s<9c`=S>-=>7ptQ~f0X diff --git a/keras_csp/parallel_model.pyc b/keras_csp/parallel_model.pyc deleted file mode 100644 index f2ff41b8e2d5da6b3483624807fec9d0e22ad375..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7247 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 ZxHJx!N%sN@k|S=VR7RLM2H0cH{{alp!!ZB= diff --git a/keras_csp/resnet50.pyc b/keras_csp/resnet50.pyc deleted file mode 100644 index c11bf9634a6a75a4fc78b71ad9b78470e3a603cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22160 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 diff --git a/keras_csp/utilsfunc.pyc b/keras_csp/utilsfunc.pyc deleted file mode 100644 index 01c074a6050a123c78d416eb8da42ad1533ed676..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7701 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 From 2d0f4ef33cb5bcc2232b3269e18ebf1dcd9e8bbf Mon Sep 17 00:00:00 2001 From: dominik dienlin Date: Tue, 6 Aug 2019 18:00:45 +0200 Subject: [PATCH 09/18] removed third brightness parameter (not being used anywhere) --- keras_csp/config.py | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/keras_csp/config.py b/keras_csp/config.py index f46b12f..c739c8a 100755 --- a/keras_csp/config.py +++ b/keras_csp/config.py @@ -1,27 +1,26 @@ - class Config(object): - def __init__(self): - self.gpu_ids = '0' - self.onegpu = 2 - self.num_epochs = 150 - self.add_epoch = 0 - self.iter_per_epoch = 2000 - self.init_lr = 1e-4 - self.alpha = 0.999 + def __init__(self): + self.gpu_ids = '0' + self.onegpu = 2 + self.num_epochs = 150 + self.add_epoch = 0 + self.iter_per_epoch = 2000 + self.init_lr = 1e-4 + self.alpha = 0.999 - # setting for network architechture - self.network = 'resnet50' # or 'mobilenet' - self.point = 'center' # or 'top', 'bottom - self.scale = 'h' # or 'w', 'hw' - self.num_scale = 1 # 1 for height (or width) prediction, 2 for height+width prediction - self.offset = False # append offset prediction or not - self.down = 4 # downsampling rate of the feature map for detection - self.radius = 2 # surrounding areas of positives for the scale map + # setting for network architechture + self.network = 'resnet50' # or 'mobilenet' + self.point = 'center' # or 'top', 'bottom + self.scale = 'h' # or 'w', 'hw' + self.num_scale = 1 # 1 for height (or width) prediction, 2 for height+width prediction + self.offset = False # append offset prediction or not + self.down = 4 # downsampling rate of the feature map for detection + self.radius = 2 # surrounding areas of positives for the scale map - # setting for data augmentation - self.use_horizontal_flips = True - self.brightness = (0.5, 2, 0.5) - self.size_train = (336, 448) + # setting for data augmentation + self.use_horizontal_flips = True + self.brightness = (0.5, 2) + self.size_train = (336, 448) - # image channel-wise mean to subtract, the order is BGR - self.img_channel_mean = [103.939, 116.779, 123.68] + # image channel-wise mean to subtract, the order is BGR + self.img_channel_mean = [103.939, 116.779, 123.68] From 14a5910c8f0382ea2d47d9f9c5b232195d8503fb Mon Sep 17 00:00:00 2001 From: dominik andreas Date: Wed, 7 Aug 2019 07:34:52 +0200 Subject: [PATCH 10/18] bugfix for getting epoch from checkpoint --- train_city.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/train_city.py b/train_city.py index 8231c7a..8df358f 100644 --- a/train_city.py +++ b/train_city.py @@ -51,8 +51,9 @@ checkpoint_paths = glob.glob(out_path + "/net*.hdf5") checkpoint_names = [f.split("/")[-1] for f in checkpoint_paths] epochs = [*map(int, [f.split("net_e")[1].split("_")[0] for f in checkpoint_names if "net_e" in f])] - epoch = np.argmax(epochs) - weight_path = checkpoint_paths[epoch] + max_epoch_idx = np.argmax(epochs) + epoch = epochs[max_epoch_idx] + weight_path = checkpoint_paths[max_epoch_idx] input_shape_img = (C.size_train[0], C.size_train[1], 3) From 5fd56c13ef591c678f25bda29d02938b72bd8b70 Mon Sep 17 00:00:00 2001 From: dominik andreas Date: Wed, 7 Aug 2019 08:04:03 +0200 Subject: [PATCH 11/18] fix for https://github.com/liuwei16/CSP/issues/49 for building extensions (adapted from https://github.com/rbgirshick/py-faster-rcnn/blob/master/lib/setup.py) --- setup.py | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 setup.py diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..8c53902 --- /dev/null +++ b/setup.py @@ -0,0 +1,127 @@ +import os +from Cython.Distutils import build_ext +from distutils.core import setup, Extension +from Cython.Build import cythonize +import numpy as np + +try: + numpy_include = np.get_include() +except AttributeError: + numpy_include = np.get_numpy_include() + +def customize_compiler_for_nvcc(self): + """inject deep into distutils to customize how the dispatch + to gcc/nvcc works. + If you subclass UnixCCompiler, it's not trivial to get your subclass + injected in, and still have the right customizations (i.e. + distutils.sysconfig.customize_compiler) run on it. So instead of going + the OO route, I have this. Note, it's kindof like a wierd functional + subclassing going on.""" + + # tell the compiler it can processes .cu + self.src_extensions.append('.cu') + + # save references to the default compiler_so and _comple methods + default_compiler_so = self.compiler_so + super = self._compile + + # now redefine the _compile method. This gets executed for each + # object but distutils doesn't have the ability to change compilers + # based on source extension: we add it. + def _compile(obj, src, ext, cc_args, extra_postargs, pp_opts): + if os.path.splitext(src)[1] == '.cu': + # use the cuda for .cu files + self.set_executable('compiler_so', CUDA['nvcc']) + # use only a subset of the extra_postargs, which are 1-1 translated + # from the extra_compile_args in the Extension class + postargs = extra_postargs['nvcc'] + else: + postargs = extra_postargs['gcc'] + + super(obj, src, ext, cc_args, postargs, pp_opts) + # reset the default compiler_so, which we might have changed for cuda + self.compiler_so = default_compiler_so + + # inject our redefined _compile method into the class + self._compile = _compile + + +# run the customize_compiler +class custom_build_ext(build_ext): + def build_extensions(self): + customize_compiler_for_nvcc(self.compiler) + build_ext.build_extensions(self) + + +def find_in_path(name, path): + "Find a file in a search path" + # Adapted fom + # http://code.activestate.com/recipes/52224-find-a-file-given-a-search-path/ + for dir in path.split(os.pathsep): + binpath = os.path.join(dir, name) + if os.path.exists(binpath): + return os.path.abspath(binpath) + return None + + +def locate_cuda(): + """Locate the CUDA environment on the system + Returns a dict with keys 'home', 'nvcc', 'include', and 'lib64' + and values giving the absolute path to each directory. + Starts by looking for the CUDAHOME env variable. If not found, everything + is based on finding 'nvcc' in the PATH. + """ + + # first check if the CUDAHOME env variable is in use + if 'CUDAHOME' in os.environ: + home = os.environ['CUDAHOME'] + nvcc = os.path.join(home, 'bin', 'nvcc') + else: + # otherwise, search the PATH for NVCC + default_path = os.path.join(os.sep, 'usr', 'local', 'cuda', 'bin') + nvcc = find_in_path('nvcc', os.environ['PATH'] + os.pathsep + default_path) + if nvcc is None: + raise EnvironmentError('The nvcc binary could not be ' + 'located in your $PATH. Either add it to your path, or set $CUDAHOME') + home = os.path.dirname(os.path.dirname(nvcc)) + + cudaconfig = {'home':home, 'nvcc':nvcc, + 'include': os.path.join(home, 'include'), + 'lib64': os.path.join(home, 'lib64')} + for k, v in cudaconfig.items(): + if not os.path.exists(v): + raise EnvironmentError('The CUDA %s path could not be located in %s' % (k, v)) + + return cudaconfig +CUDA = locate_cuda() + +ext_modules = [ + Extension( + "keras_csp.nms.cpu_nms", + ["keras_csp/nms/cpu_nms.pyx"], + extra_compile_args={'gcc': ["-Wno-cpp", "-Wno-unused-function"]}, + include_dirs = [numpy_include] + ), + Extension('keras_csp.nms.gpu_nms', + ['keras_csp/nms/nms_kernel.cu', 'keras_csp/nms/gpu_nms.pyx'], + library_dirs=[CUDA['lib64']], + libraries=['cudart'], + language='c++', + runtime_library_dirs=[CUDA['lib64']], + # this syntax is specific to this build system + # we're only going to use certain compiler args with nvcc and not with + # gcc the implementation of this trick is in customize_compiler() below + extra_compile_args={'gcc': ["-Wno-unused-function"], + 'nvcc': ['-arch=sm_35', + '--ptxas-options=-v', + '-c', + '--compiler-options', + "'-fPIC'"]}, + include_dirs = [numpy_include, CUDA['include']] + ) +] + +setup( + ext_modules=ext_modules, + cmdclass={'build_ext': custom_build_ext}, +) From 52eb6f5177d60031141cc55e9a652f39ec87219c Mon Sep 17 00:00:00 2001 From: dominik andreas Date: Wed, 7 Aug 2019 08:06:25 +0200 Subject: [PATCH 12/18] added comment on how to build, adapted requirements --- README.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 55d7d1f..c0c49a8 100644 --- a/README.md +++ b/README.md @@ -10,10 +10,10 @@ Besides the superority on pedestrian detection demonstrated in the paper, we tak ### Dependencies -* Python 2.7 -* Tensorflow 1.4.1 -* Keras 2.0.6 -* OpenCV 3.4.1.15 +* Python >= 3.6 +* Tensorflow >= 1.1.3 +* Keras >= 2.0.6 +* OpenCV >= 3.4.1.15 ## Contents 1. [Installation](#installation) @@ -33,6 +33,12 @@ Besides the superority on pedestrian detection demonstrated in the paper, we tak pip install -r requirements.txt ``` +3. Build dependencies +``` + python setup.py build_ext --inplace +``` + + ### Preparation 1. Download the dataset. From 5e41a2e31ea69f26cd165edfaf0981b016395a64 Mon Sep 17 00:00:00 2001 From: dominik andreas Date: Wed, 7 Aug 2019 08:06:57 +0200 Subject: [PATCH 13/18] cleanup --- keras_csp/bbox_process.py | 48 +++++++++++++----------- keras_csp/data_generators.py | 6 ++- test_city.py | 71 ++++++++++++++++++------------------ train_city.py | 1 - 4 files changed, 67 insertions(+), 59 deletions(-) diff --git a/keras_csp/bbox_process.py b/keras_csp/bbox_process.py index 6cd190b..d2f0553 100644 --- a/keras_csp/bbox_process.py +++ b/keras_csp/bbox_process.py @@ -1,18 +1,18 @@ - import numpy as np from keras_csp.nms_wrapper import nms -def parse_det(Y, C, score=0.1, down=4,scale='h'): + +def parse_det(Y, C, score=0.1, down=4, scale='h'): seman = Y[0][0, :, :, 0] - if scale=='h': - height = np.exp(Y[1][0, :, :, 0])*down - width = 0.41*height - elif scale=='w': - width = np.exp(Y[1][0, :, :, 0])*down - height = width/0.41 - elif scale=='hw': - height = np.exp(Y[1][0, :, :, 0])*down - width = np.exp(Y[1][0, :, :, 1])*down + if scale == 'h': + height = np.exp(Y[1][0, :, :, 0]) * down + width = 0.41 * height + elif scale == 'w': + width = np.exp(Y[1][0, :, :, 0]) * down + height = width / 0.41 + elif scale == 'hw': + height = np.exp(Y[1][0, :, :, 0]) * down + width = np.exp(Y[1][0, :, :, 1]) * down y_c, x_c = np.where(seman > score) boxs = [] if len(y_c) > 0: @@ -20,13 +20,14 @@ def parse_det(Y, C, score=0.1, down=4,scale='h'): h = height[y_c[i], x_c[i]] w = width[y_c[i], x_c[i]] s = seman[y_c[i], x_c[i]] - x1, y1 = max(0, (x_c[i]+0.5) * down - w / 2), max(0, (y_c[i]+0.5) * down - h / 2) + x1, y1 = max(0, (x_c[i] + 0.5) * down - w / 2), max(0, (y_c[i] + 0.5) * down - h / 2) boxs.append([x1, y1, min(x1 + w, C.size_test[1]), min(y1 + h, C.size_test[0]), s]) boxs = np.asarray(boxs, dtype=np.float32) keep = nms(boxs, 0.5, usegpu=False, gpu_id=0) boxs = boxs[keep, :] return boxs + def parse_det_top(Y, C, score=0.1): seman = Y[0][0, :, :, 0] height = Y[1][0, :, :, 0] @@ -44,6 +45,7 @@ def parse_det_top(Y, C, score=0.1): boxs = boxs[keep, :] return boxs + def parse_det_bottom(Y, C, score=0.1): seman = Y[0][0, :, :, 0] height = Y[1][0, :, :, 0] @@ -54,14 +56,15 @@ def parse_det_bottom(Y, C, score=0.1): h = np.exp(height[y_c[i], x_c[i]]) * 4 w = 0.41 * h s = seman[y_c[i], x_c[i]] - x1, y1 = max(0, x_c[i] * 4 + 2 - w / 2), max(0, y_c[i] * 4 + 2-h) + x1, y1 = max(0, x_c[i] * 4 + 2 - w / 2), max(0, y_c[i] * 4 + 2 - h) boxs.append([x1, y1, min(x1 + w, C.size_test[1]), min(y1 + h, C.size_test[0]), s]) boxs = np.asarray(boxs, dtype=np.float32) keep = nms(boxs, 0.5, usegpu=False, gpu_id=0) boxs = boxs[keep, :] return boxs -def parse_det_offset(Y, C, score=0.1,down=4): + +def parse_det_offset(Y, C, score=0.1, down=4): seman = Y[0][0, :, :, 0] height = Y[1][0, :, :, 0] offset_y = Y[2][0, :, :, 0] @@ -71,7 +74,7 @@ def parse_det_offset(Y, C, score=0.1,down=4): if len(y_c) > 0: for i in range(len(y_c)): h = np.exp(height[y_c[i], x_c[i]]) * down - w = 0.41*h + w = 0.41 * h o_y = offset_y[y_c[i], x_c[i]] o_x = offset_x[y_c[i], x_c[i]] s = seman[y_c[i], x_c[i]] @@ -82,7 +85,8 @@ def parse_det_offset(Y, C, score=0.1,down=4): boxs = boxs[keep, :] return boxs -def parse_wider_offset(Y, C, score=0.1,down=4,nmsthre=0.5): + +def parse_wider_offset(Y, C, score=0.1, down=4, nmsthre=0.5): seman = Y[0][0, :, :, 0] height = Y[1][0, :, :, 0] width = Y[1][0, :, :, 1] @@ -101,12 +105,13 @@ def parse_wider_offset(Y, C, score=0.1,down=4,nmsthre=0.5): x1, y1 = min(x1, C.size_test[1]), min(y1, C.size_test[0]) boxs.append([x1, y1, min(x1 + w, C.size_test[1]), min(y1 + h, C.size_test[0]), s]) boxs = np.asarray(boxs, dtype=np.float32) - #keep = nms(boxs, nmsthre, usegpu=False, gpu_id=0) - #boxs = boxs[keep, :] - boxs = soft_bbox_vote(boxs,thre=nmsthre) + # keep = nms(boxs, nmsthre, usegpu=False, gpu_id=0) + # boxs = boxs[keep, :] + boxs = soft_bbox_vote(boxs, thre=nmsthre) return boxs -def soft_bbox_vote(det,thre=0.35,score=0.05): + +def soft_bbox_vote(det, thre=0.35, score=0.05): if det.shape[0] <= 1: return det order = det[:, 4].ravel().argsort()[::-1] @@ -160,7 +165,8 @@ def soft_bbox_vote(det,thre=0.35,score=0.05): dets = dets[order, :] return dets -def bbox_vote(det,thre): + +def bbox_vote(det, thre): if det.shape[0] <= 1: return det order = det[:, 4].ravel().argsort()[::-1] diff --git a/keras_csp/data_generators.py b/keras_csp/data_generators.py index 2cd76ad..98c7158 100644 --- a/keras_csp/data_generators.py +++ b/keras_csp/data_generators.py @@ -132,7 +132,8 @@ def gaussian(kernel): scale_map[y2-r:y2+r+1, c_x-r:c_x+r+1, 0] = np.log(gts[ind,3]-gts[ind,1]) scale_map[y2-r:y2+r+1, c_x-r:c_x+r+1, 1] = 1 - return seman_map,scale_map + return seman_map, scale_map + def get_data(ped_data, C, batchsize = 8): current_ped = 0 @@ -152,7 +153,7 @@ def get_data(ped_data, C, batchsize = 8): elif C.point == 'bottom': y_seman, y_height = calc_gt_bottom(C, img_data) else: - y_seman, y_height = calc_gt_center(C, img_data,down=C.down, scale=C.scale, offset=False) + y_seman, y_height = calc_gt_center(C, img_data, down=C.down, scale=C.scale, offset=False) x_img = x_img.astype(np.float32) x_img[:, :, 0] -= C.img_channel_mean[0] @@ -177,6 +178,7 @@ def get_data(ped_data, C, batchsize = 8): else: yield np.copy(x_img_batch), [np.copy(y_seman_batch), np.copy(y_height_batch)] + def get_data_hybrid(ped_data, emp_data, C, batchsize = 8,hyratio=0.5): current_ped = 0 current_emp = 0 diff --git a/test_city.py b/test_city.py index a3c5838..4f787a9 100644 --- a/test_city.py +++ b/test_city.py @@ -1,4 +1,3 @@ - import os import time import pickle @@ -12,7 +11,7 @@ C.offset = True cache_path = 'data/cache/cityperson/val_500' with open(cache_path, 'rb') as fid: - val_data = pickle.load(fid) + val_data = pickle.load(fid, encoding='latin1') num_imgs = len(val_data) print('num of val samples: {}'.format(num_imgs)) @@ -21,9 +20,9 @@ img_input = Input(shape=input_shape_img) # define the base network (resnet here, can be MobileNet, etc) -if C.network=='resnet50': +if C.network == 'resnet50': from keras_csp import resnet50 as nn -elif C.network=='mobilenet': +elif C.network == 'mobilenet': from keras_csp import mobilenet as nn else: raise NotImplementedError('Not support network: {}'.format(C.network)) @@ -39,37 +38,39 @@ w_path = 'output/valmodels/city/%s/nooff' % (C.scale) out_path = 'output/valresults/city/%s/nooff' % (C.scale) if not os.path.exists(out_path): - os.makedirs(out_path) + os.makedirs(out_path) files = sorted(os.listdir(w_path)) # get the results from epoch 51 to epoch 150 -for w_ind in range(51,151): - for f in files: - if f.split('_')[0] == 'net' and int(f.split('_')[1][1:]) == w_ind: - cur_file = f - break - weight1 = os.path.join(w_path, cur_file) - print('load weights from {}'.format(weight1)) - model.load_weights(weight1, by_name=True) - res_path = os.path.join(out_path, '%03d'%int(str(w_ind))) - if not os.path.exists(res_path): - os.makedirs(res_path) - print(res_path) - res_file = os.path.join(res_path, 'val_det.txt') - res_all = [] - start_time = time.time() - for f in range(num_imgs): - filepath = val_data[f]['filepath'] - img = cv2.imread(filepath) - x_rcnn = format_img(img, C) - Y = model.predict(x_rcnn) +for w_ind in range(150, 151): + for f in files: + if f.split('_')[0] == 'net' and int(f.split('_')[1][1:]) == w_ind: + cur_file = f + break + weight1 = os.path.join(w_path, cur_file) + print('load weights from {}'.format(weight1)) + model.load_weights(weight1, by_name=True) + res_path = os.path.join(out_path, '%03d' % int(str(w_ind))) + if not os.path.exists(res_path): + os.makedirs(res_path) + print(res_path) + res_file = os.path.join(res_path, 'val_det.txt') + res_all = [] + start_time = time.time() + for f in range(num_imgs): + filepath = val_data[f]['filepath'] + img = cv2.imread(filepath) + if img is None: + raise RuntimeError("image at %s not found" % filepath) + x_rcnn = format_img(img, C) + Y = model.predict(x_rcnn) - if C.offset: - boxes = bbox_process.parse_det_offset(Y, C, score=0.1,down=4) - else: - boxes = bbox_process.parse_det(Y, C, score=0.1, down=4, scale=C.scale) - if len(boxes)>0: - f_res = np.repeat(f+1, len(boxes), axis=0).reshape((-1, 1)) - boxes[:, [2, 3]] -= boxes[:, [0, 1]] - res_all += np.concatenate((f_res, boxes), axis=-1).tolist() - np.savetxt(res_file, np.array(res_all), fmt='%6f') - print(time.time() - start_time) + if C.offset: + boxes = bbox_process.parse_det_offset(Y, C, score=0.1, down=4) + else: + boxes = bbox_process.parse_det(Y, C, score=0.1, down=4, scale=C.scale) + if len(boxes) > 0: + f_res = np.repeat(f + 1, len(boxes), axis=0).reshape((-1, 1)) + boxes[:, [2, 3]] -= boxes[:, [0, 1]] + res_all += np.concatenate((f_res, boxes), axis=-1).tolist() + np.savetxt(res_file, np.array(res_all), fmt='%6f') + print(time.time() - start_time) diff --git a/train_city.py b/train_city.py index 8df358f..f035ae4 100644 --- a/train_city.py +++ b/train_city.py @@ -47,7 +47,6 @@ os.makedirs(out_path) epoch = 0 else: - int_strings = [*map(str, range(10))] checkpoint_paths = glob.glob(out_path + "/net*.hdf5") checkpoint_names = [f.split("/")[-1] for f in checkpoint_paths] epochs = [*map(int, [f.split("net_e")[1].split("_")[0] for f in checkpoint_names if "net_e" in f])] From 6e912ccd39c12925fa03cf7e514550e442b2d80b Mon Sep 17 00:00:00 2001 From: dominik andreas Date: Wed, 7 Aug 2019 08:11:45 +0200 Subject: [PATCH 14/18] added .gitignore file --- .gitignore | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7756454 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.idea/ +build/ +data/ +__pycache__ +output From b207c093ef6d7e38187d9c528a7174587a86c244 Mon Sep 17 00:00:00 2001 From: dominik andreas Date: Wed, 7 Aug 2019 08:15:44 +0200 Subject: [PATCH 15/18] PEP8 cleanup, updated readme for weight downloading --- README.md | 5 + download_weights.sh | 0 generate_cache_caltech.py | 77 +-- generate_cache_city.py | 101 ++-- generate_cache_wider.py | 62 +-- keras_csp/bbox_transform.py | 8 +- keras_csp/data_augment.py | 13 +- keras_csp/data_generators.py | 580 ++++++++++++----------- keras_csp/keras_layer_L2Normalization.py | 1 + keras_csp/losses.py | 74 +-- keras_csp/utilsfunc.py | 255 +++++----- setup.py | 41 +- test_caltech.py | 91 ++-- test_wider_ms.py | 262 +++++----- train_caltech.py | 35 +- train_city.py | 28 +- train_wider.py | 28 +- 17 files changed, 860 insertions(+), 801 deletions(-) mode change 100644 => 100755 download_weights.sh diff --git a/README.md b/README.md index c0c49a8..79c6462 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,11 @@ Besides the superority on pedestrian detection demonstrated in the paper, we tak python setup.py build_ext --inplace ``` +4. Download pretrained weights: +``` +./download_weights.sh +``` + ### Preparation 1. Download the dataset. diff --git a/download_weights.sh b/download_weights.sh old mode 100644 new mode 100755 diff --git a/generate_cache_caltech.py b/generate_cache_caltech.py index 30fb028..c1923d2 100755 --- a/generate_cache_caltech.py +++ b/generate_cache_caltech.py @@ -18,46 +18,47 @@ box_count = 0 files = sorted(os.listdir(all_anno_path)) for l in range(len(files)): - gtname = files[l] - imgname = files[l].split('.')[0]+'.jpg' - img_path = os.path.join(all_img_path, imgname) - gt_path = os.path.join(all_anno_path, gtname) + gtname = files[l] + imgname = files[l].split('.')[0] + '.jpg' + img_path = os.path.join(all_img_path, imgname) + gt_path = os.path.join(all_anno_path, gtname) - boxes = [] - ig_boxes = [] - with open(gt_path, 'rb') as fid: - lines = fid.readlines() - if len(lines)>1: - for i in range(1, len(lines)): - info = lines[i].strip().split(' ') - label = info[0] - occ, ignore = info[5], info[10] - x1, y1 = max(int(float(info[1])), 0), max(int(float(info[2])), 0) - w, h = min(int(float(info[3])), cols - x1 - 1), min(int(float(info[4])), rows - y1 - 1) - box = np.array([int(x1), int(y1), int(x1) + int(w), int(y1) + int(h)]) - if int(ignore) == 0: - boxes.append(box) - else: - ig_boxes.append(box) - boxes = np.array(boxes) - ig_boxes = np.array(ig_boxes) + boxes = [] + ig_boxes = [] + with open(gt_path, 'rb') as fid: + lines = fid.readlines() + if len(lines) > 1: + for i in range(1, len(lines)): + info = lines[i].strip().split(' ') + label = info[0] + occ, ignore = info[5], info[10] + x1, y1 = max(int(float(info[1])), 0), max(int(float(info[2])), 0) + w, h = min(int(float(info[3])), cols - x1 - 1), min(int(float(info[4])), rows - y1 - 1) + box = np.array([int(x1), int(y1), int(x1) + int(w), int(y1) + int(h)]) + if int(ignore) == 0: + boxes.append(box) + else: + ig_boxes.append(box) + boxes = np.array(boxes) + ig_boxes = np.array(ig_boxes) - annotation = {} - annotation['filepath'] = img_path - box_count += len(boxes) - iggt_count += len(ig_boxes) - annotation['bboxes'] = boxes - annotation['ignoreareas'] = ig_boxes - if len(boxes) == 0: - image_data_nogt.append(annotation) - else: - image_data_gt.append(annotation) - valid_count += 1 -print('{} images and {} valid images, {} valid gt and {} ignored gt'.format(len(files), valid_count, box_count, iggt_count)) + annotation = {} + annotation['filepath'] = img_path + box_count += len(boxes) + iggt_count += len(ig_boxes) + annotation['bboxes'] = boxes + annotation['ignoreareas'] = ig_boxes + if len(boxes) == 0: + image_data_nogt.append(annotation) + else: + image_data_gt.append(annotation) + valid_count += 1 +print('{} images and {} valid images, {} valid gt and {} ignored gt'.format(len(files), valid_count, box_count, + iggt_count)) if not os.path.exists(res_path_gt): - with open(res_path_gt, 'wb') as fid: - pickle.dump(image_data_gt, fid, pickle.HIGHEST_PROTOCOL) + with open(res_path_gt, 'wb') as fid: + pickle.dump(image_data_gt, fid, pickle.HIGHEST_PROTOCOL) if not os.path.exists(res_path_nogt): - with open(res_path_nogt, 'wb') as fid: - pickle.dump(image_data_nogt, fid, pickle.HIGHEST_PROTOCOL) \ No newline at end of file + with open(res_path_nogt, 'wb') as fid: + pickle.dump(image_data_nogt, fid, pickle.HIGHEST_PROTOCOL) diff --git a/generate_cache_city.py b/generate_cache_city.py index 7e21f39..00c230e 100755 --- a/generate_cache_city.py +++ b/generate_cache_city.py @@ -1,4 +1,3 @@ - import os import cv2 import pickle @@ -15,54 +14,56 @@ rows, cols = 1024, 2048 for type in types: - anno_path = os.path.join(all_anno_path, 'anno_'+type+'.mat') - res_path = os.path.join('data/cache/cityperson', type) - image_data = [] - annos = scio.loadmat(anno_path) - index = 'anno_'+type+'_aligned' - valid_count = 0 - iggt_count = 0 - box_count = 0 - for l in range(len(annos[index][0])): - anno = annos[index][0][l] - cityname = anno[0][0][0][0].encode() - imgname = anno[0][0][1][0].encode() - gts = anno[0][0][2] - img_path = os.path.join(all_img_path, type + '/'+ cityname+'/'+imgname) - boxes = [] - ig_boxes = [] - vis_boxes = [] - for i in range(len(gts)): - label, x1, y1, w, h = gts[i, :5] - x1, y1 = max(int(x1), 0), max(int(y1), 0) - w, h = min(int(w), cols - x1 -1), min(int(h), rows - y1 -1) - xv1, yv1, wv, hv = gts[i, 6:] - xv1, yv1 = max(int(xv1), 0), max(int(yv1), 0) - wv, hv = min(int(wv), cols - xv1 - 1), min(int(hv), rows - yv1 - 1) + anno_path = os.path.join(all_anno_path, 'anno_' + type + '.mat') + res_path = os.path.join('data/cache/cityperson', type) + image_data = [] + annos = scio.loadmat(anno_path) + index = 'anno_' + type + '_aligned' + valid_count = 0 + iggt_count = 0 + box_count = 0 + for l in range(len(annos[index][0])): + anno = annos[index][0][l] + cityname = anno[0][0][0][0].encode() + imgname = anno[0][0][1][0].encode() + gts = anno[0][0][2] + img_path = os.path.join(all_img_path, type + '/' + cityname + '/' + imgname) + boxes = [] + ig_boxes = [] + vis_boxes = [] + for i in range(len(gts)): + label, x1, y1, w, h = gts[i, :5] + x1, y1 = max(int(x1), 0), max(int(y1), 0) + w, h = min(int(w), cols - x1 - 1), min(int(h), rows - y1 - 1) + xv1, yv1, wv, hv = gts[i, 6:] + xv1, yv1 = max(int(xv1), 0), max(int(yv1), 0) + wv, hv = min(int(wv), cols - xv1 - 1), min(int(hv), rows - yv1 - 1) - if label == 1 and h>=50: - box = np.array([int(x1), int(y1), int(x1)+int(w), int(y1)+int(h)]) - boxes.append(box) - vis_box = np.array([int(xv1), int(yv1), int(xv1)+int(wv), int(yv1)+int(hv)]) - vis_boxes.append(vis_box) - else: - ig_box = np.array([int(x1), int(y1), int(x1)+int(w), int(y1)+int(h)]) - ig_boxes.append(ig_box) - boxes = np.array(boxes) - vis_boxes = np.array(vis_boxes) - ig_boxes = np.array(ig_boxes) + if label == 1 and h >= 50: + box = np.array([int(x1), int(y1), int(x1) + int(w), int(y1) + int(h)]) + boxes.append(box) + vis_box = np.array([int(xv1), int(yv1), int(xv1) + int(wv), int(yv1) + int(hv)]) + vis_boxes.append(vis_box) + else: + ig_box = np.array([int(x1), int(y1), int(x1) + int(w), int(y1) + int(h)]) + ig_boxes.append(ig_box) + boxes = np.array(boxes) + vis_boxes = np.array(vis_boxes) + ig_boxes = np.array(ig_boxes) - if len(boxes)>0: - valid_count += 1 - annotation = {} - annotation['filepath'] = img_path - box_count += len(boxes) - iggt_count += len(ig_boxes) - annotation['bboxes'] = boxes - annotation['vis_bboxes'] = vis_boxes - annotation['ignoreareas'] = ig_boxes - image_data.append(annotation) - if not os.path.exists(res_path): - with open(res_path, 'wb') as fid: - pickle.dump(image_data, fid, pickle.HIGHEST_PROTOCOL) - print('{} has {} images and {} valid images, {} valid gt and {} ignored gt'.format(type, len(annos[index][0]), valid_count, box_count, iggt_count)) + if len(boxes) > 0: + valid_count += 1 + annotation = {} + annotation['filepath'] = img_path + box_count += len(boxes) + iggt_count += len(ig_boxes) + annotation['bboxes'] = boxes + annotation['vis_bboxes'] = vis_boxes + annotation['ignoreareas'] = ig_boxes + image_data.append(annotation) + if not os.path.exists(res_path): + with open(res_path, 'wb') as fid: + pickle.dump(image_data, fid, pickle.HIGHEST_PROTOCOL) + print('{} has {} images and {} valid images, {} valid gt and {} ignored gt'.format(type, len(annos[index][0]), + valid_count, box_count, + iggt_count)) diff --git a/generate_cache_wider.py b/generate_cache_wider.py index a76c940..15145c0 100755 --- a/generate_cache_wider.py +++ b/generate_cache_wider.py @@ -6,7 +6,7 @@ root_dir = 'data/WiderFace/' img_path = os.path.join(root_dir, 'WIDER_train/images') -anno_path = os.path.join(root_dir, 'wider_face_split','wider_face_train_bbx_gt.txt') +anno_path = os.path.join(root_dir, 'wider_face_split', 'wider_face_train_bbx_gt.txt') # anno_path = os.path.join(root_dir, 'wider_face_split','wider_face_test_filelist.txt') res_path = 'data/cache/train' @@ -16,38 +16,38 @@ img_count = 0 box_count = 0 with open(anno_path, 'rb') as fid: - lines = fid.readlines() + lines = fid.readlines() num_lines = len(lines) index = 0 -while index0: - for i in range(num_obj): - info = lines[index+2+i].strip().split(' ') - x1, y1 = max(int(info[0]), 0), max(int(info[1]), 0) - w, h = min(int(info[2]), img_width - x1 - 1), min(int(info[3]), img_height - y1 - 1) - if w>=5 and h>=5: - box = np.array([x1, y1, x1+w, y1+h]) - boxes.append(box) - boxes = np.array(boxes) - box_count += len(boxes) - if len(boxes)>0: - valid_count += 1 - annotation = {} - annotation['filepath'] = filepath - annotation['bboxes'] = boxes - image_data.append(annotation) - index += (2+num_obj) +while index < num_lines: + filename = lines[index].strip() + img_count += 1 + if img_count % 1000 == 0: + print(img_count) + num_obj = int(lines[index + 1]) + filepath = os.path.join(img_path, filename) + img = cv2.imread(filepath) + img_height, img_width = img.shape[:2] + boxes = [] + if num_obj > 0: + for i in range(num_obj): + info = lines[index + 2 + i].strip().split(' ') + x1, y1 = max(int(info[0]), 0), max(int(info[1]), 0) + w, h = min(int(info[2]), img_width - x1 - 1), min(int(info[3]), img_height - y1 - 1) + if w >= 5 and h >= 5: + box = np.array([x1, y1, x1 + w, y1 + h]) + boxes.append(box) + boxes = np.array(boxes) + box_count += len(boxes) + if len(boxes) > 0: + valid_count += 1 + annotation = {} + annotation['filepath'] = filepath + annotation['bboxes'] = boxes + image_data.append(annotation) + index += (2 + num_obj) -print('{} images and {} valid images and {} boxes'.format(img_count, valid_count,box_count)) +print('{} images and {} valid images and {} boxes'.format(img_count, valid_count, box_count)) with open(res_path, 'wb') as fid: - pickle.dump(image_data, fid, pickle.HIGHEST_PROTOCOL) \ No newline at end of file + pickle.dump(image_data, fid, pickle.HIGHEST_PROTOCOL) diff --git a/keras_csp/bbox_transform.py b/keras_csp/bbox_transform.py index c216440..fbc8796 100644 --- a/keras_csp/bbox_transform.py +++ b/keras_csp/bbox_transform.py @@ -7,6 +7,7 @@ import numpy as np + def bbox_transform(ex_rois, gt_rois): ex_widths = ex_rois[:, 2] - ex_rois[:, 0] + 1.0 ex_heights = ex_rois[:, 3] - ex_rois[:, 1] + 1.0 @@ -27,6 +28,7 @@ def bbox_transform(ex_rois, gt_rois): (targets_dx, targets_dy, targets_dw, targets_dh)).transpose() return targets + def bbox_transform_inv(boxes, deltas): if boxes.shape[0] == 0: return np.zeros((0, deltas.shape[1]), dtype=deltas.dtype) @@ -60,7 +62,8 @@ def bbox_transform_inv(boxes, deltas): return pred_boxes -def compute_targets(ex_rois, gt_rois, classifier_regr_std,std): + +def compute_targets(ex_rois, gt_rois, classifier_regr_std, std): """Compute bounding-box regression targets for an image.""" assert ex_rois.shape[0] == gt_rois.shape[0] @@ -70,9 +73,10 @@ def compute_targets(ex_rois, gt_rois, classifier_regr_std,std): targets = bbox_transform(ex_rois, gt_rois) # Optionally normalize targets by a precomputed mean and stdev if std: - targets = targets/np.array(classifier_regr_std) + targets = targets / np.array(classifier_regr_std) return targets + def clip_boxes(boxes, im_shape): # boxes[:, 0::4] = np.maximum(np.minimum(boxes[:, 0::4], im_shape[1] - 1), 0) # # y1 >= 0 diff --git a/keras_csp/data_augment.py b/keras_csp/data_augment.py index 2c014a8..247ab76 100644 --- a/keras_csp/data_augment.py +++ b/keras_csp/data_augment.py @@ -85,20 +85,21 @@ def random_crop(image, gts, igs, crop_size, limit=8): return cropped_image, gts, igs + def random_pave(image, gts, igs, pave_size, limit=8): img_height, img_width = image.shape[0:2] pave_h, pave_w = pave_size # paved_image = np.zeros((pave_h, pave_w, 3), dtype=image.dtype) - paved_image = np.ones((pave_h, pave_w, 3), dtype=image.dtype)*np.mean(image,dtype=int) - pave_x = int(np.random.randint(0, pave_w-img_width+1)) - pave_y = int(np.random.randint(0, pave_h-img_height+1)) - paved_image[pave_y:pave_y+img_height, pave_x:pave_x+img_width] = image + paved_image = np.ones((pave_h, pave_w, 3), dtype=image.dtype) * np.mean(image, dtype=int) + pave_x = int(np.random.randint(0, pave_w - img_width + 1)) + pave_y = int(np.random.randint(0, pave_h - img_height + 1)) + paved_image[pave_y:pave_y + img_height, pave_x:pave_x + img_width] = image # pave detections if len(igs) > 0: igs[:, 0:4:2] += pave_x igs[:, 1:4:2] += pave_y - keep_inds = ((igs[:, 2] - igs[:, 0]) >=8) & \ - ((igs[:, 3] - igs[:, 1]) >=8) + keep_inds = ((igs[:, 2] - igs[:, 0]) >= 8) & \ + ((igs[:, 3] - igs[:, 1]) >= 8) igs = igs[keep_inds] if len(gts) > 0: diff --git a/keras_csp/data_generators.py b/keras_csp/data_generators.py index 98c7158..ad51a46 100644 --- a/keras_csp/data_generators.py +++ b/keras_csp/data_generators.py @@ -1,294 +1,302 @@ - - # import numpy as np # import cv2 import random from . import data_augment from .bbox_transform import * -def calc_gt_center(C, img_data,r=2, down=4,scale='h',offset=True): - def gaussian(kernel): - sigma = ((kernel-1) * 0.5 - 1) * 0.3 + 0.8 - s = 2*(sigma**2) - dx = np.exp(-np.square(np.arange(kernel) - int(kernel / 2)) / s) - return np.reshape(dx,(-1,1)) - gts = np.copy(img_data['bboxes']) - igs = np.copy(img_data['ignoreareas']) - scale_map = np.zeros((int(C.size_train[0]/down), int(C.size_train[1]/down), 2)) - if scale=='hw': - scale_map = np.zeros((int(C.size_train[0] / down), int(C.size_train[1] / down), 3)) - if offset: - offset_map = np.zeros((int(C.size_train[0] / down), int(C.size_train[1] / down), 3)) - seman_map = np.zeros((int(C.size_train[0]/down), int(C.size_train[1]/down), 3)) - seman_map[:,:,1] = 1 - if len(igs) > 0: - igs = igs/down - for ind in range(len(igs)): - x1,y1,x2,y2 = int(igs[ind,0]), int(igs[ind,1]), int(np.ceil(igs[ind,2])), int(np.ceil(igs[ind,3])) - seman_map[y1:y2, x1:x2,1] = 0 - if len(gts)>0: - gts = gts/down - for ind in range(len(gts)): - # x1, y1, x2, y2 = int(round(gts[ind, 0])), int(round(gts[ind, 1])), int(round(gts[ind, 2])), int(round(gts[ind, 3])) - x1, y1, x2, y2 = int(np.ceil(gts[ind, 0])), int(np.ceil(gts[ind, 1])), int(gts[ind, 2]), int(gts[ind, 3]) - c_x, c_y = int((gts[ind, 0] + gts[ind, 2]) / 2), int((gts[ind, 1] + gts[ind, 3]) / 2) - dx = gaussian(x2-x1) - dy = gaussian(y2-y1) - gau_map = np.multiply(dy, np.transpose(dx)) - seman_map[y1:y2, x1:x2,0] = np.maximum(seman_map[y1:y2, x1:x2,0], gau_map) - seman_map[y1:y2, x1:x2,1] = 1 - seman_map[c_y, c_x, 2] = 1 - - if scale == 'h': - scale_map[c_y-r:c_y+r+1, c_x-r:c_x+r+1, 0] = np.log(gts[ind, 3] - gts[ind, 1]) - scale_map[c_y-r:c_y+r+1, c_x-r:c_x+r+1, 1] = 1 - elif scale=='w': - scale_map[c_y-r:c_y+r+1, c_x-r:c_x+r+1, 0] = np.log(gts[ind, 2] - gts[ind, 0]) - scale_map[c_y-r:c_y+r+1, c_x-r:c_x+r+1, 1] = 1 - elif scale=='hw': - scale_map[c_y-r:c_y+r+1, c_x-r:c_x+r+1, 0] = np.log(gts[ind, 3] - gts[ind, 1]) - scale_map[c_y-r:c_y+r+1, c_x-r:c_x+r+1, 1] = np.log(gts[ind, 2] - gts[ind, 0]) - scale_map[c_y-r:c_y+r+1, c_x-r:c_x+r+1, 2] = 1 - if offset: - offset_map[c_y, c_x, 0] = (gts[ind, 1] + gts[ind, 3]) / 2 - c_y - 0.5 - offset_map[c_y, c_x, 1] = (gts[ind, 0] + gts[ind, 2]) / 2 - c_x - 0.5 - offset_map[c_y, c_x, 2] = 1 - - if offset: - return seman_map,scale_map,offset_map - else: - return seman_map, scale_map - -def calc_gt_top(C, img_data,r=2): - def gaussian(kernel): - sigma = ((kernel-1) * 0.5 - 1) * 0.3 + 0.8 - s = 2*(sigma**2) - dx = np.exp(-np.square(np.arange(kernel) - int(kernel / 2)) / s) - return np.reshape(dx,(-1,1)) - gts = np.copy(img_data['bboxes']) - igs = np.copy(img_data['ignoreareas']) - scale_map = np.zeros((int(C.size_train[0]/4), int(C.size_train[1]/4), 2)) - seman_map = np.zeros((int(C.size_train[0]/4), int(C.size_train[1]/4), 3)) - seman_map[:,:,1] = 1 - if len(igs) > 0: - igs = igs/4 - for ind in range(len(igs)): - x1,y1,x2,y2 = int(igs[ind,0]), int(igs[ind,1]), int(np.ceil(igs[ind,2])), int(np.ceil(igs[ind,3])) - seman_map[y1:y2, x1:x2,1] = 0 - if len(gts)>0: - gts = gts/4 - for ind in range(len(gts)): - x1, y1, x2, y2 = int(round(gts[ind, 0])), int(round(gts[ind, 1])), int(round(gts[ind, 2])), int(round(gts[ind, 3])) - w = x2-x1 - c_x = int((gts[ind, 0] + gts[ind, 2]) / 2) - - dx = gaussian(w) - dy = gaussian(w) - gau_map = np.multiply(dy, np.transpose(dx)) - - ty = np.maximum(0,int(round(y1-w/2))) - ot = ty-int(round(y1-w/2)) - seman_map[ty:ty+w-ot, x1:x2,0] = np.maximum(seman_map[ty:ty+w-ot, x1:x2,0], gau_map[ot:,:]) - seman_map[ty:ty+w-ot, x1:x2,1] = 1 - seman_map[y1, c_x, 2] = 1 - - scale_map[y1-r:y1+r+1, c_x-r:c_x+r+1, 0] = np.log(gts[ind,3]-gts[ind,1]) - scale_map[y1-r:y1+r+1, c_x-r:c_x+r+1, 1] = 1 - return seman_map,scale_map + +def calc_gt_center(C, img_data, r=2, down=4, scale='h', offset=True): + def gaussian(kernel): + sigma = ((kernel - 1) * 0.5 - 1) * 0.3 + 0.8 + s = 2 * (sigma ** 2) + dx = np.exp(-np.square(np.arange(kernel) - int(kernel / 2)) / s) + return np.reshape(dx, (-1, 1)) + + gts = np.copy(img_data['bboxes']) + igs = np.copy(img_data['ignoreareas']) + scale_map = np.zeros((int(C.size_train[0] / down), int(C.size_train[1] / down), 2)) + if scale == 'hw': + scale_map = np.zeros((int(C.size_train[0] / down), int(C.size_train[1] / down), 3)) + if offset: + offset_map = np.zeros((int(C.size_train[0] / down), int(C.size_train[1] / down), 3)) + seman_map = np.zeros((int(C.size_train[0] / down), int(C.size_train[1] / down), 3)) + seman_map[:, :, 1] = 1 + if len(igs) > 0: + igs = igs / down + for ind in range(len(igs)): + x1, y1, x2, y2 = int(igs[ind, 0]), int(igs[ind, 1]), int(np.ceil(igs[ind, 2])), int(np.ceil(igs[ind, 3])) + seman_map[y1:y2, x1:x2, 1] = 0 + if len(gts) > 0: + gts = gts / down + for ind in range(len(gts)): + # x1, y1, x2, y2 = int(round(gts[ind, 0])), int(round(gts[ind, 1])), int(round(gts[ind, 2])), int(round(gts[ind, 3])) + x1, y1, x2, y2 = int(np.ceil(gts[ind, 0])), int(np.ceil(gts[ind, 1])), int(gts[ind, 2]), int(gts[ind, 3]) + c_x, c_y = int((gts[ind, 0] + gts[ind, 2]) / 2), int((gts[ind, 1] + gts[ind, 3]) / 2) + dx = gaussian(x2 - x1) + dy = gaussian(y2 - y1) + gau_map = np.multiply(dy, np.transpose(dx)) + seman_map[y1:y2, x1:x2, 0] = np.maximum(seman_map[y1:y2, x1:x2, 0], gau_map) + seman_map[y1:y2, x1:x2, 1] = 1 + seman_map[c_y, c_x, 2] = 1 + + if scale == 'h': + scale_map[c_y - r:c_y + r + 1, c_x - r:c_x + r + 1, 0] = np.log(gts[ind, 3] - gts[ind, 1]) + scale_map[c_y - r:c_y + r + 1, c_x - r:c_x + r + 1, 1] = 1 + elif scale == 'w': + scale_map[c_y - r:c_y + r + 1, c_x - r:c_x + r + 1, 0] = np.log(gts[ind, 2] - gts[ind, 0]) + scale_map[c_y - r:c_y + r + 1, c_x - r:c_x + r + 1, 1] = 1 + elif scale == 'hw': + scale_map[c_y - r:c_y + r + 1, c_x - r:c_x + r + 1, 0] = np.log(gts[ind, 3] - gts[ind, 1]) + scale_map[c_y - r:c_y + r + 1, c_x - r:c_x + r + 1, 1] = np.log(gts[ind, 2] - gts[ind, 0]) + scale_map[c_y - r:c_y + r + 1, c_x - r:c_x + r + 1, 2] = 1 + if offset: + offset_map[c_y, c_x, 0] = (gts[ind, 1] + gts[ind, 3]) / 2 - c_y - 0.5 + offset_map[c_y, c_x, 1] = (gts[ind, 0] + gts[ind, 2]) / 2 - c_x - 0.5 + offset_map[c_y, c_x, 2] = 1 + + if offset: + return seman_map, scale_map, offset_map + else: + return seman_map, scale_map + + +def calc_gt_top(C, img_data, r=2): + def gaussian(kernel): + sigma = ((kernel - 1) * 0.5 - 1) * 0.3 + 0.8 + s = 2 * (sigma ** 2) + dx = np.exp(-np.square(np.arange(kernel) - int(kernel / 2)) / s) + return np.reshape(dx, (-1, 1)) + + gts = np.copy(img_data['bboxes']) + igs = np.copy(img_data['ignoreareas']) + scale_map = np.zeros((int(C.size_train[0] / 4), int(C.size_train[1] / 4), 2)) + seman_map = np.zeros((int(C.size_train[0] / 4), int(C.size_train[1] / 4), 3)) + seman_map[:, :, 1] = 1 + if len(igs) > 0: + igs = igs / 4 + for ind in range(len(igs)): + x1, y1, x2, y2 = int(igs[ind, 0]), int(igs[ind, 1]), int(np.ceil(igs[ind, 2])), int(np.ceil(igs[ind, 3])) + seman_map[y1:y2, x1:x2, 1] = 0 + if len(gts) > 0: + gts = gts / 4 + for ind in range(len(gts)): + x1, y1, x2, y2 = int(round(gts[ind, 0])), int(round(gts[ind, 1])), int(round(gts[ind, 2])), int( + round(gts[ind, 3])) + w = x2 - x1 + c_x = int((gts[ind, 0] + gts[ind, 2]) / 2) + + dx = gaussian(w) + dy = gaussian(w) + gau_map = np.multiply(dy, np.transpose(dx)) + + ty = np.maximum(0, int(round(y1 - w / 2))) + ot = ty - int(round(y1 - w / 2)) + seman_map[ty:ty + w - ot, x1:x2, 0] = np.maximum(seman_map[ty:ty + w - ot, x1:x2, 0], gau_map[ot:, :]) + seman_map[ty:ty + w - ot, x1:x2, 1] = 1 + seman_map[y1, c_x, 2] = 1 + + scale_map[y1 - r:y1 + r + 1, c_x - r:c_x + r + 1, 0] = np.log(gts[ind, 3] - gts[ind, 1]) + scale_map[y1 - r:y1 + r + 1, c_x - r:c_x + r + 1, 1] = 1 + return seman_map, scale_map + def calc_gt_bottom(C, img_data, r=2): - def gaussian(kernel): - sigma = ((kernel-1) * 0.5 - 1) * 0.3 + 0.8 - s = 2*(sigma**2) - dx = np.exp(-np.square(np.arange(kernel) - int(kernel / 2)) / s) - return np.reshape(dx,(-1,1)) - gts = np.copy(img_data['bboxes']) - igs = np.copy(img_data['ignoreareas']) - scale_map = np.zeros((int(C.size_train[0]/4), int(C.size_train[1]/4), 2)) - seman_map = np.zeros((int(C.size_train[0]/4), int(C.size_train[1]/4), 3)) - seman_map[:,:,1] = 1 - if len(igs) > 0: - igs = igs/4 - for ind in range(len(igs)): - x1,y1,x2,y2 = int(igs[ind,0]), int(igs[ind,1]), int(np.ceil(igs[ind,2])), int(np.ceil(igs[ind,3])) - seman_map[y1:y2, x1:x2,1] = 0 - if len(gts)>0: - gts = gts/4 - for ind in range(len(gts)): - x1, y1, x2, y2 = int(np.ceil(gts[ind, 0])), int(np.ceil(gts[ind, 1])), int(gts[ind, 2]), int(gts[ind, 3]) - y2 = np.minimum(int(C.random_crop[0] / 4) - 1, y2) - w = x2 - x1 - c_x = int((gts[ind, 0] + gts[ind, 2]) / 2) - dx = gaussian(w) - dy = gaussian(w) - gau_map = np.multiply(dy, np.transpose(dx)) - - by = np.minimum(int(C.random_crop[0]/4)-1, int(round(y2+w/2))) - ob = int(round(y2+w/2))-by - seman_map[by-w+ob:by, x1:x2, 0] = np.maximum(seman_map[by-w+ob:by, x1:x2, 0], gau_map[:w-ob, :]) - seman_map[by-w+ob:by, x1:x2, 1] = 1 - seman_map[y2, c_x, 2] = 1 - - scale_map[y2-r:y2+r+1, c_x-r:c_x+r+1, 0] = np.log(gts[ind,3]-gts[ind,1]) - scale_map[y2-r:y2+r+1, c_x-r:c_x+r+1, 1] = 1 - - return seman_map, scale_map - - -def get_data(ped_data, C, batchsize = 8): - current_ped = 0 - while True: - x_img_batch, y_seman_batch, y_height_batch, y_offset_batch = [], [], [], [] - if current_ped>len(ped_data)-batchsize: - random.shuffle(ped_data) - current_ped = 0 - for img_data in ped_data[current_ped:current_ped + batchsize]: - try: - img_data, x_img = data_augment.augment(img_data, C) - if C.offset: - y_seman, y_height, y_offset = calc_gt_center(C, img_data, down=C.down, scale=C.scale, offset=True) - else: - if C.point == 'top': - y_seman, y_height = calc_gt_top(C, img_data) - elif C.point == 'bottom': - y_seman, y_height = calc_gt_bottom(C, img_data) - else: - y_seman, y_height = calc_gt_center(C, img_data, down=C.down, scale=C.scale, offset=False) - - x_img = x_img.astype(np.float32) - x_img[:, :, 0] -= C.img_channel_mean[0] - x_img[:, :, 1] -= C.img_channel_mean[1] - x_img[:, :, 2] -= C.img_channel_mean[2] - - x_img_batch.append(np.expand_dims(x_img, axis=0)) - y_seman_batch.append(np.expand_dims(y_seman, axis=0)) - y_height_batch.append(np.expand_dims(y_height, axis=0)) - if C.offset: - y_offset_batch.append(np.expand_dims(y_offset, axis=0)) - except Exception as e: - print(('get_batch_gt:',e)) - x_img_batch = np.concatenate(x_img_batch,axis=0) - y_seman_batch = np.concatenate(y_seman_batch, axis=0) - y_height_batch = np.concatenate(y_height_batch, axis=0) - if C.offset: - y_offset_batch = np.concatenate(y_offset_batch, axis=0) - current_ped += batchsize - if C.offset: - yield np.copy(x_img_batch), [np.copy(y_seman_batch), np.copy(y_height_batch), np.copy(y_offset_batch)] - else: - yield np.copy(x_img_batch), [np.copy(y_seman_batch), np.copy(y_height_batch)] - - -def get_data_hybrid(ped_data, emp_data, C, batchsize = 8,hyratio=0.5): - current_ped = 0 - current_emp = 0 - batchsize_ped = int(batchsize * hyratio) - batchsize_emp = batchsize - batchsize_ped - while True: - x_img_batch, y_seman_batch, y_height_batch, y_offset_batch = [], [], [], [] - if current_ped>len(ped_data)-batchsize_ped: - random.shuffle(ped_data) - current_ped = 0 - if current_emp>len(emp_data)-batchsize_emp: - random.shuffle(emp_data) - current_emp = 0 - for img_data in ped_data[current_ped:current_ped + batchsize_ped]: - try: - img_data, x_img = data_augment.augment(img_data, C) - if C.offset: - y_seman, y_height, y_offset = calc_gt_center(C, img_data, down=C.down, scale=C.scale, offset=C.offset) - else: - if C.point == 'top': - y_seman, y_height = calc_gt_top(C, img_data) - elif C.point == 'bottom': - y_seman, y_height = calc_gt_bottom(C, img_data) - else: - y_seman, y_height = calc_gt_center(C, img_data,down=C.down, scale=C.scale, offset=False) - - x_img = x_img.astype(np.float32) - x_img[:, :, 0] -= C.img_channel_mean[0] - x_img[:, :, 1] -= C.img_channel_mean[1] - x_img[:, :, 2] -= C.img_channel_mean[2] - - x_img_batch.append(np.expand_dims(x_img, axis=0)) - y_seman_batch.append(np.expand_dims(y_seman, axis=0)) - y_height_batch.append(np.expand_dims(y_height, axis=0)) - if C.offset: - y_offset_batch.append(np.expand_dims(y_offset, axis=0)) - - except Exception as e: - print(('get_batch_gt:',e)) - for img_data in emp_data[current_emp:current_emp + batchsize_emp]: - try: - img_data, x_img = data_augment.augment(img_data, C) - if C.offset: - y_seman, y_height, y_offset = calc_gt_center(C, img_data, down=C.down, scale=C.scale, offset=C.offset) - else: - if C.point == 'top': - y_seman, y_height = calc_gt_top(C, img_data) - elif C.point == 'bottom': - y_seman, y_height = calc_gt_bottom(C, img_data) - else: - y_seman, y_height = calc_gt_center(C, img_data,down=C.down, scale=C.scale, offset=False) - - x_img = x_img.astype(np.float32) - x_img[:, :, 0] -= C.img_channel_mean[0] - x_img[:, :, 1] -= C.img_channel_mean[1] - x_img[:, :, 2] -= C.img_channel_mean[2] - - x_img_batch.append(np.expand_dims(x_img, axis=0)) - y_seman_batch.append(np.expand_dims(y_seman, axis=0)) - y_height_batch.append(np.expand_dims(y_height, axis=0)) - if C.offset: - y_offset_batch.append(np.expand_dims(y_offset, axis=0)) - except Exception as e: - print(('get_batch_gt_emp:',e)) - x_img_batch = np.concatenate(x_img_batch,axis=0) - y_seman_batch = np.concatenate(y_seman_batch, axis=0) - y_height_batch = np.concatenate(y_height_batch, axis=0) - if C.offset: - y_offset_batch = np.concatenate(y_offset_batch, axis=0) - current_ped += batchsize_ped - current_emp += batchsize_emp - if C.offset: - yield np.copy(x_img_batch), [np.copy(y_seman_batch), np.copy(y_height_batch), np.copy(y_offset_batch)] - else: - yield np.copy(x_img_batch), [np.copy(y_seman_batch), np.copy(y_height_batch)] - -def get_data_wider(ped_data, C, batchsize = 8): - current_ped = 0 - while True: - x_img_batch, y_seman_batch, y_height_batch, y_offset_batch = [], [], [], [] - if current_ped>len(ped_data)-batchsize: - random.shuffle(ped_data) - current_ped = 0 - for img_data in ped_data[current_ped:current_ped + batchsize]: - try: - img_data, x_img = data_augment.augment_wider(img_data, C) - if C.offset: - y_seman, y_height, y_offset = calc_gt_center(C, img_data, down=C.down, scale=C.scale, offset=True) - else: - y_seman, y_height = calc_gt_center(C, img_data,down=C.down, scale=C.scale, offset=False) - - x_img = x_img.astype(np.float32) - x_img[:, :, 0] -= C.img_channel_mean[0] - x_img[:, :, 1] -= C.img_channel_mean[1] - x_img[:, :, 2] -= C.img_channel_mean[2] - - x_img_batch.append(np.expand_dims(x_img, axis=0)) - y_seman_batch.append(np.expand_dims(y_seman, axis=0)) - y_height_batch.append(np.expand_dims(y_height, axis=0)) - if C.offset: - y_offset_batch.append(np.expand_dims(y_offset, axis=0)) - except Exception as e: - print(('get_batch_gt:',e)) - x_img_batch = np.concatenate(x_img_batch,axis=0) - y_seman_batch = np.concatenate(y_seman_batch, axis=0) - y_height_batch = np.concatenate(y_height_batch, axis=0) - if C.offset: - y_offset_batch = np.concatenate(y_offset_batch, axis=0) - current_ped += batchsize - if C.offset: - yield np.copy(x_img_batch), [np.copy(y_seman_batch), np.copy(y_height_batch), np.copy(y_offset_batch)] - else: - yield np.copy(x_img_batch), [np.copy(y_seman_batch), np.copy(y_height_batch)] + def gaussian(kernel): + sigma = ((kernel - 1) * 0.5 - 1) * 0.3 + 0.8 + s = 2 * (sigma ** 2) + dx = np.exp(-np.square(np.arange(kernel) - int(kernel / 2)) / s) + return np.reshape(dx, (-1, 1)) + + gts = np.copy(img_data['bboxes']) + igs = np.copy(img_data['ignoreareas']) + scale_map = np.zeros((int(C.size_train[0] / 4), int(C.size_train[1] / 4), 2)) + seman_map = np.zeros((int(C.size_train[0] / 4), int(C.size_train[1] / 4), 3)) + seman_map[:, :, 1] = 1 + if len(igs) > 0: + igs = igs / 4 + for ind in range(len(igs)): + x1, y1, x2, y2 = int(igs[ind, 0]), int(igs[ind, 1]), int(np.ceil(igs[ind, 2])), int(np.ceil(igs[ind, 3])) + seman_map[y1:y2, x1:x2, 1] = 0 + if len(gts) > 0: + gts = gts / 4 + for ind in range(len(gts)): + x1, y1, x2, y2 = int(np.ceil(gts[ind, 0])), int(np.ceil(gts[ind, 1])), int(gts[ind, 2]), int(gts[ind, 3]) + y2 = np.minimum(int(C.random_crop[0] / 4) - 1, y2) + w = x2 - x1 + c_x = int((gts[ind, 0] + gts[ind, 2]) / 2) + dx = gaussian(w) + dy = gaussian(w) + gau_map = np.multiply(dy, np.transpose(dx)) + + by = np.minimum(int(C.random_crop[0] / 4) - 1, int(round(y2 + w / 2))) + ob = int(round(y2 + w / 2)) - by + seman_map[by - w + ob:by, x1:x2, 0] = np.maximum(seman_map[by - w + ob:by, x1:x2, 0], gau_map[:w - ob, :]) + seman_map[by - w + ob:by, x1:x2, 1] = 1 + seman_map[y2, c_x, 2] = 1 + + scale_map[y2 - r:y2 + r + 1, c_x - r:c_x + r + 1, 0] = np.log(gts[ind, 3] - gts[ind, 1]) + scale_map[y2 - r:y2 + r + 1, c_x - r:c_x + r + 1, 1] = 1 + + return seman_map, scale_map + + +def get_data(ped_data, C, batchsize=8): + current_ped = 0 + while True: + x_img_batch, y_seman_batch, y_height_batch, y_offset_batch = [], [], [], [] + if current_ped > len(ped_data) - batchsize: + random.shuffle(ped_data) + current_ped = 0 + for img_data in ped_data[current_ped:current_ped + batchsize]: + try: + img_data, x_img = data_augment.augment(img_data, C) + if C.offset: + y_seman, y_height, y_offset = calc_gt_center(C, img_data, down=C.down, scale=C.scale, offset=True) + else: + if C.point == 'top': + y_seman, y_height = calc_gt_top(C, img_data) + elif C.point == 'bottom': + y_seman, y_height = calc_gt_bottom(C, img_data) + else: + y_seman, y_height = calc_gt_center(C, img_data, down=C.down, scale=C.scale, offset=False) + + x_img = x_img.astype(np.float32) + x_img[:, :, 0] -= C.img_channel_mean[0] + x_img[:, :, 1] -= C.img_channel_mean[1] + x_img[:, :, 2] -= C.img_channel_mean[2] + + x_img_batch.append(np.expand_dims(x_img, axis=0)) + y_seman_batch.append(np.expand_dims(y_seman, axis=0)) + y_height_batch.append(np.expand_dims(y_height, axis=0)) + if C.offset: + y_offset_batch.append(np.expand_dims(y_offset, axis=0)) + except Exception as e: + print(('get_batch_gt:', e)) + x_img_batch = np.concatenate(x_img_batch, axis=0) + y_seman_batch = np.concatenate(y_seman_batch, axis=0) + y_height_batch = np.concatenate(y_height_batch, axis=0) + if C.offset: + y_offset_batch = np.concatenate(y_offset_batch, axis=0) + current_ped += batchsize + if C.offset: + yield np.copy(x_img_batch), [np.copy(y_seman_batch), np.copy(y_height_batch), np.copy(y_offset_batch)] + else: + yield np.copy(x_img_batch), [np.copy(y_seman_batch), np.copy(y_height_batch)] + + +def get_data_hybrid(ped_data, emp_data, C, batchsize=8, hyratio=0.5): + current_ped = 0 + current_emp = 0 + batchsize_ped = int(batchsize * hyratio) + batchsize_emp = batchsize - batchsize_ped + while True: + x_img_batch, y_seman_batch, y_height_batch, y_offset_batch = [], [], [], [] + if current_ped > len(ped_data) - batchsize_ped: + random.shuffle(ped_data) + current_ped = 0 + if current_emp > len(emp_data) - batchsize_emp: + random.shuffle(emp_data) + current_emp = 0 + for img_data in ped_data[current_ped:current_ped + batchsize_ped]: + try: + img_data, x_img = data_augment.augment(img_data, C) + if C.offset: + y_seman, y_height, y_offset = calc_gt_center(C, img_data, down=C.down, scale=C.scale, + offset=C.offset) + else: + if C.point == 'top': + y_seman, y_height = calc_gt_top(C, img_data) + elif C.point == 'bottom': + y_seman, y_height = calc_gt_bottom(C, img_data) + else: + y_seman, y_height = calc_gt_center(C, img_data, down=C.down, scale=C.scale, offset=False) + + x_img = x_img.astype(np.float32) + x_img[:, :, 0] -= C.img_channel_mean[0] + x_img[:, :, 1] -= C.img_channel_mean[1] + x_img[:, :, 2] -= C.img_channel_mean[2] + + x_img_batch.append(np.expand_dims(x_img, axis=0)) + y_seman_batch.append(np.expand_dims(y_seman, axis=0)) + y_height_batch.append(np.expand_dims(y_height, axis=0)) + if C.offset: + y_offset_batch.append(np.expand_dims(y_offset, axis=0)) + + except Exception as e: + print(('get_batch_gt:', e)) + for img_data in emp_data[current_emp:current_emp + batchsize_emp]: + try: + img_data, x_img = data_augment.augment(img_data, C) + if C.offset: + y_seman, y_height, y_offset = calc_gt_center(C, img_data, down=C.down, scale=C.scale, + offset=C.offset) + else: + if C.point == 'top': + y_seman, y_height = calc_gt_top(C, img_data) + elif C.point == 'bottom': + y_seman, y_height = calc_gt_bottom(C, img_data) + else: + y_seman, y_height = calc_gt_center(C, img_data, down=C.down, scale=C.scale, offset=False) + + x_img = x_img.astype(np.float32) + x_img[:, :, 0] -= C.img_channel_mean[0] + x_img[:, :, 1] -= C.img_channel_mean[1] + x_img[:, :, 2] -= C.img_channel_mean[2] + + x_img_batch.append(np.expand_dims(x_img, axis=0)) + y_seman_batch.append(np.expand_dims(y_seman, axis=0)) + y_height_batch.append(np.expand_dims(y_height, axis=0)) + if C.offset: + y_offset_batch.append(np.expand_dims(y_offset, axis=0)) + except Exception as e: + print(('get_batch_gt_emp:', e)) + x_img_batch = np.concatenate(x_img_batch, axis=0) + y_seman_batch = np.concatenate(y_seman_batch, axis=0) + y_height_batch = np.concatenate(y_height_batch, axis=0) + if C.offset: + y_offset_batch = np.concatenate(y_offset_batch, axis=0) + current_ped += batchsize_ped + current_emp += batchsize_emp + if C.offset: + yield np.copy(x_img_batch), [np.copy(y_seman_batch), np.copy(y_height_batch), np.copy(y_offset_batch)] + else: + yield np.copy(x_img_batch), [np.copy(y_seman_batch), np.copy(y_height_batch)] + + +def get_data_wider(ped_data, C, batchsize=8): + current_ped = 0 + while True: + x_img_batch, y_seman_batch, y_height_batch, y_offset_batch = [], [], [], [] + if current_ped > len(ped_data) - batchsize: + random.shuffle(ped_data) + current_ped = 0 + for img_data in ped_data[current_ped:current_ped + batchsize]: + try: + img_data, x_img = data_augment.augment_wider(img_data, C) + if C.offset: + y_seman, y_height, y_offset = calc_gt_center(C, img_data, down=C.down, scale=C.scale, offset=True) + else: + y_seman, y_height = calc_gt_center(C, img_data, down=C.down, scale=C.scale, offset=False) + + x_img = x_img.astype(np.float32) + x_img[:, :, 0] -= C.img_channel_mean[0] + x_img[:, :, 1] -= C.img_channel_mean[1] + x_img[:, :, 2] -= C.img_channel_mean[2] + + x_img_batch.append(np.expand_dims(x_img, axis=0)) + y_seman_batch.append(np.expand_dims(y_seman, axis=0)) + y_height_batch.append(np.expand_dims(y_height, axis=0)) + if C.offset: + y_offset_batch.append(np.expand_dims(y_offset, axis=0)) + except Exception as e: + print(('get_batch_gt:', e)) + x_img_batch = np.concatenate(x_img_batch, axis=0) + y_seman_batch = np.concatenate(y_seman_batch, axis=0) + y_height_batch = np.concatenate(y_height_batch, axis=0) + if C.offset: + y_offset_batch = np.concatenate(y_offset_batch, axis=0) + current_ped += batchsize + if C.offset: + yield np.copy(x_img_batch), [np.copy(y_seman_batch), np.copy(y_height_batch), np.copy(y_offset_batch)] + else: + yield np.copy(x_img_batch), [np.copy(y_seman_batch), np.copy(y_height_batch)] diff --git a/keras_csp/keras_layer_L2Normalization.py b/keras_csp/keras_layer_L2Normalization.py index 5f1b9c2..7b15e33 100644 --- a/keras_csp/keras_layer_L2Normalization.py +++ b/keras_csp/keras_layer_L2Normalization.py @@ -22,6 +22,7 @@ from keras.engine.topology import Layer import numpy as np + class L2Normalization(Layer): ''' Performs L2 normalization on the input tensor with a learnable scaling parameter diff --git a/keras_csp/losses.py b/keras_csp/losses.py index 499994d..1e870dd 100644 --- a/keras_csp/losses.py +++ b/keras_csp/losses.py @@ -2,63 +2,65 @@ from keras.objectives import categorical_crossentropy if K.image_dim_ordering() == 'tf': - import tensorflow as tf + import tensorflow as tf epsilon = 1e-4 def cls_center(y_true, y_pred): + classification_loss = K.binary_crossentropy(y_pred[:, :, :, 0], y_true[:, :, :, 2]) + # firstly we compute the focal weight + positives = y_true[:, :, :, 2] + negatives = y_true[:, :, :, 1] - y_true[:, :, :, 2] + foreground_weight = positives * (1.0 - y_pred[:, :, :, 0]) ** 2.0 + # foreground_weight = positives + background_weight = negatives * ((1.0 - y_true[:, :, :, 0]) ** 4.0) * (y_pred[:, :, :, 0] ** 2.0) + # background_weight = negatives * ((1.0 - y_true[:, :, :, 0])**4.0)*(0.01 ** 2.0) - classification_loss = K.binary_crossentropy(y_pred[:, :, :, 0], y_true[:, :, :, 2]) - # firstly we compute the focal weight - positives = y_true[:, :, :, 2] - negatives = y_true[:, :, :, 1]-y_true[:, :, :, 2] - foreground_weight = positives * (1.0 - y_pred[:, :, :, 0]) ** 2.0 - # foreground_weight = positives - background_weight = negatives * ((1.0 - y_true[:, :, :, 0])**4.0)*(y_pred[:, :, :, 0] ** 2.0) - # background_weight = negatives * ((1.0 - y_true[:, :, :, 0])**4.0)*(0.01 ** 2.0) + # foreground_weight = y_true[:, :, :, 0] * (1- y_pred[:, :, :, 0]) ** 2.0 + # background_weight = negatives * y_pred[:, :, :, 0] ** 2.0 - # foreground_weight = y_true[:, :, :, 0] * (1- y_pred[:, :, :, 0]) ** 2.0 - # background_weight = negatives * y_pred[:, :, :, 0] ** 2.0 + focal_weight = foreground_weight + background_weight - focal_weight = foreground_weight + background_weight + assigned_boxes = tf.reduce_sum(y_true[:, :, :, 2]) + class_loss = 0.01 * tf.reduce_sum(focal_weight * classification_loss) / tf.maximum(1.0, assigned_boxes) - assigned_boxes = tf.reduce_sum(y_true[:, :, :, 2]) - class_loss = 0.01*tf.reduce_sum(focal_weight*classification_loss) / tf.maximum(1.0, assigned_boxes) + # assigned_boxes = tf.reduce_sum(tf.reduce_sum(y_true[:, :, :, 1], axis=-1), axis=-1) + # class_loss = tf.reduce_sum(tf.reduce_sum(classification_loss, axis=-1), axis=-1) / tf.maximum(1.0, assigned_boxes) - # assigned_boxes = tf.reduce_sum(tf.reduce_sum(y_true[:, :, :, 1], axis=-1), axis=-1) - # class_loss = tf.reduce_sum(tf.reduce_sum(classification_loss, axis=-1), axis=-1) / tf.maximum(1.0, assigned_boxes) + return class_loss - return class_loss def regr_h(y_true, y_pred): + absolute_loss = tf.abs(y_true[:, :, :, 0] - y_pred[:, :, :, 0]) / (y_true[:, :, :, 0] + 1e-10) + square_loss = 0.5 * ((y_true[:, :, :, 0] - y_pred[:, :, :, 0]) / (y_true[:, :, :, 0] + 1e-10)) ** 2 - absolute_loss = tf.abs(y_true[:, :, :, 0] - y_pred[:, :, :, 0])/(y_true[:, :, :, 0]+1e-10) - square_loss = 0.5 * ((y_true[:, :, :, 0] - y_pred[:, :, :, 0])/(y_true[:, :, :, 0]+1e-10)) ** 2 + l1_loss = y_true[:, :, :, 1] * tf.where(tf.less(absolute_loss, 1.0), square_loss, absolute_loss - 0.5) - l1_loss = y_true[:, :, :, 1]*tf.where(tf.less(absolute_loss, 1.0), square_loss, absolute_loss - 0.5) + assigned_boxes = tf.reduce_sum(y_true[:, :, :, 1]) + class_loss = tf.reduce_sum(l1_loss) / tf.maximum(1.0, assigned_boxes) - assigned_boxes = tf.reduce_sum(y_true[:, :, :, 1]) - class_loss = tf.reduce_sum(l1_loss) / tf.maximum(1.0, assigned_boxes) + return class_loss - return class_loss def regr_hw(y_true, y_pred): - absolute_loss = tf.abs(y_true[:, :, :, :2] - y_pred[:, :, :, :]) / (y_true[:, :, :, :2] + 1e-10) - square_loss = 0.5 * ((y_true[:, :, :, :2] - y_pred[:, :, :, :]) / (y_true[:, :, :, :2] + 1e-10)) ** 2 - loss = y_true[:, :, :, 2] * tf.reduce_sum(tf.where(tf.less(absolute_loss, 1.0), square_loss, absolute_loss - 0.5),axis=-1) - assigned_boxes = tf.reduce_sum(y_true[:, :, :, 2]) - class_loss = tf.reduce_sum(loss) / tf.maximum(1.0, assigned_boxes) + absolute_loss = tf.abs(y_true[:, :, :, :2] - y_pred[:, :, :, :]) / (y_true[:, :, :, :2] + 1e-10) + square_loss = 0.5 * ((y_true[:, :, :, :2] - y_pred[:, :, :, :]) / (y_true[:, :, :, :2] + 1e-10)) ** 2 + loss = y_true[:, :, :, 2] * tf.reduce_sum(tf.where(tf.less(absolute_loss, 1.0), square_loss, absolute_loss - 0.5), + axis=-1) + assigned_boxes = tf.reduce_sum(y_true[:, :, :, 2]) + class_loss = tf.reduce_sum(loss) / tf.maximum(1.0, assigned_boxes) - return class_loss + return class_loss -def regr_offset(y_true, y_pred): - absolute_loss = tf.abs(y_true[:, :, :, :2] - y_pred[:, :, :, :]) - square_loss = 0.5 * (y_true[:, :, :, :2] - y_pred[:, :, :, :]) ** 2 - l1_loss = y_true[:, :, :, 2] * tf.reduce_sum(tf.where(tf.less(absolute_loss, 1.0), square_loss, absolute_loss - 0.5), axis=-1) +def regr_offset(y_true, y_pred): + absolute_loss = tf.abs(y_true[:, :, :, :2] - y_pred[:, :, :, :]) + square_loss = 0.5 * (y_true[:, :, :, :2] - y_pred[:, :, :, :]) ** 2 + l1_loss = y_true[:, :, :, 2] * tf.reduce_sum( + tf.where(tf.less(absolute_loss, 1.0), square_loss, absolute_loss - 0.5), axis=-1) - assigned_boxes = tf.reduce_sum(y_true[:, :, :, 2]) - class_loss = 0.1*tf.reduce_sum(l1_loss) / tf.maximum(1.0, assigned_boxes) + assigned_boxes = tf.reduce_sum(y_true[:, :, :, 2]) + class_loss = 0.1 * tf.reduce_sum(l1_loss) / tf.maximum(1.0, assigned_boxes) - return class_loss + return class_loss diff --git a/keras_csp/utilsfunc.py b/keras_csp/utilsfunc.py index bee2111..127595c 100644 --- a/keras_csp/utilsfunc.py +++ b/keras_csp/utilsfunc.py @@ -1,71 +1,78 @@ - import cv2 import numpy as np + def format_img_size(img, C): - """ formats the image size based on config """ - img_min_side = float(C.im_size) - (height,width,_) = img.shape - - if width <= height: - ratio = img_min_side/width - new_height = int(ratio * height) - new_width = int(img_min_side) - else: - ratio = img_min_side/height - new_width = int(ratio * width) - new_height = int(img_min_side) - img = cv2.resize(img, (new_width, new_height), interpolation=cv2.INTER_CUBIC) - return img, ratio + """ formats the image size based on config """ + img_min_side = float(C.im_size) + (height, width, _) = img.shape + + if width <= height: + ratio = img_min_side / width + new_height = int(ratio * height) + new_width = int(img_min_side) + else: + ratio = img_min_side / height + new_width = int(ratio * width) + new_height = int(img_min_side) + img = cv2.resize(img, (new_width, new_height), interpolation=cv2.INTER_CUBIC) + return img, ratio + + def format_img_channels(img, C): - """ formats the image channels based on config """ - # img = img[:, :, (2, 1, 0)] - img = img.astype(np.float32) - img[:, :, 0] -= C.img_channel_mean[0] - img[:, :, 1] -= C.img_channel_mean[1] - img[:, :, 2] -= C.img_channel_mean[2] - # img /= C.img_scaling_factor - # img = np.transpose(img, (2, 0, 1)) - img = np.expand_dims(img, axis=0) - return img + """ formats the image channels based on config """ + # img = img[:, :, (2, 1, 0)] + img = img.astype(np.float32) + img[:, :, 0] -= C.img_channel_mean[0] + img[:, :, 1] -= C.img_channel_mean[1] + img[:, :, 2] -= C.img_channel_mean[2] + # img /= C.img_scaling_factor + # img = np.transpose(img, (2, 0, 1)) + img = np.expand_dims(img, axis=0) + return img + def format_img_batch(img, C): - """ formats the image channels based on config """ - # img = img[:, :, (2, 1, 0)] - img = img.astype(np.float32) - img[:, :, :, 0] -= C.img_channel_mean[0] - img[:, :, :, 1] -= C.img_channel_mean[1] - img[:, :, :, 2] -= C.img_channel_mean[2] - # img /= C.img_scaling_factor - # img = np.transpose(img, (2, 0, 1)) - # img = np.expand_dims(img, axis=0) - return img + """ formats the image channels based on config """ + # img = img[:, :, (2, 1, 0)] + img = img.astype(np.float32) + img[:, :, :, 0] -= C.img_channel_mean[0] + img[:, :, :, 1] -= C.img_channel_mean[1] + img[:, :, :, 2] -= C.img_channel_mean[2] + # img /= C.img_scaling_factor + # img = np.transpose(img, (2, 0, 1)) + # img = np.expand_dims(img, axis=0) + return img + def format_img(img, C): - """ formats an image for model prediction based on config """ - # img, ratio = format_img_size(img, C) - img = format_img_channels(img, C) - return img #return img, ratio + """ formats an image for model prediction based on config """ + # img, ratio = format_img_size(img, C) + img = format_img_channels(img, C) + return img # return img, ratio + def format_img_inria(img, C): - img_h, img_w = img.shape[:2] - # img_h_new, img_w_new = int(round(img_h/16)*16), int(round(img_w/16)*16) - # img = cv2.resize(img, (img_w_new, img_h_new)) - img_h_new, img_w_new = int(np.ceil(img_h/16)*16), int(np.ceil(img_w/16)*16) - paved_image = np.zeros((img_h_new, img_w_new, 3), dtype=img.dtype) - paved_image[0:img_h,0:img_w] = img - img = format_img_channels(paved_image, C) - return img + img_h, img_w = img.shape[:2] + # img_h_new, img_w_new = int(round(img_h/16)*16), int(round(img_w/16)*16) + # img = cv2.resize(img, (img_w_new, img_h_new)) + img_h_new, img_w_new = int(np.ceil(img_h / 16) * 16), int(np.ceil(img_w / 16) * 16) + paved_image = np.zeros((img_h_new, img_w_new, 3), dtype=img.dtype) + paved_image[0:img_h, 0:img_w] = img + img = format_img_channels(paved_image, C) + return img + def format_img_ratio(img, C, ratio): - img = img.astype(np.float32) - img[:, :, 0] -= C.img_channel_mean[0] - img[:, :, 1] -= C.img_channel_mean[1] - img[:, :, 2] -= C.img_channel_mean[2] - img = cv2.resize(img, None, None, fx=ratio, fy=ratio) - # img = cv2.resize(img, None, None, fx=ratio, fy=ratio, interpolation=cv2.INTER_CUBIC) - img = np.expand_dims(img, axis=0) - return img #return img, ratio + img = img.astype(np.float32) + img[:, :, 0] -= C.img_channel_mean[0] + img[:, :, 1] -= C.img_channel_mean[1] + img[:, :, 2] -= C.img_channel_mean[2] + img = cv2.resize(img, None, None, fx=ratio, fy=ratio) + # img = cv2.resize(img, None, None, fx=ratio, fy=ratio, interpolation=cv2.INTER_CUBIC) + img = np.expand_dims(img, axis=0) + return img # return img, ratio + def preprocess_input_test(x): x = x.astype(np.float32) @@ -75,24 +82,26 @@ def preprocess_input_test(x): x = np.expand_dims(x, axis=0) return x + # Method to transform the coordinates of the bounding box to its original size def get_real_coordinates(ratio, x1, y1, x2, y2): + real_x1 = int(round(x1 // ratio)) + real_y1 = int(round(y1 // ratio)) + real_x2 = int(round(x2 // ratio)) + real_y2 = int(round(y2 // ratio)) - real_x1 = int(round(x1 // ratio)) - real_y1 = int(round(y1 // ratio)) - real_x2 = int(round(x2 // ratio)) - real_y2 = int(round(y2 // ratio)) + return (real_x1, real_y1, real_x2, real_y2) - return (real_x1, real_y1, real_x2 ,real_y2) def intersection(ai, bi, area): - x = max(ai[0], bi[0]) - y = max(ai[1], bi[1]) - w = min(ai[2], bi[2]) - x - h = min(ai[3], bi[3]) - y - if w < 0 or h < 0: - return 0 - return w*h/area + x = max(ai[0], bi[0]) + y = max(ai[1], bi[1]) + w = min(ai[2], bi[2]) - x + h = min(ai[3], bi[3]) - y + if w < 0 or h < 0: + return 0 + return w * h / area + def box_grid_overlap(bboxes, get_img_output_length): width, height = 960, 540 @@ -109,7 +118,9 @@ def box_grid_overlap(bboxes, get_img_output_length): if num_bboxes > 0: # get the GT box coordinates, and resize to account for image resizing gta = np.zeros((num_bboxes, 4)) - gta[:,0],gta[:,1],gta[:,2],gta[:,3] = bboxes[:,0],bboxes[:,1],bboxes[:,2]+bboxes[:,0],bboxes[:,3]+bboxes[:,1] + gta[:, 0], gta[:, 1], gta[:, 2], gta[:, 3] = bboxes[:, 0], bboxes[:, 1], bboxes[:, 2] + bboxes[:, 0], bboxes[:, + 3] + bboxes[ + :, 1] # for bbox_num in range(num_bboxes): # # get the GT box coordinates, and resize to account for image resizing # gta[bbox_num, 0] = bboxes[bbox_num][0] @@ -124,62 +135,66 @@ def box_grid_overlap(bboxes, get_img_output_length): y2_anc = downscale * (jy + 1) best_op = 0 for b in range(num_bboxes): - grid = [x1_anc,y1_anc,x2_anc,y2_anc] - op = intersection(grid,gta[b,:],downscale**2) - best_op = op if op>best_op else best_op - y_grid_overlap[jy,ix] = best_op + grid = [x1_anc, y1_anc, x2_anc, y2_anc] + op = intersection(grid, gta[b, :], downscale ** 2) + best_op = op if op > best_op else best_op + y_grid_overlap[jy, ix] = best_op + + y_grid_overlap = np.expand_dims(y_grid_overlap.reshape((1, -1)), axis=0) + return y_grid_overlap - y_grid_overlap = np.expand_dims(y_grid_overlap.reshape((1,-1)), axis=0) - return y_grid_overlap def integrate_motion_score(bboxes, probs, pred, stride=16): - if len(bboxes) == 0: - return [] - probs = probs.reshape((-1,1)) - pred_anchor_score = np.zeros((probs.shape[0], 1)) - for i in range(len(bboxes)): - x1, y1, x2, y2 = int(bboxes[i][0]/stride), int(bboxes[i][1]/stride), int(bboxes[i][2]/stride), int(bboxes[i][3]/stride) - pred_anchor_score[i,0] = np.sum(pred[y1:y2, x1:x2])/((x2-x1)*(y2-y1)) - # alpha, belta = 2/0.7, 0.1 - # pred_anchor_score = np.where(pred_anchor_score>0.7, pred_anchor_score*alpha, pred_anchor_score) - # pred_anchor_score = np.maximum(pred_anchor_score*alpha, np.ones_like(pred_anchor_score)*belta) - # all_probs = pred_anchor_score - all_probs = probs*pred_anchor_score - return all_probs + if len(bboxes) == 0: + return [] + probs = probs.reshape((-1, 1)) + pred_anchor_score = np.zeros((probs.shape[0], 1)) + for i in range(len(bboxes)): + x1, y1, x2, y2 = int(bboxes[i][0] / stride), int(bboxes[i][1] / stride), int(bboxes[i][2] / stride), int( + bboxes[i][3] / stride) + pred_anchor_score[i, 0] = np.sum(pred[y1:y2, x1:x2]) / ((x2 - x1) * (y2 - y1)) + # alpha, belta = 2/0.7, 0.1 + # pred_anchor_score = np.where(pred_anchor_score>0.7, pred_anchor_score*alpha, pred_anchor_score) + # pred_anchor_score = np.maximum(pred_anchor_score*alpha, np.ones_like(pred_anchor_score)*belta) + # all_probs = pred_anchor_score + all_probs = probs * pred_anchor_score + return all_probs + def box_encoder_pp(anchors, boxes, Y1): - A = np.copy(anchors[:, :, :, :4]) - A = A.reshape((-1, 4)) - - # 1 calculate the iou scores - max_overlaps = np.zeros((anchors.shape[0] * anchors.shape[1] * anchors.shape[2],), dtype=np.float32) - if len(boxes) > 0: - boxes[:, 2] += boxes[:, 0] - boxes[:, 3] += boxes[:, 1] - overlaps = bbox_overlaps(np.ascontiguousarray(A, dtype=np.float64), - np.ascontiguousarray(boxes, dtype=np.float64)) - max_overlaps = overlaps.max(axis=1) - # normalize the iou scores - if np.max(max_overlaps) > 0: - max_overlaps = (max_overlaps - np.min(max_overlaps)) / np.max(max_overlaps) - # 2 calculate the rpn scores - rpn_score = Y1.reshape((-1)).astype(np.float32) - inds = np.where(max_overlaps == 0) - rpn_score[inds] = np.min(rpn_score) - scores = (rpn_score + max_overlaps) / 2 - scores = np.expand_dims(scores.reshape((1,-1)).astype(np.float32), axis=0) - return scores + A = np.copy(anchors[:, :, :, :4]) + A = A.reshape((-1, 4)) + + # 1 calculate the iou scores + max_overlaps = np.zeros((anchors.shape[0] * anchors.shape[1] * anchors.shape[2],), dtype=np.float32) + if len(boxes) > 0: + boxes[:, 2] += boxes[:, 0] + boxes[:, 3] += boxes[:, 1] + overlaps = bbox_overlaps(np.ascontiguousarray(A, dtype=np.float64), + np.ascontiguousarray(boxes, dtype=np.float64)) + max_overlaps = overlaps.max(axis=1) + # normalize the iou scores + if np.max(max_overlaps) > 0: + max_overlaps = (max_overlaps - np.min(max_overlaps)) / np.max(max_overlaps) + # 2 calculate the rpn scores + rpn_score = Y1.reshape((-1)).astype(np.float32) + inds = np.where(max_overlaps == 0) + rpn_score[inds] = np.min(rpn_score) + scores = (rpn_score + max_overlaps) / 2 + scores = np.expand_dims(scores.reshape((1, -1)).astype(np.float32), axis=0) + return scores + def box_encoder_iou(anchors, boxes): - A = np.copy(anchors[:, :, :, :4]) - A = A.reshape((-1, 4)) - - max_overlaps = np.zeros((anchors.shape[0] * anchors.shape[1] * anchors.shape[2],), dtype=np.float32) - if len(boxes) > 0: - boxes[:, 2] += boxes[:, 0] - boxes[:, 3] += boxes[:, 1] - overlaps = bbox_overlaps(np.ascontiguousarray(A, dtype=np.float64), - np.ascontiguousarray(boxes, dtype=np.float64)) - max_overlaps = overlaps.max(axis=1) - scores = np.expand_dims(max_overlaps.reshape((1,-1)).astype(np.float32), axis=0) - return scores + A = np.copy(anchors[:, :, :, :4]) + A = A.reshape((-1, 4)) + + max_overlaps = np.zeros((anchors.shape[0] * anchors.shape[1] * anchors.shape[2],), dtype=np.float32) + if len(boxes) > 0: + boxes[:, 2] += boxes[:, 0] + boxes[:, 3] += boxes[:, 1] + overlaps = bbox_overlaps(np.ascontiguousarray(A, dtype=np.float64), + np.ascontiguousarray(boxes, dtype=np.float64)) + max_overlaps = overlaps.max(axis=1) + scores = np.expand_dims(max_overlaps.reshape((1, -1)).astype(np.float32), axis=0) + return scores diff --git a/setup.py b/setup.py index 8c53902..fdafaf2 100644 --- a/setup.py +++ b/setup.py @@ -9,6 +9,7 @@ except AttributeError: numpy_include = np.get_numpy_include() + def customize_compiler_for_nvcc(self): """inject deep into distutils to customize how the dispatch to gcc/nvcc works. @@ -82,10 +83,10 @@ def locate_cuda(): nvcc = find_in_path('nvcc', os.environ['PATH'] + os.pathsep + default_path) if nvcc is None: raise EnvironmentError('The nvcc binary could not be ' - 'located in your $PATH. Either add it to your path, or set $CUDAHOME') + 'located in your $PATH. Either add it to your path, or set $CUDAHOME') home = os.path.dirname(os.path.dirname(nvcc)) - cudaconfig = {'home':home, 'nvcc':nvcc, + cudaconfig = {'home': home, 'nvcc': nvcc, 'include': os.path.join(home, 'include'), 'lib64': os.path.join(home, 'lib64')} for k, v in cudaconfig.items(): @@ -93,6 +94,8 @@ def locate_cuda(): raise EnvironmentError('The CUDA %s path could not be located in %s' % (k, v)) return cudaconfig + + CUDA = locate_cuda() ext_modules = [ @@ -100,25 +103,25 @@ def locate_cuda(): "keras_csp.nms.cpu_nms", ["keras_csp/nms/cpu_nms.pyx"], extra_compile_args={'gcc': ["-Wno-cpp", "-Wno-unused-function"]}, - include_dirs = [numpy_include] + include_dirs=[numpy_include] ), Extension('keras_csp.nms.gpu_nms', - ['keras_csp/nms/nms_kernel.cu', 'keras_csp/nms/gpu_nms.pyx'], - library_dirs=[CUDA['lib64']], - libraries=['cudart'], - language='c++', - runtime_library_dirs=[CUDA['lib64']], - # this syntax is specific to this build system - # we're only going to use certain compiler args with nvcc and not with - # gcc the implementation of this trick is in customize_compiler() below - extra_compile_args={'gcc': ["-Wno-unused-function"], - 'nvcc': ['-arch=sm_35', - '--ptxas-options=-v', - '-c', - '--compiler-options', - "'-fPIC'"]}, - include_dirs = [numpy_include, CUDA['include']] - ) + ['keras_csp/nms/nms_kernel.cu', 'keras_csp/nms/gpu_nms.pyx'], + library_dirs=[CUDA['lib64']], + libraries=['cudart'], + language='c++', + runtime_library_dirs=[CUDA['lib64']], + # this syntax is specific to this build system + # we're only going to use certain compiler args with nvcc and not with + # gcc the implementation of this trick is in customize_compiler() below + extra_compile_args={'gcc': ["-Wno-unused-function"], + 'nvcc': ['-arch=sm_35', + '--ptxas-options=-v', + '-c', + '--compiler-options', + "'-fPIC'"]}, + include_dirs=[numpy_include, CUDA['include']] + ) ] setup( diff --git a/test_caltech.py b/test_caltech.py index 506d8fb..553fdd4 100644 --- a/test_caltech.py +++ b/test_caltech.py @@ -1,4 +1,3 @@ - import os import time import pickle @@ -13,7 +12,7 @@ C.offset = True cache_path = 'data/cache/caltech/test' with open(cache_path, 'rb') as fid: - val_data = pickle.load(fid) + val_data = pickle.load(fid) num_imgs = len(val_data) print('num of val samples: {}'.format(num_imgs)) @@ -34,53 +33,53 @@ out_path = 'output/valresults/caltech/%s/nooff' % (C.scale) if not os.path.exists(out_path): - os.makedirs(out_path) + os.makedirs(out_path) files = sorted(os.listdir(w_path)) for w_ind in range(51, 121): - for f in files: - if f.split('_')[0] == 'net' and int(f.split('_')[1][1:]) == w_ind: - cur_file = f - break - weight1 = os.path.join(w_path, cur_file) - print('load weights from {}'.format(weight1)) - model.load_weights(weight1, by_name=True) - res_path = os.path.join(out_path, '%03d'%int(str(w_ind))) + for f in files: + if f.split('_')[0] == 'net' and int(f.split('_')[1][1:]) == w_ind: + cur_file = f + break + weight1 = os.path.join(w_path, cur_file) + print('load weights from {}'.format(weight1)) + model.load_weights(weight1, by_name=True) + res_path = os.path.join(out_path, '%03d' % int(str(w_ind))) - print(res_path) - if not os.path.exists(res_path): - os.mkdir(res_path) - for st in range(6, 11): - set_path = os.path.join(res_path, 'set' + '%02d' % st) - if not os.path.exists(set_path): - os.mkdir(set_path) + print(res_path) + if not os.path.exists(res_path): + os.mkdir(res_path) + for st in range(6, 11): + set_path = os.path.join(res_path, 'set' + '%02d' % st) + if not os.path.exists(set_path): + os.mkdir(set_path) - start_time = time.time() - for f in range(num_imgs): - filepath = val_data[f]['filepath'] - filepath_next = val_data[f + 1]['filepath'] if f < num_imgs - 1 else val_data[f]['filepath'] - set = filepath.split('/')[-1].split('_')[0] - video = filepath.split('/')[-1].split('_')[1] - frame_number = int(filepath.split('/')[-1].split('_')[2][1:6]) + 1 - frame_number_next = int(filepath_next.split('/')[-1].split('_')[2][1:6]) + 1 - set_path = os.path.join(res_path, set) - video_path = os.path.join(set_path, video + '.txt') - if os.path.exists(video_path): - continue - if frame_number == 30: - res_all = [] - img = cv2.imread(filepath) - x_rcnn = format_img(img, C) - Y = model.predict(x_rcnn) + start_time = time.time() + for f in range(num_imgs): + filepath = val_data[f]['filepath'] + filepath_next = val_data[f + 1]['filepath'] if f < num_imgs - 1 else val_data[f]['filepath'] + set = filepath.split('/')[-1].split('_')[0] + video = filepath.split('/')[-1].split('_')[1] + frame_number = int(filepath.split('/')[-1].split('_')[2][1:6]) + 1 + frame_number_next = int(filepath_next.split('/')[-1].split('_')[2][1:6]) + 1 + set_path = os.path.join(res_path, set) + video_path = os.path.join(set_path, video + '.txt') + if os.path.exists(video_path): + continue + if frame_number == 30: + res_all = [] + img = cv2.imread(filepath) + x_rcnn = format_img(img, C) + Y = model.predict(x_rcnn) - if C.offset: - boxes = bbox_process.parse_det_offset(Y, C, score=0.01,down=4) - else: - boxes = bbox_process.parse_det(Y, C, score=0.01, down=4, scale=C.scale) + if C.offset: + boxes = bbox_process.parse_det_offset(Y, C, score=0.01, down=4) + else: + boxes = bbox_process.parse_det(Y, C, score=0.01, down=4, scale=C.scale) - if len(boxes)>0: - f_res = np.repeat(frame_number, len(boxes), axis=0).reshape((-1, 1)) - boxes[:, [2, 3]] -= boxes[:, [0, 1]] - res_all += np.concatenate((f_res, boxes), axis=-1).tolist() - if frame_number_next == 30 or f == num_imgs - 1: - np.savetxt(video_path, np.array(res_all), fmt='%6f') - print(time.time() - start_time) + if len(boxes) > 0: + f_res = np.repeat(frame_number, len(boxes), axis=0).reshape((-1, 1)) + boxes[:, [2, 3]] -= boxes[:, [0, 1]] + res_all += np.concatenate((f_res, boxes), axis=-1).tolist() + if frame_number_next == 30 or f == num_imgs - 1: + np.savetxt(video_path, np.array(res_all), fmt='%6f') + print(time.time() - start_time) diff --git a/test_wider_ms.py b/test_wider_ms.py index ef36024..46aa25d 100644 --- a/test_wider_ms.py +++ b/test_wider_ms.py @@ -1,4 +1,3 @@ - import os import time import pickle @@ -14,7 +13,7 @@ C.num_scale = 2 cache_path = 'data/cache/widerface/val' with open(cache_path, 'rb') as fid: - val_data = pickle.load(fid) + val_data = pickle.load(fid) num_imgs = len(val_data) print('num of val samples: {}'.format(num_imgs)) @@ -24,6 +23,7 @@ # define the base network (resnet here, can be MobileNet, etc) from keras_csp import resnet50 as nn + # define the network prediction preds = nn.nn_p3p4p5(img_input, offset=C.offset, num_scale=C.num_scale, trainable=True) model = Model(img_input, preds) @@ -35,129 +35,139 @@ w_path = 'output/valmodels/wider/%s/nooff' % (C.scale) out_path = 'output/valresults/wider/%s/nooff' % (C.scale) if not os.path.exists(out_path): - os.makedirs(out_path) + os.makedirs(out_path) files = sorted(os.listdir(w_path)) # get the results from epoch 51 to epoch 150 -for w_ind in range(382,383): - for f in files: - if f.split('_')[0] == 'net' and int(f.split('_')[1][1:]) == w_ind: - cur_file = f - break - weight1 = os.path.join(w_path, cur_file) - print('load weights from {}'.format(weight1)) - model.load_weights(weight1, by_name=True) - res_path = os.path.join(out_path, '%03d'%int(str(w_ind))) - if not os.path.exists(res_path): - os.makedirs(res_path) - print(res_path) - - start_time = time.time() - for f in range(num_imgs): - filepath = val_data[f]['filepath'] - event = filepath.split('/')[-2] - event_path = os.path.join(res_path, event) - if not os.path.exists(event_path): - os.mkdir(event_path) - filename = filepath.split('/')[-1].split('.')[0] - txtpath = os.path.join(event_path, filename + '.txt') - if os.path.exists(txtpath): - continue - - img = cv2.imread(filepath) - - def detect_face(img, scale=1, flip=False): - img_h, img_w = img.shape[:2] - img_h_new, img_w_new = int(np.ceil(scale * img_h / 16) * 16), int(np.ceil(scale * img_w / 16) * 16) - scale_h, scale_w = img_h_new / img_h, img_w_new / img_w - - img_s = cv2.resize(img, None, None, fx=scale_w, fy=scale_h, interpolation=cv2.INTER_LINEAR) - # img_h, img_w = img_s.shape[:2] - # print frame_number - C.size_test[0] = img_h_new - C.size_test[1] = img_w_new - - if flip: - img_sf = cv2.flip(img_s, 1) - # x_rcnn = format_img_pad(img_sf, C) - x_rcnn = format_img(img_sf, C) - else: - # x_rcnn = format_img_pad(img_s, C) - x_rcnn = format_img(img_s, C) - Y = model.predict(x_rcnn) - boxes = bbox_process.parse_wider_offset(Y, C, score=0.05, nmsthre=0.6) - if len(boxes) > 0: - keep_index = np.where(np.minimum(boxes[:, 2] - boxes[:, 0], boxes[:, 3] - boxes[:, 1]) >= 12)[0] - boxes = boxes[keep_index, :] - if len(boxes) > 0: - if flip: - boxes[:, [0, 2]] = img_s.shape[1] - boxes[:, [2, 0]] - boxes[:, 0:4:2] = boxes[:, 0:4:2] / scale_w - boxes[:, 1:4:2] = boxes[:, 1:4:2] / scale_h - else: - boxes = np.empty(shape=[0, 5], dtype=np.float32) - return boxes - - def im_det_ms_pyramid(image, max_im_shrink): - # shrink detecting and shrink only detect big face - det_s = np.row_stack((detect_face(image, 0.5), detect_face(image, 0.5, flip=True))) - index = np.where(np.maximum(det_s[:, 2] - det_s[:, 0] + 1, det_s[:, 3] - det_s[:, 1] + 1) > 64)[0] - det_s = det_s[index, :] - - det_temp = np.row_stack((detect_face(image, 0.75), detect_face(image, 0.75, flip=True))) - index = np.where(np.maximum(det_temp[:, 2] - det_temp[:, 0] + 1, det_temp[:, 3] - det_temp[:, 1] + 1) > 32)[0] - det_temp = det_temp[index, :] - det_s = np.row_stack((det_s, det_temp)) - - det_temp = np.row_stack((detect_face(image, 0.25), detect_face(image, 0.25, flip=True))) - index = np.where(np.maximum(det_temp[:, 2] - det_temp[:, 0] + 1, det_temp[:, 3] - det_temp[:, 1] + 1) > 96)[0] - det_temp = det_temp[index, :] - det_s = np.row_stack((det_s, det_temp)) - - st = [1.25, 1.5, 1.75, 2.0, 2.25] - for i in range(len(st)): - if (st[i] <= max_im_shrink): - det_temp = np.row_stack((detect_face(image, st[i]), detect_face(image, st[i], flip=True))) - # Enlarged images are only used to detect small faces. - if st[i] == 1.25: - index = np.where( - np.minimum(det_temp[:, 2] - det_temp[:, 0] + 1, det_temp[:, 3] - det_temp[:, 1] + 1) < 128)[0] - det_temp = det_temp[index, :] - elif st[i] == 1.5: - index = np.where( - np.minimum(det_temp[:, 2] - det_temp[:, 0] + 1, det_temp[:, 3] - det_temp[:, 1] + 1) < 96)[0] - det_temp = det_temp[index, :] - elif st[i] == 1.75: - index = np.where( - np.minimum(det_temp[:, 2] - det_temp[:, 0] + 1, det_temp[:, 3] - det_temp[:, 1] + 1) < 64)[0] - det_temp = det_temp[index, :] - elif st[i] == 2.0: - index = np.where( - np.minimum(det_temp[:, 2] - det_temp[:, 0] + 1, det_temp[:, 3] - det_temp[:, 1] + 1) < 48)[0] - det_temp = det_temp[index, :] - elif st[i] == 2.25: - index = np.where( - np.minimum(det_temp[:, 2] - det_temp[:, 0] + 1, det_temp[:, 3] - det_temp[:, 1] + 1) < 32)[0] - det_temp = det_temp[index, :] - det_s = np.row_stack((det_s, det_temp)) - return det_s - - max_im_shrink = (0x7fffffff / 577.0 / (img.shape[0] * img.shape[1])) ** 0.5 # the max size of input image - shrink = max_im_shrink if max_im_shrink < 1 else 1 - det0 = detect_face(img) - det1 = detect_face(img, flip=True) - det2 = im_det_ms_pyramid(img, max_im_shrink) - # merge all test results via bounding box voting - det = np.row_stack((det0, det1, det2)) - keep_index = np.where(np.minimum(det[:, 2] - det[:, 0], det[:, 3] - det[:, 1]) >= 3)[0] - det = det[keep_index, :] - dets = bbox_process.soft_bbox_vote(det, thre=0.4) - keep_index = np.where((dets[:, 2] - dets[:, 0] + 1) * (dets[:, 3] - dets[:, 1] + 1) >= 6 ** 2)[0] - dets = dets[keep_index, :] - - with open(txtpath, 'w') as f: - f.write('{:s}\n'.format(filename)) - f.write('{:d}\n'.format(len(dets))) - for line in dets: - f.write('{:.0f} {:.0f} {:.0f} {:.0f} {:.3f}\n'. - format(line[0], line[1], line[2] - line[0] + 1, line[3] - line[1] + 1, line[4])) - print(time.time() - start_time) \ No newline at end of file +for w_ind in range(382, 383): + for f in files: + if f.split('_')[0] == 'net' and int(f.split('_')[1][1:]) == w_ind: + cur_file = f + break + weight1 = os.path.join(w_path, cur_file) + print('load weights from {}'.format(weight1)) + model.load_weights(weight1, by_name=True) + res_path = os.path.join(out_path, '%03d' % int(str(w_ind))) + if not os.path.exists(res_path): + os.makedirs(res_path) + print(res_path) + + start_time = time.time() + for f in range(num_imgs): + filepath = val_data[f]['filepath'] + event = filepath.split('/')[-2] + event_path = os.path.join(res_path, event) + if not os.path.exists(event_path): + os.mkdir(event_path) + filename = filepath.split('/')[-1].split('.')[0] + txtpath = os.path.join(event_path, filename + '.txt') + if os.path.exists(txtpath): + continue + + img = cv2.imread(filepath) + + + def detect_face(img, scale=1, flip=False): + img_h, img_w = img.shape[:2] + img_h_new, img_w_new = int(np.ceil(scale * img_h / 16) * 16), int(np.ceil(scale * img_w / 16) * 16) + scale_h, scale_w = img_h_new / img_h, img_w_new / img_w + + img_s = cv2.resize(img, None, None, fx=scale_w, fy=scale_h, interpolation=cv2.INTER_LINEAR) + # img_h, img_w = img_s.shape[:2] + # print frame_number + C.size_test[0] = img_h_new + C.size_test[1] = img_w_new + + if flip: + img_sf = cv2.flip(img_s, 1) + # x_rcnn = format_img_pad(img_sf, C) + x_rcnn = format_img(img_sf, C) + else: + # x_rcnn = format_img_pad(img_s, C) + x_rcnn = format_img(img_s, C) + Y = model.predict(x_rcnn) + boxes = bbox_process.parse_wider_offset(Y, C, score=0.05, nmsthre=0.6) + if len(boxes) > 0: + keep_index = np.where(np.minimum(boxes[:, 2] - boxes[:, 0], boxes[:, 3] - boxes[:, 1]) >= 12)[0] + boxes = boxes[keep_index, :] + if len(boxes) > 0: + if flip: + boxes[:, [0, 2]] = img_s.shape[1] - boxes[:, [2, 0]] + boxes[:, 0:4:2] = boxes[:, 0:4:2] / scale_w + boxes[:, 1:4:2] = boxes[:, 1:4:2] / scale_h + else: + boxes = np.empty(shape=[0, 5], dtype=np.float32) + return boxes + + + def im_det_ms_pyramid(image, max_im_shrink): + # shrink detecting and shrink only detect big face + det_s = np.row_stack((detect_face(image, 0.5), detect_face(image, 0.5, flip=True))) + index = np.where(np.maximum(det_s[:, 2] - det_s[:, 0] + 1, det_s[:, 3] - det_s[:, 1] + 1) > 64)[0] + det_s = det_s[index, :] + + det_temp = np.row_stack((detect_face(image, 0.75), detect_face(image, 0.75, flip=True))) + index = np.where(np.maximum(det_temp[:, 2] - det_temp[:, 0] + 1, det_temp[:, 3] - det_temp[:, 1] + 1) > 32)[ + 0] + det_temp = det_temp[index, :] + det_s = np.row_stack((det_s, det_temp)) + + det_temp = np.row_stack((detect_face(image, 0.25), detect_face(image, 0.25, flip=True))) + index = np.where(np.maximum(det_temp[:, 2] - det_temp[:, 0] + 1, det_temp[:, 3] - det_temp[:, 1] + 1) > 96)[ + 0] + det_temp = det_temp[index, :] + det_s = np.row_stack((det_s, det_temp)) + + st = [1.25, 1.5, 1.75, 2.0, 2.25] + for i in range(len(st)): + if (st[i] <= max_im_shrink): + det_temp = np.row_stack((detect_face(image, st[i]), detect_face(image, st[i], flip=True))) + # Enlarged images are only used to detect small faces. + if st[i] == 1.25: + index = np.where( + np.minimum(det_temp[:, 2] - det_temp[:, 0] + 1, det_temp[:, 3] - det_temp[:, 1] + 1) < 128)[ + 0] + det_temp = det_temp[index, :] + elif st[i] == 1.5: + index = np.where( + np.minimum(det_temp[:, 2] - det_temp[:, 0] + 1, det_temp[:, 3] - det_temp[:, 1] + 1) < 96)[ + 0] + det_temp = det_temp[index, :] + elif st[i] == 1.75: + index = np.where( + np.minimum(det_temp[:, 2] - det_temp[:, 0] + 1, det_temp[:, 3] - det_temp[:, 1] + 1) < 64)[ + 0] + det_temp = det_temp[index, :] + elif st[i] == 2.0: + index = np.where( + np.minimum(det_temp[:, 2] - det_temp[:, 0] + 1, det_temp[:, 3] - det_temp[:, 1] + 1) < 48)[ + 0] + det_temp = det_temp[index, :] + elif st[i] == 2.25: + index = np.where( + np.minimum(det_temp[:, 2] - det_temp[:, 0] + 1, det_temp[:, 3] - det_temp[:, 1] + 1) < 32)[ + 0] + det_temp = det_temp[index, :] + det_s = np.row_stack((det_s, det_temp)) + return det_s + + + max_im_shrink = (0x7fffffff / 577.0 / (img.shape[0] * img.shape[1])) ** 0.5 # the max size of input image + shrink = max_im_shrink if max_im_shrink < 1 else 1 + det0 = detect_face(img) + det1 = detect_face(img, flip=True) + det2 = im_det_ms_pyramid(img, max_im_shrink) + # merge all test results via bounding box voting + det = np.row_stack((det0, det1, det2)) + keep_index = np.where(np.minimum(det[:, 2] - det[:, 0], det[:, 3] - det[:, 1]) >= 3)[0] + det = det[keep_index, :] + dets = bbox_process.soft_bbox_vote(det, thre=0.4) + keep_index = np.where((dets[:, 2] - dets[:, 0] + 1) * (dets[:, 3] - dets[:, 1] + 1) >= 6 ** 2)[0] + dets = dets[keep_index, :] + + with open(txtpath, 'w') as f: + f.write('{:s}\n'.format(filename)) + f.write('{:d}\n'.format(len(dets))) + for line in dets: + f.write('{:.0f} {:.0f} {:.0f} {:.0f} {:.3f}\n'. + format(line[0], line[1], line[2] - line[0] + 1, line[3] - line[1] + 1, line[4])) + print(time.time() - start_time) diff --git a/train_caltech.py b/train_caltech.py index 05af949..866fd1f 100644 --- a/train_caltech.py +++ b/train_caltech.py @@ -1,4 +1,3 @@ - import random import sys, os import time @@ -33,15 +32,17 @@ emp_data = pickle.load(fid) num_imgs_ped = len(ped_data) num_imgs_emp = len(emp_data) -print(('num of ped and emp samples: {} {}'.format(num_imgs_ped,num_imgs_emp))) +print(('num of ped and emp samples: {} {}'.format(num_imgs_ped, num_imgs_emp))) data_gen_train = data_generators.get_data_hybrid(ped_data, emp_data, C, batchsize=batchsize, hyratio=0.5) # define the base network (resnet here, can be MobileNet, etc) -if C.network=='resnet50': +if C.network == 'resnet50': from keras_csp import resnet50 as nn + weight_path = 'data/models/resnet50_weights_tf_dim_ordering_tf_kernels.h5' -elif C.network=='mobilenet': +elif C.network == 'mobilenet': from keras_csp import mobilenet as nn + weight_path = 'data/models/mobilenet_1_0_224_tf_no_top.h5' else: raise NotImplementedError('Not support network: {}'.format(C.network)) @@ -53,8 +54,9 @@ preds_tea = nn.nn_p3p4p5(img_input, offset=C.offset, num_scale=C.num_scale, trainable=True) model = Model(img_input, preds) -if num_gpu>1: +if num_gpu > 1: from keras_csp.parallel_model import ParallelModel + model = ParallelModel(model, int(num_gpu)) model_stu = Model(img_input, preds) model_tea = Model(img_input, preds_tea) @@ -68,22 +70,20 @@ else: out_path = 'output/valmodels/caltech/%s/nooff' % (C.scale) - if not os.path.exists(out_path): os.makedirs(out_path) -res_file = os.path.join(out_path,'records.txt') +res_file = os.path.join(out_path, 'records.txt') optimizer = Adam(lr=C.init_lr) if C.offset: model.compile(optimizer=optimizer, loss=[losses.cls_center, losses.regr_h, losses.regr_offset]) else: - if C.scale=='hw': + if C.scale == 'hw': model.compile(optimizer=optimizer, loss=[losses.cls_center, losses.regr_hw]) else: model.compile(optimizer=optimizer, loss=[losses.cls_center, losses.regr_h]) - -epoch_length = int(C.iter_per_epoch/batchsize) +epoch_length = int(C.iter_per_epoch / batchsize) iter_num = 0 add_epoch = 0 losses = np.zeros((epoch_length, 3)) @@ -102,12 +102,13 @@ for l in model_tea.layers: weights_tea = l.get_weights() - if len(weights_tea)>0: + if len(weights_tea) > 0: if num_gpu > 1: weights_stu = model_stu.get_layer(name=l.name).get_weights() else: weights_stu = model.get_layer(name=l.name).get_weights() - weights_tea = [C.alpha*w_tea + (1-C.alpha)*w_stu for (w_tea, w_stu) in zip(weights_tea, weights_stu)] + weights_tea = [C.alpha * w_tea + (1 - C.alpha) * w_stu for (w_tea, w_stu) in + zip(weights_tea, weights_stu)] l.set_weights(weights_tea) # print loss_s1 losses[iter_num, 0] = loss_s1[1] @@ -120,12 +121,13 @@ iter_num += 1 if iter_num % 20 == 0: progbar.update(iter_num, - [('cls', np.mean(losses[:iter_num, 0])), ('regr_h', np.mean(losses[:iter_num, 1])), ('offset', np.mean(losses[:iter_num, 2]))]) + [('cls', np.mean(losses[:iter_num, 0])), ('regr_h', np.mean(losses[:iter_num, 1])), + ('offset', np.mean(losses[:iter_num, 2]))]) if iter_num == epoch_length: cls_loss1 = np.mean(losses[:, 0]) regr_loss1 = np.mean(losses[:, 1]) offset_loss1 = np.mean(losses[:, 2]) - total_loss = cls_loss1+regr_loss1+offset_loss1 + total_loss = cls_loss1 + regr_loss1 + offset_loss1 total_loss_r.append(total_loss) cls_loss_r1.append(cls_loss1) @@ -140,7 +142,8 @@ if total_loss < best_loss: print(('Total loss decreased from {} to {}, saving weights'.format(best_loss, total_loss))) best_loss = total_loss - model_tea.save_weights(os.path.join(out_path, 'net_e{}_l{}.hdf5'.format(epoch_num + 1 + add_epoch, total_loss))) + model_tea.save_weights( + os.path.join(out_path, 'net_e{}_l{}.hdf5'.format(epoch_num + 1 + add_epoch, total_loss))) break except Exception as e: print(('Exception: {}'.format(e))) @@ -151,4 +154,4 @@ np.asarray(offset_loss_r1).reshape((-1, 1)),), axis=-1) np.savetxt(res_file, np.array(records), fmt='%.6f') -print('Training complete, exiting.') \ No newline at end of file +print('Training complete, exiting.') diff --git a/train_city.py b/train_city.py index f035ae4..cd6c58f 100644 --- a/train_city.py +++ b/train_city.py @@ -15,7 +15,7 @@ C = config.Config() C.gpu_ids = '0,1,2,3' C.onegpu = 2 -C.size_train = (640,1280) +C.size_train = (640, 1280) C.init_lr = 2e-4 C.num_epochs = 150 C.offset = True @@ -34,10 +34,10 @@ data_gen_train = data_generators.get_data(train_data, C, batchsize=batchsize) # define the base network (resnet here, can be MobileNet, etc) -if C.network=='resnet50': +if C.network == 'resnet50': from keras_csp import resnet50 as nn - weight_path = 'data/models/resnet50_weights_tf_dim_ordering_tf_kernels.h5' + weight_path = 'data/models/resnet50_weights_tf_dim_ordering_tf_kernels.h5' if C.offset: out_path = 'output/valmodels/city/%s/off' % (C.scale) @@ -54,7 +54,6 @@ epoch = epochs[max_epoch_idx] weight_path = checkpoint_paths[max_epoch_idx] - input_shape_img = (C.size_train[0], C.size_train[1], 3) img_input = Input(shape=input_shape_img) # define the network prediction @@ -64,6 +63,7 @@ if num_gpu > 1: from keras_csp.parallel_model import ParallelModel + model = ParallelModel(model, int(num_gpu)) model_stu = Model(img_input, preds) model_tea = Model(img_input, preds_tea) @@ -72,19 +72,18 @@ model_tea.load_weights(weight_path, by_name=True) print('load weights from {}'.format(weight_path)) -res_file = os.path.join(out_path,'records.txt') +res_file = os.path.join(out_path, 'records.txt') optimizer = Adam(lr=C.init_lr) if C.offset: model.compile(optimizer=optimizer, loss=[losses.cls_center, losses.regr_h, losses.regr_offset]) else: - if C.scale=='hw': + if C.scale == 'hw': model.compile(optimizer=optimizer, loss=[losses.cls_center, losses.regr_hw]) else: model.compile(optimizer=optimizer, loss=[losses.cls_center, losses.regr_h]) - -epoch_length = int(C.iter_per_epoch/batchsize) +epoch_length = int(C.iter_per_epoch / batchsize) iter_num = 0 add_epoch = 0 losses = np.zeros((epoch_length, 3)) @@ -102,12 +101,13 @@ for l in model_tea.layers: weights_tea = l.get_weights() - if len(weights_tea)>0: + if len(weights_tea) > 0: if num_gpu > 1: weights_stu = model_stu.get_layer(name=l.name).get_weights() else: weights_stu = model.get_layer(name=l.name).get_weights() - weights_tea = [C.alpha*w_tea + (1-C.alpha)*w_stu for (w_tea, w_stu) in zip(weights_tea, weights_stu)] + weights_tea = [C.alpha * w_tea + (1 - C.alpha) * w_stu for (w_tea, w_stu) in + zip(weights_tea, weights_stu)] l.set_weights(weights_tea) # print loss_s1 losses[iter_num, 0] = loss_s1[1] @@ -120,12 +120,13 @@ iter_num += 1 if iter_num % 20 == 0: progbar.update(iter_num, - [('cls', np.mean(losses[:iter_num, 0])), ('regr_h', np.mean(losses[:iter_num, 1])), ('offset', np.mean(losses[:iter_num, 2]))]) + [('cls', np.mean(losses[:iter_num, 0])), ('regr_h', np.mean(losses[:iter_num, 1])), + ('offset', np.mean(losses[:iter_num, 2]))]) if iter_num == epoch_length: cls_loss1 = np.mean(losses[:, 0]) regr_loss1 = np.mean(losses[:, 1]) offset_loss1 = np.mean(losses[:, 2]) - total_loss = cls_loss1+regr_loss1+offset_loss1 + total_loss = cls_loss1 + regr_loss1 + offset_loss1 total_loss_r.append(total_loss) cls_loss_r1.append(cls_loss1) @@ -140,7 +141,8 @@ if total_loss < best_loss: print(('Total loss decreased from {} to {}, saving weights'.format(best_loss, total_loss))) best_loss = total_loss - model_tea.save_weights(os.path.join(out_path, 'net_e{}_l{}.hdf5'.format(epoch_num + 1 + add_epoch, total_loss))) + model_tea.save_weights( + os.path.join(out_path, 'net_e{}_l{}.hdf5'.format(epoch_num + 1 + add_epoch, total_loss))) break records = np.concatenate((np.asarray(total_loss_r).reshape((-1, 1)), diff --git a/train_wider.py b/train_wider.py index c5df94a..6e56ad1 100644 --- a/train_wider.py +++ b/train_wider.py @@ -1,4 +1,3 @@ - import random import sys, os import time @@ -15,7 +14,7 @@ C = config.Config() C.gpu_ids = '0,1,2,3,4,5,6,7' C.onegpu = 4 -C.size_train = (704,704) +C.size_train = (704, 704) C.init_lr = 2e-4 C.offset = True C.scale = 'hw' @@ -35,8 +34,9 @@ data_gen_train = data_generators.get_data_wider(train_data, C, batchsize=batchsize) # define the base network (resnet here, can be MobileNet, etc) -if C.network=='resnet50': +if C.network == 'resnet50': from keras_csp import resnet50 as nn + weight_path = 'data/models/resnet50_weights_tf_dim_ordering_tf_kernels.h5' input_shape_img = (C.size_train[0], C.size_train[1], 3) @@ -46,8 +46,9 @@ preds_tea = nn.nn_p3p4p5(img_input, offset=C.offset, num_scale=C.num_scale, trainable=True) model = Model(img_input, preds) -if num_gpu>1: +if num_gpu > 1: from keras_csp.parallel_model import ParallelModel + model = ParallelModel(model, int(num_gpu)) model_stu = Model(img_input, preds) model_tea = Model(img_input, preds_tea) @@ -62,7 +63,7 @@ out_path = 'output/valmodels/wider/%s/nooff' % (C.scale) if not os.path.exists(out_path): os.makedirs(out_path) -res_file = os.path.join(out_path,'records.txt') +res_file = os.path.join(out_path, 'records.txt') optimizer = Adam(lr=C.init_lr) if C.offset: @@ -70,7 +71,7 @@ else: model.compile(optimizer=optimizer, loss=[losses.cls_center, losses.regr_hw]) -epoch_length = int(C.iter_per_epoch/batchsize) +epoch_length = int(C.iter_per_epoch / batchsize) iter_num = 0 add_epoch = 0 losses = np.zeros((epoch_length, 3)) @@ -89,12 +90,13 @@ for l in model_tea.layers: weights_tea = l.get_weights() - if len(weights_tea)>0: + if len(weights_tea) > 0: if num_gpu > 1: weights_stu = model_stu.get_layer(name=l.name).get_weights() else: weights_stu = model.get_layer(name=l.name).get_weights() - weights_tea = [C.alpha*w_tea + (1-C.alpha)*w_stu for (w_tea, w_stu) in zip(weights_tea, weights_stu)] + weights_tea = [C.alpha * w_tea + (1 - C.alpha) * w_stu for (w_tea, w_stu) in + zip(weights_tea, weights_stu)] l.set_weights(weights_tea) # print loss_s1 losses[iter_num, 0] = loss_s1[1] @@ -107,12 +109,13 @@ iter_num += 1 if iter_num % 20 == 0: progbar.update(iter_num, - [('cls', np.mean(losses[:iter_num, 0])), ('regr_h', np.mean(losses[:iter_num, 1])), ('offset', np.mean(losses[:iter_num, 2]))]) + [('cls', np.mean(losses[:iter_num, 0])), ('regr_h', np.mean(losses[:iter_num, 1])), + ('offset', np.mean(losses[:iter_num, 2]))]) if iter_num == epoch_length: cls_loss1 = np.mean(losses[:, 0]) regr_loss1 = np.mean(losses[:, 1]) offset_loss1 = np.mean(losses[:, 2]) - total_loss = cls_loss1+regr_loss1+offset_loss1 + total_loss = cls_loss1 + regr_loss1 + offset_loss1 total_loss_r.append(total_loss) cls_loss_r1.append(cls_loss1) @@ -127,7 +130,8 @@ if total_loss < best_loss: print(('Total loss decreased from {} to {}, saving weights'.format(best_loss, total_loss))) best_loss = total_loss - model_tea.save_weights(os.path.join(out_path, 'net_e{}_l{}.hdf5'.format(epoch_num + 1 + add_epoch, total_loss))) + model_tea.save_weights( + os.path.join(out_path, 'net_e{}_l{}.hdf5'.format(epoch_num + 1 + add_epoch, total_loss))) break except Exception as e: print(('Exception: {}'.format(e))) @@ -138,4 +142,4 @@ np.asarray(offset_loss_r1).reshape((-1, 1)),), axis=-1) np.savetxt(res_file, np.array(records), fmt='%.6f') -print('Training complete, exiting.') \ No newline at end of file +print('Training complete, exiting.') From 430ea01450ce375f025ff5d46e37ee2774e4eb15 Mon Sep 17 00:00:00 2001 From: dominik andreas Date: Wed, 7 Aug 2019 08:24:16 +0200 Subject: [PATCH 16/18] added note about opencv version --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 79c6462..6154e68 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Besides the superority on pedestrian detection demonstrated in the paper, we tak * Python >= 3.6 * Tensorflow >= 1.1.3 * Keras >= 2.0.6 -* OpenCV >= 3.4.1.15 +* OpenCV >= 3.4.1.15 (note that other versions than 3.4.1.15 will result in different performance on Caltech) ## Contents 1. [Installation](#installation) @@ -38,7 +38,7 @@ Besides the superority on pedestrian detection demonstrated in the paper, we tak python setup.py build_ext --inplace ``` -4. Download pretrained weights: +4. Download pretrained resnet50 weights (basenet only): ``` ./download_weights.sh ``` From 482a8b2d968d0428889a2b8eeb7138da630b28a5 Mon Sep 17 00:00:00 2001 From: dominik andreas Date: Wed, 7 Aug 2019 08:24:40 +0200 Subject: [PATCH 17/18] updated pickle loading of scripts for compatibility to python2 pickled files --- test_caltech.py | 2 +- test_wider_ms.py | 2 +- train_caltech.py | 4 ++-- train_wider.py | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test_caltech.py b/test_caltech.py index 553fdd4..7cf8926 100644 --- a/test_caltech.py +++ b/test_caltech.py @@ -12,7 +12,7 @@ C.offset = True cache_path = 'data/cache/caltech/test' with open(cache_path, 'rb') as fid: - val_data = pickle.load(fid) + val_data = pickle.load(fid, encoding='latin1') num_imgs = len(val_data) print('num of val samples: {}'.format(num_imgs)) diff --git a/test_wider_ms.py b/test_wider_ms.py index 46aa25d..b8b2169 100644 --- a/test_wider_ms.py +++ b/test_wider_ms.py @@ -13,7 +13,7 @@ C.num_scale = 2 cache_path = 'data/cache/widerface/val' with open(cache_path, 'rb') as fid: - val_data = pickle.load(fid) + val_data = pickle.load(fid, encoding='latin1') num_imgs = len(val_data) print('num of val samples: {}'.format(num_imgs)) diff --git a/train_caltech.py b/train_caltech.py index 866fd1f..ec6b0f1 100644 --- a/train_caltech.py +++ b/train_caltech.py @@ -27,9 +27,9 @@ cache_ped = 'data/cache/caltech/train_gt' cache_emp = 'data/cache/caltech/train_nogt' with open(cache_ped, 'rb') as fid: - ped_data = pickle.load(fid) + ped_data = pickle.load(fid, encoding='latin1') with open(cache_emp, 'rb') as fid: - emp_data = pickle.load(fid) + emp_data = pickle.load(fid, encoding='latin1') num_imgs_ped = len(ped_data) num_imgs_emp = len(emp_data) print(('num of ped and emp samples: {} {}'.format(num_imgs_ped, num_imgs_emp))) diff --git a/train_wider.py b/train_wider.py index 6e56ad1..34ffd6f 100644 --- a/train_wider.py +++ b/train_wider.py @@ -28,7 +28,7 @@ # get the training data cache_path = 'data/cache/widerface/train' with open(cache_path, 'rb') as fid: - train_data = pickle.load(fid) + train_data = pickle.load(fid, encoding='latin1') num_imgs_train = len(train_data) print('num of training samples: {}'.format(num_imgs_train)) data_gen_train = data_generators.get_data_wider(train_data, C, batchsize=batchsize) From e4a5a3770609896d3ab4b164c434ce80746225e6 Mon Sep 17 00:00:00 2001 From: dominikandreas <13525040+dominikandreas@users.noreply.github.com> Date: Tue, 20 Aug 2019 08:40:14 +0200 Subject: [PATCH 18/18] Update Readme: Fix broken link to paper Paper link was a broken reference inside this repository, new link targets official CVPR version of the paper --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6154e68..35e84a4 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # High-level Semantic Feature Detection: A New Perspective for Pedestrian Detection Keras implementation of [CSP] accepted by CVPR 2019. ## Introduction -This paper provides a new perspective for detecting pedestrians where detection is formulated as Center and Scale Prediction (CSP), the pipeline is illustrated in the following. For more details, please refer to our [paper](./docs/2019CVPR-CSP.pdf). +This paper provides a new perspective for detecting pedestrians where detection is formulated as Center and Scale Prediction (CSP), the pipeline is illustrated in the following. For more details, please refer to our [paper](http://openaccess.thecvf.com/content_CVPR_2019/papers/Liu_High-Level_Semantic_Feature_Detection_A_New_Perspective_for_Pedestrian_Detection_CVPR_2019_paper.pdf). ![img01](./docs/pipeline.png) Besides the superority on pedestrian detection demonstrated in the paper, we take a step further towards the generablity of CSP and validate it on face detection. Experimental reults on WiderFace benchmark also show the competitiveness of CSP.