from ...utils.pascal_voc_clean_xml import pascal_voc_clean_xml from numpy.random import permutation as perm from .predict import preprocess # from .misc import show from copy import deepcopy import pickle import numpy as np import os def parse(self, exclusive = False): meta = self.meta ext = '.parsed' ann = self.FLAGS.annotation if not os.path.isdir(ann): msg = 'Annotation directory not found {} .' exit('Error: {}'.format(msg.format(ann))) print('\n{} parsing {}'.format(meta['model'], ann)) dumps = pascal_voc_clean_xml(ann, meta['labels'], exclusive) return dumps def _batch(self, chunk): """ Takes a chunk of parsed annotations returns value for placeholders of net's input & loss layer correspond to this chunk """ meta = self.meta S, B = meta['side'], meta['num'] C, labels = meta['classes'], meta['labels'] # preprocess jpg = chunk[0]; w, h, allobj_ = chunk[1] allobj = deepcopy(allobj_) path = os.path.join(self.FLAGS.dataset, jpg) img = self.preprocess(path, allobj) # Calculate regression target cellx = 1. * w / S celly = 1. * h / S for obj in allobj: centerx = .5*(obj[1]+obj[3]) #xmin, xmax centery = .5*(obj[2]+obj[4]) #ymin, ymax cx = centerx / cellx cy = centery / celly if cx >= S or cy >= S: return None, None obj[3] = float(obj[3]-obj[1]) / w obj[4] = float(obj[4]-obj[2]) / h obj[3] = np.sqrt(obj[3]) obj[4] = np.sqrt(obj[4]) obj[1] = cx - np.floor(cx) # centerx obj[2] = cy - np.floor(cy) # centery obj += [int(np.floor(cy) * S + np.floor(cx))] # show(im, allobj, S, w, h, cellx, celly) # unit test # Calculate placeholders' values probs = np.zeros([S*S,C]) confs = np.zeros([S*S,B]) coord = np.zeros([S*S,B,4]) proid = np.zeros([S*S,C]) prear = np.zeros([S*S,4]) for obj in allobj: probs[obj[5], :] = [0.] * C probs[obj[5], labels.index(obj[0])] = 1. proid[obj[5], :] = [1] * C coord[obj[5], :, :] = [obj[1:5]] * B prear[obj[5],0] = obj[1] - obj[3]**2 * .5 * S # xleft prear[obj[5],1] = obj[2] - obj[4]**2 * .5 * S # yup prear[obj[5],2] = obj[1] + obj[3]**2 * .5 * S # xright prear[obj[5],3] = obj[2] + obj[4]**2 * .5 * S # ybot confs[obj[5], :] = [1.] * B # Finalise the placeholders' values upleft = np.expand_dims(prear[:,0:2], 1) botright = np.expand_dims(prear[:,2:4], 1) wh = botright - upleft; area = wh[:,:,0] * wh[:,:,1] upleft = np.concatenate([upleft] * B, 1) botright = np.concatenate([botright] * B, 1) areas = np.concatenate([area] * B, 1) # value for placeholder at input layer inp_feed_val = img # value for placeholder at loss layer loss_feed_val = { 'probs': probs, 'confs': confs, 'coord': coord, 'proid': proid, 'areas': areas, 'upleft': upleft, 'botright': botright } return inp_feed_val, loss_feed_val def shuffle(self): batch = self.FLAGS.batch data = self.parse() size = len(data) print('Dataset of {} instance(s)'.format(size)) if batch > size: self.FLAGS.batch = batch = size batch_per_epoch = int(size / batch) for i in range(self.FLAGS.epoch): shuffle_idx = perm(np.arange(size)) for b in range(batch_per_epoch): # yield these x_batch = list() feed_batch = dict() for j in range(b*batch, b*batch+batch): train_instance = data[shuffle_idx[j]] try: inp, new_feed = self._batch(train_instance) except ZeroDivisionError: print("This image's width or height are zeros: ", train_instance[0]) print('train_instance:', train_instance) print('Please remove or fix it then try again.') raise if inp is None: continue x_batch += [np.expand_dims(inp, 0)] for key in new_feed: new = new_feed[key] old_feed = feed_batch.get(key, np.zeros((0,) + new.shape)) feed_batch[key] = np.concatenate([ old_feed, [new] ]) x_batch = np.concatenate(x_batch, 0) yield x_batch, feed_batch print('Finish {} epoch(es)'.format(i + 1))