loader.py
Go to the documentation of this file.
00001 # --------------------------------------------------------
00002 # Deformable Convolutional Networks
00003 # Copyright (c) 2016 by Contributors
00004 # Copyright (c) 2017 Microsoft
00005 # Licensed under The Apache-2.0 License [see LICENSE for details]
00006 # Modified by Yuwen Xiong
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         # save parameters as properties
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         # infer properties from roidb
00032         self.size = len(self.roidb)
00033         self.index = np.arange(self.size)
00034 
00035         # decide data and label names (only for training)
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         # status variable for synchronization between get_data and get_label
00043         self.cur = 0
00044         self.data = None
00045         self.label = []
00046         self.im_info = None
00047 
00048         # get first batch to fill in provide_data and provide_label
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         # save parameters as properties
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         # infer properties from roidb
00144         self.size = len(roidb)
00145         self.index = np.arange(self.size)
00146 
00147         # decide data and label names (only for training)
00148         self.data_name = ['data', 'rois']
00149         self.label_name = ['label', 'bbox_target', 'bbox_weight']
00150 
00151         # status variable for synchronization between get_data and get_label
00152         self.cur = 0
00153         self.batch = None
00154         self.data = None
00155         self.label = None
00156 
00157         # get first batch to fill in provide_data and provide_label
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         # slice roidb
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         # decide multi device slices
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         # get each device
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         # slice roidb
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         # decide multi device slices
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         # save parameters as properties
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         # infer properties from roidb
00318         self.size = len(roidb)
00319         self.index = np.arange(self.size)
00320 
00321         # decide data and label names
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         # status variable for synchronization between get_data and get_label
00329         self.cur = 0
00330         self.batch = None
00331         self.data = None
00332         self.label = None
00333 
00334         # get first batch to fill in provide_data and provide_label
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         # slice roidb
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         # decide multi device slice
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         # get testing data for multigpu
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         # pad data first and then assign anchor (read label)
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             # infer label shape
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             # add gt_boxes to data for e2e
00449             data['gt_boxes'] = label['gt_boxes'][np.newaxis, :, :]
00450 
00451             # assign anchor for label
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         # decide multi device slice
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         # get testing data for multigpu
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         # add gt_boxes to data for e2e
00499         data['gt_boxes'] = label['gt_boxes'][np.newaxis, :, :]
00500 
00501         # assign anchor for label
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 


rail_object_detector
Author(s):
autogenerated on Sat Jun 8 2019 20:26:30