00001
00002
00003
00004
00005
00006
00007
00008
00009 import numpy as np
00010 import mxnet as mx
00011 from mxnet.executor_manager import _split_input_slice
00012
00013 from config.config import config
00014 from utils.image import tensor_vstack
00015 from rpn.rpn import get_rpn_testbatch, get_rpn_batch, assign_anchor
00016 from rcnn import get_rcnn_testbatch, get_rcnn_batch
00017
00018
00019 class TestLoader(mx.io.DataIter):
00020 def __init__(self, roidb, config, batch_size=1, shuffle=False,
00021 has_rpn=False):
00022 super(TestLoader, self).__init__()
00023
00024
00025 self.cfg = config
00026 self.roidb = roidb
00027 self.batch_size = batch_size
00028 self.shuffle = shuffle
00029 self.has_rpn = has_rpn
00030
00031
00032 self.size = len(self.roidb)
00033 self.index = np.arange(self.size)
00034
00035
00036 if has_rpn:
00037 self.data_name = ['data', 'im_info']
00038 else:
00039 self.data_name = ['data', 'rois']
00040 self.label_name = None
00041
00042
00043 self.cur = 0
00044 self.data = None
00045 self.label = []
00046 self.im_info = None
00047
00048
00049 self.reset()
00050 self.get_batch()
00051
00052 @property
00053 def provide_data(self):
00054 return [[(k, v.shape) for k, v in zip(self.data_name, idata)] for idata in self.data]
00055
00056 @property
00057 def provide_label(self):
00058 return [None for _ in range(len(self.data))]
00059
00060 @property
00061 def provide_data_single(self):
00062 return [(k, v.shape) for k, v in zip(self.data_name, self.data[0])]
00063
00064 @property
00065 def provide_label_single(self):
00066 return None
00067
00068 def reset(self):
00069 self.cur = 0
00070 if self.shuffle:
00071 np.random.shuffle(self.index)
00072
00073 def iter_next(self):
00074 return self.cur < self.size
00075
00076 def next(self):
00077 if self.iter_next():
00078 self.get_batch()
00079 self.cur += self.batch_size
00080 return self.im_info, mx.io.DataBatch(data=self.data, label=self.label,
00081 pad=self.getpad(), index=self.getindex(),
00082 provide_data=self.provide_data, provide_label=self.provide_label)
00083 else:
00084 raise StopIteration
00085
00086 def getindex(self):
00087 return self.cur / self.batch_size
00088
00089 def getpad(self):
00090 if self.cur + self.batch_size > self.size:
00091 return self.cur + self.batch_size - self.size
00092 else:
00093 return 0
00094
00095 def get_batch(self):
00096 cur_from = self.cur
00097 cur_to = min(cur_from + self.batch_size, self.size)
00098 roidb = [self.roidb[self.index[i]] for i in range(cur_from, cur_to)]
00099 if self.has_rpn:
00100 data, label, im_info = get_rpn_testbatch(roidb, self.cfg)
00101 else:
00102 data, label, im_info = get_rcnn_testbatch(roidb, self.cfg)
00103 self.data = [[mx.nd.array(idata[name]) for name in self.data_name] for idata in data]
00104 self.im_info = im_info
00105
00106 def get_batch_individual(self):
00107 cur_from = self.cur
00108 cur_to = min(cur_from + self.batch_size, self.size)
00109 roidb = [self.roidb[self.index[i]] for i in range(cur_from, cur_to)]
00110 if self.has_rpn:
00111 data, label, im_info = get_rpn_testbatch(roidb, self.cfg)
00112 else:
00113 data, label, im_info = get_rcnn_testbatch(roidb, self.cfg)
00114 self.data = [mx.nd.array(data[name]) for name in self.data_name]
00115 self.im_info = im_info
00116
00117
00118 class ROIIter(mx.io.DataIter):
00119 def __init__(self, roidb, config, batch_size=2, shuffle=False, ctx=None, work_load_list=None, aspect_grouping=False):
00120 """
00121 This Iter will provide roi data to Fast R-CNN network
00122 :param roidb: must be preprocessed
00123 :param batch_size: must divide BATCH_SIZE(128)
00124 :param shuffle: bool
00125 :param ctx: list of contexts
00126 :param work_load_list: list of work load
00127 :param aspect_grouping: group images with similar aspects
00128 :return: ROIIter
00129 """
00130 super(ROIIter, self).__init__()
00131
00132
00133 self.roidb = roidb
00134 self.cfg = config
00135 self.batch_size = batch_size
00136 self.shuffle = shuffle
00137 self.ctx = ctx
00138 if self.ctx is None:
00139 self.ctx = [mx.cpu()]
00140 self.work_load_list = work_load_list
00141 self.aspect_grouping = aspect_grouping
00142
00143
00144 self.size = len(roidb)
00145 self.index = np.arange(self.size)
00146
00147
00148 self.data_name = ['data', 'rois']
00149 self.label_name = ['label', 'bbox_target', 'bbox_weight']
00150
00151
00152 self.cur = 0
00153 self.batch = None
00154 self.data = None
00155 self.label = None
00156
00157
00158 self.reset()
00159 self.get_batch_individual()
00160
00161 @property
00162 def provide_data(self):
00163 return [[(k, v.shape) for k, v in zip(self.data_name, self.data[i])] for i in xrange(len(self.data))]
00164
00165 @property
00166 def provide_label(self):
00167 return [[(k, v.shape) for k, v in zip(self.label_name, self.label[i])] for i in xrange(len(self.data))]
00168
00169 @property
00170 def provide_data_single(self):
00171 return [(k, v.shape) for k, v in zip(self.data_name, self.data[0])]
00172
00173 @property
00174 def provide_label_single(self):
00175 return [(k, v.shape) for k, v in zip(self.label_name, self.label[0])]
00176
00177 def reset(self):
00178 self.cur = 0
00179 if self.shuffle:
00180 if self.aspect_grouping:
00181 widths = np.array([r['width'] for r in self.roidb])
00182 heights = np.array([r['height'] for r in self.roidb])
00183 horz = (widths >= heights)
00184 vert = np.logical_not(horz)
00185 horz_inds = np.where(horz)[0]
00186 vert_inds = np.where(vert)[0]
00187 inds = np.hstack((np.random.permutation(horz_inds), np.random.permutation(vert_inds)))
00188 extra = inds.shape[0] % self.batch_size
00189 inds_ = np.reshape(inds[:-extra], (-1, self.batch_size))
00190 row_perm = np.random.permutation(np.arange(inds_.shape[0]))
00191 inds[:-extra] = np.reshape(inds_[row_perm, :], (-1,))
00192 self.index = inds
00193 else:
00194 np.random.shuffle(self.index)
00195
00196 def iter_next(self):
00197 return self.cur + self.batch_size <= self.size
00198
00199 def next(self):
00200 if self.iter_next():
00201 self.get_batch_individual()
00202 self.cur += self.batch_size
00203 return mx.io.DataBatch(data=self.data, label=self.label,
00204 pad=self.getpad(), index=self.getindex(),
00205 provide_data=self.provide_data, provide_label=self.provide_label)
00206 else:
00207 raise StopIteration
00208
00209 def getindex(self):
00210 return self.cur / self.batch_size
00211
00212 def getpad(self):
00213 if self.cur + self.batch_size > self.size:
00214 return self.cur + self.batch_size - self.size
00215 else:
00216 return 0
00217
00218 def get_batch(self):
00219
00220 cur_from = self.cur
00221 cur_to = min(cur_from + self.batch_size, self.size)
00222 roidb = [self.roidb[self.index[i]] for i in range(cur_from, cur_to)]
00223
00224
00225 work_load_list = self.work_load_list
00226 ctx = self.ctx
00227 if work_load_list is None:
00228 work_load_list = [1] * len(ctx)
00229 assert isinstance(work_load_list, list) and len(work_load_list) == len(ctx), \
00230 "Invalid settings for work load. "
00231 slices = _split_input_slice(self.batch_size, work_load_list)
00232
00233
00234 data_list = []
00235 label_list = []
00236 for islice in slices:
00237 iroidb = [roidb[i] for i in range(islice.start, islice.stop)]
00238 data, label = get_rcnn_batch(iroidb, self.cfg)
00239 data_list.append(data)
00240 label_list.append(label)
00241
00242 all_data = dict()
00243 for key in data_list[0].keys():
00244 all_data[key] = tensor_vstack([batch[key] for batch in data_list])
00245
00246 all_label = dict()
00247 for key in label_list[0].keys():
00248 all_label[key] = tensor_vstack([batch[key] for batch in label_list])
00249
00250 self.data = [mx.nd.array(all_data[name]) for name in self.data_name]
00251 self.label = [mx.nd.array(all_label[name]) for name in self.label_name]
00252
00253 def get_batch_individual(self):
00254
00255 cur_from = self.cur
00256 cur_to = min(cur_from + self.batch_size, self.size)
00257 roidb = [self.roidb[self.index[i]] for i in range(cur_from, cur_to)]
00258
00259
00260 work_load_list = self.work_load_list
00261 ctx = self.ctx
00262 if work_load_list is None:
00263 work_load_list = [1] * len(ctx)
00264 assert isinstance(work_load_list, list) and len(work_load_list) == len(ctx), \
00265 "Invalid settings for work load. "
00266 slices = _split_input_slice(self.batch_size, work_load_list)
00267
00268 rst = []
00269 for idx, islice in enumerate(slices):
00270 iroidb = [roidb[i] for i in range(islice.start, islice.stop)]
00271 rst.append(self.parfetch(iroidb))
00272
00273 all_data = [_['data'] for _ in rst]
00274 all_label = [_['label'] for _ in rst]
00275 self.data = [[mx.nd.array(data[key]) for key in self.data_name] for data in all_data]
00276 self.label = [[mx.nd.array(label[key]) for key in self.label_name] for label in all_label]
00277
00278 def parfetch(self, iroidb):
00279 data, label = get_rcnn_batch(iroidb, self.cfg)
00280 return {'data': data, 'label': label}
00281
00282
00283 class AnchorLoader(mx.io.DataIter):
00284
00285 def __init__(self, feat_sym, roidb, cfg, batch_size=1, shuffle=False, ctx=None, work_load_list=None,
00286 feat_stride=16, anchor_scales=(8, 16, 32), anchor_ratios=(0.5, 1, 2), allowed_border=0,
00287 aspect_grouping=False):
00288 """
00289 This Iter will provide roi data to Fast R-CNN network
00290 :param feat_sym: to infer shape of assign_output
00291 :param roidb: must be preprocessed
00292 :param batch_size: must divide BATCH_SIZE(128)
00293 :param shuffle: bool
00294 :param ctx: list of contexts
00295 :param work_load_list: list of work load
00296 :param aspect_grouping: group images with similar aspects
00297 :return: AnchorLoader
00298 """
00299 super(AnchorLoader, self).__init__()
00300
00301
00302 self.feat_sym = feat_sym
00303 self.roidb = roidb
00304 self.cfg = cfg
00305 self.batch_size = batch_size
00306 self.shuffle = shuffle
00307 self.ctx = ctx
00308 if self.ctx is None:
00309 self.ctx = [mx.cpu()]
00310 self.work_load_list = work_load_list
00311 self.feat_stride = feat_stride
00312 self.anchor_scales = anchor_scales
00313 self.anchor_ratios = anchor_ratios
00314 self.allowed_border = allowed_border
00315 self.aspect_grouping = aspect_grouping
00316
00317
00318 self.size = len(roidb)
00319 self.index = np.arange(self.size)
00320
00321
00322 if config.TRAIN.END2END:
00323 self.data_name = ['data', 'im_info', 'gt_boxes']
00324 else:
00325 self.data_name = ['data']
00326 self.label_name = ['label', 'bbox_target', 'bbox_weight']
00327
00328
00329 self.cur = 0
00330 self.batch = None
00331 self.data = None
00332 self.label = None
00333
00334
00335 self.reset()
00336 self.get_batch_individual()
00337
00338 @property
00339 def provide_data(self):
00340 return [[(k, v.shape) for k, v in zip(self.data_name, self.data[i])] for i in xrange(len(self.data))]
00341
00342 @property
00343 def provide_label(self):
00344 return [[(k, v.shape) for k, v in zip(self.label_name, self.label[i])] for i in xrange(len(self.data))]
00345
00346 @property
00347 def provide_data_single(self):
00348 return [(k, v.shape) for k, v in zip(self.data_name, self.data[0])]
00349
00350 @property
00351 def provide_label_single(self):
00352 return [(k, v.shape) for k, v in zip(self.label_name, self.label[0])]
00353
00354 def reset(self):
00355 self.cur = 0
00356 if self.shuffle:
00357 if self.aspect_grouping:
00358 widths = np.array([r['width'] for r in self.roidb])
00359 heights = np.array([r['height'] for r in self.roidb])
00360 horz = (widths >= heights)
00361 vert = np.logical_not(horz)
00362 horz_inds = np.where(horz)[0]
00363 vert_inds = np.where(vert)[0]
00364 inds = np.hstack((np.random.permutation(horz_inds), np.random.permutation(vert_inds)))
00365 extra = inds.shape[0] % self.batch_size
00366 inds_ = np.reshape(inds[:-extra], (-1, self.batch_size))
00367 row_perm = np.random.permutation(np.arange(inds_.shape[0]))
00368 inds[:-extra] = np.reshape(inds_[row_perm, :], (-1,))
00369 self.index = inds
00370 else:
00371 np.random.shuffle(self.index)
00372
00373 def iter_next(self):
00374 return self.cur + self.batch_size <= self.size
00375
00376 def next(self):
00377 if self.iter_next():
00378 self.get_batch_individual()
00379 self.cur += self.batch_size
00380 return mx.io.DataBatch(data=self.data, label=self.label,
00381 pad=self.getpad(), index=self.getindex(),
00382 provide_data=self.provide_data, provide_label=self.provide_label)
00383 else:
00384 raise StopIteration
00385
00386 def getindex(self):
00387 return self.cur / self.batch_size
00388
00389 def getpad(self):
00390 if self.cur + self.batch_size > self.size:
00391 return self.cur + self.batch_size - self.size
00392 else:
00393 return 0
00394
00395 def infer_shape(self, max_data_shape=None, max_label_shape=None):
00396 """ Return maximum data and label shape for single gpu """
00397 if max_data_shape is None:
00398 max_data_shape = []
00399 if max_label_shape is None:
00400 max_label_shape = []
00401 max_shapes = dict(max_data_shape + max_label_shape)
00402 input_batch_size = max_shapes['data'][0]
00403 im_info = [[max_shapes['data'][2], max_shapes['data'][3], 1.0]]
00404 _, feat_shape, _ = self.feat_sym.infer_shape(**max_shapes)
00405 label = assign_anchor(feat_shape[0], np.zeros((0, 5)), im_info, self.cfg,
00406 self.feat_stride, self.anchor_scales, self.anchor_ratios, self.allowed_border)
00407 label = [label[k] for k in self.label_name]
00408 label_shape = [(k, tuple([input_batch_size] + list(v.shape[1:]))) for k, v in zip(self.label_name, label)]
00409 return max_data_shape, label_shape
00410
00411 def get_batch(self):
00412
00413 cur_from = self.cur
00414 cur_to = min(cur_from + self.batch_size, self.size)
00415 roidb = [self.roidb[self.index[i]] for i in range(cur_from, cur_to)]
00416
00417
00418 work_load_list = self.work_load_list
00419 ctx = self.ctx
00420 if work_load_list is None:
00421 work_load_list = [1] * len(ctx)
00422 assert isinstance(work_load_list, list) and len(work_load_list) == len(ctx), \
00423 "Invalid settings for work load. "
00424 slices = _split_input_slice(self.batch_size, work_load_list)
00425
00426
00427 data_list = []
00428 label_list = []
00429 for islice in slices:
00430 iroidb = [roidb[i] for i in range(islice.start, islice.stop)]
00431 data, label = get_rpn_batch(iroidb, self.cfg)
00432 data_list.append(data)
00433 label_list.append(label)
00434
00435
00436 data_tensor = tensor_vstack([batch['data'] for batch in data_list])
00437 for data, data_pad in zip(data_list, data_tensor):
00438 data['data'] = data_pad[np.newaxis, :]
00439
00440 new_label_list = []
00441 for data, label in zip(data_list, label_list):
00442
00443 data_shape = {k: v.shape for k, v in data.items()}
00444 del data_shape['im_info']
00445 _, feat_shape, _ = self.feat_sym.infer_shape(**data_shape)
00446 feat_shape = [int(i) for i in feat_shape[0]]
00447
00448
00449 data['gt_boxes'] = label['gt_boxes'][np.newaxis, :, :]
00450
00451
00452 label = assign_anchor(feat_shape, label['gt_boxes'], data['im_info'], self.cfg,
00453 self.feat_stride, self.anchor_scales,
00454 self.anchor_ratios, self.allowed_border)
00455 new_label_list.append(label)
00456
00457 all_data = dict()
00458 for key in self.data_name:
00459 all_data[key] = tensor_vstack([batch[key] for batch in data_list])
00460
00461 all_label = dict()
00462 for key in self.label_name:
00463 pad = -1 if key == 'label' else 0
00464 all_label[key] = tensor_vstack([batch[key] for batch in new_label_list], pad=pad)
00465
00466 self.data = [mx.nd.array(all_data[key]) for key in self.data_name]
00467 self.label = [mx.nd.array(all_label[key]) for key in self.label_name]
00468
00469 def get_batch_individual(self):
00470 cur_from = self.cur
00471 cur_to = min(cur_from + self.batch_size, self.size)
00472 roidb = [self.roidb[self.index[i]] for i in range(cur_from, cur_to)]
00473
00474 work_load_list = self.work_load_list
00475 ctx = self.ctx
00476 if work_load_list is None:
00477 work_load_list = [1] * len(ctx)
00478 assert isinstance(work_load_list, list) and len(work_load_list) == len(ctx), \
00479 "Invalid settings for work load. "
00480 slices = _split_input_slice(self.batch_size, work_load_list)
00481 rst = []
00482 for idx, islice in enumerate(slices):
00483 iroidb = [roidb[i] for i in range(islice.start, islice.stop)]
00484 rst.append(self.parfetch(iroidb))
00485 all_data = [_['data'] for _ in rst]
00486 all_label = [_['label'] for _ in rst]
00487 self.data = [[mx.nd.array(data[key]) for key in self.data_name] for data in all_data]
00488 self.label = [[mx.nd.array(label[key]) for key in self.label_name] for label in all_label]
00489
00490 def parfetch(self, iroidb):
00491
00492 data, label = get_rpn_batch(iroidb, self.cfg)
00493 data_shape = {k: v.shape for k, v in data.items()}
00494 del data_shape['im_info']
00495 _, feat_shape, _ = self.feat_sym.infer_shape(**data_shape)
00496 feat_shape = [int(i) for i in feat_shape[0]]
00497
00498
00499 data['gt_boxes'] = label['gt_boxes'][np.newaxis, :, :]
00500
00501
00502 label = assign_anchor(feat_shape, label['gt_boxes'], data['im_info'], self.cfg,
00503 self.feat_stride, self.anchor_scales,
00504 self.anchor_ratios, self.allowed_border)
00505 return {'data': data, 'label': label}
00506