def __init__(self, params, indexlist, phase, proc_id):
        super(BatchLoader, self).__init__()
        self.indexlist = indexlist
        self.proc_id = proc_id
        self.batch_size = params['batch_size']
        self.im_shape = params['im_shape']
        self.phase = phase
        self.queue = Queue(_QSIZE)
        #rec_conn, send_conn = Pipe()
        # self.rec_conn = rec_conn
        # self.send_conn = send_conn
        ## Dividing with rest the batch size for the jobs we have
        self.batch_ck_size = self.batch_size // _nJobs
        ## in case of the last jobs adding the rest
        if self.proc_id == (_nJobs - 1):
            self.batch_ck_size += self.batch_size % _nJobs
        ## Opening LMDB
        lmdb_output_pose_env = lmdb.Environment(params['source'] +
                                                '/pose_lmdb/',
                                                readonly=True,
                                                lock=False)
        self.cur_pose = lmdb_output_pose_env.begin().cursor()
        lmdb_output_flip_env = lmdb.Environment(params['source'] +
                                                '/flip_lmdb/',
                                                readonly=True,
                                                lock=False)
        self.cur_flip = lmdb_output_flip_env.begin().cursor()
        lmdb_output_land_env = lmdb.Environment(params['source'] +
                                                '/land_lmdb/',
                                                readonly=True,
                                                lock=False)
        self.cur_land = lmdb_output_land_env.begin().cursor()
        ################
        self.Nimgs = len(self.indexlist)
        # this class does some simple data-manipulations
        #proto_data = open(params['mean_file'], "rb").read()

        #a = caffe.io.caffe_pb2.BlobProto.FromString(proto_data)
        #mean  = caffe.io.blobproto_to_array(a)[0]
        ## mean is read BGR and c,h,w; we convert it to h,w,c.
        ## BGR is OK since OpenCV and caffe are BGR
        ## Then MySimpleTransformer will remove mean after that the image
        ## has been changed to BGR as well. So apple-to-apple.
        self.transformer = MySimpleTransformer()
        self.aug_tr = aug_tracker.AugmentationTracker()

        if params['mean_file'] is not None:
            mean = np.load(params['mean_file'])
            mean = mean.transpose(1, 2, 0)
            mean = np.float32(mean)
            self.transformer.set_mean(mean)

        if self.phase == 1:
            util.myprint("BatchLoader_valid" + str(self.proc_id) +
                         " initialized with " + str(self.Nimgs) + " images")
        else:
            util.myprint("BatchLoader_train" + str(self.proc_id) +
                         "  initialized with " + str(self.Nimgs) + " images")
            util.myprint("This will process: " + str(self.batch_ck_size) +
                         '/' + str(self.batch_size))
Example #2
0
class BatchLoader(Process):
    """
    This class abstracts away the loading of images.
    Images can either be loaded singly, or in a batch. The latter is used for
    the asyncronous data layer to preload batches while other processing is
    performed.
    """

    def __init__(self, params, indexlist, phase, proc_id):
        super(BatchLoader, self).__init__()
        self.indexlist = indexlist
        self.proc_id = proc_id
        self.batch_size = params['batch_size']
        self.im_shape = params['im_shape']
        self.phase = phase
        self.queue = Queue(_QSIZE)
        #rec_conn, send_conn = Pipe()
        # self.rec_conn = rec_conn
        # self.send_conn = send_conn
        ## Dividing with rest the batch size for the jobs we have
        self.batch_ck_size = self.batch_size//_nJobs
        ## in case of the last jobs adding the rest
        if self.proc_id == (_nJobs - 1):
                self.batch_ck_size += self.batch_size % _nJobs
        ## Opening LMDB
        lmdb_output_pose_env = lmdb.Environment(params['source']+'/pose_lmdb/', readonly=True, lock=False)
        self.cur_pose = lmdb_output_pose_env.begin().cursor()
        lmdb_output_flip_env = lmdb.Environment(params['source']+'/flip_lmdb/', readonly=True, lock=False)
        self.cur_flip = lmdb_output_flip_env.begin().cursor()
        lmdb_output_land_env = lmdb.Environment(params['source']+'/land_lmdb/', readonly=True, lock=False)
        self.cur_land = lmdb_output_land_env.begin().cursor()
        ################
        self.Nimgs = len(self.indexlist)
        # this class does some simple data-manipulations
        #proto_data = open(params['mean_file'], "rb").read()
        
        #a = caffe.io.caffe_pb2.BlobProto.FromString(proto_data)
        #mean  = caffe.io.blobproto_to_array(a)[0]
        ## mean is read BGR and c,h,w; we convert it to h,w,c.
        ## BGR is OK since OpenCV and caffe are BGR
        ## Then MySimpleTransformer will remove mean after that the image
        ## has been changed to BGR as well. So apple-to-apple.
        self.transformer = MySimpleTransformer()
        self.aug_tr = aug_tracker.AugmentationTracker()

        if params['mean_file'] is not None:
            mean = np.load(params['mean_file'])
            mean = mean.transpose(1, 2, 0)
            mean = np.float32(mean)
            self.transformer.set_mean(mean)

        if self.phase == 1:
            util.myprint("BatchLoader_valid" + str(self.proc_id) + " initialized with " + str(self.Nimgs) +" images")
        else:
            util.myprint("BatchLoader_train" + str(self.proc_id) + "  initialized with " + str(self.Nimgs) +" images")
            util.myprint("This will process: " + str(self.batch_ck_size)+'/'+str(self.batch_size) )

    def run(self):
        if self.phase == 1:
            util.myprint("Process started pre-fetching for Validation " + str(self.proc_id) + " : nimgs " + str(self.Nimgs) )
        else:
            util.myprint("Process started pre-fetching for Training " + str(self.proc_id) + " : nimgs " + str(self.Nimgs) )
        ## Counter to the entire augmented set
        count = 0
        ## Counter to the relative mini-batch
        countStep = 0
        ## Pre-allocate the data for the mini-batch
        listData = [None]*self.batch_ck_size
        while True:
            for ii in range(0,self.Nimgs):
                ####### Checking if we finished an (augmented) epoch
                if  count == self.Nimgs:
                    util.myprint("Finished an (augmented) epoch for loader id " + str(self.proc_id) + "...shuffling")
                    count = 0
                    shuffle(self.indexlist)

                # ######## Part to resume/wait a certain process when the other is operating
                # if self.phase == 1:
                #     if not _eventValidList[self.proc_id].is_set():
                #         util.myprint('Waiting Validation Loader ' + str(self.proc_id) + ' to start again')
                #         _eventValidList[self.proc_id].wait()
                # else:
                #     if not _eventTrainList[self.proc_id].is_set():
                #         util.myprint('Waiting Train Loader ' + str(self.proc_id) + ' to start again')
                #         _eventTrainList[self.proc_id].wait()

                ### Starting to do augmentation
                batch_img = None
                #index is of form:
                #blur_fr_13 XXXm.0hhvfrvXXX_MS000024 !!TMPDIR!!/imgs/XXXm.0hhvfrvXXX/XXXm.0hhvfrvXXX_MS000024.jpg 0
                index = self.indexlist[ii]
                index = index.split(' ')
                aug_type = index[0] #augemntation type
                image_key = index[1] # image key
                image_file_name = index[2] #image
                label = np.float32(index[3]) #label
                ## Loading the image with OpenCV
                flipON = int( np.frombuffer( self.cur_flip.get(image_key) )[1] ) == 1
                im = cv2.imread(image_file_name,cv2.CV_LOAD_IMAGE_COLOR)
                ## Check immediately if we have to flip an image
                if flipON:
                    im = cv2.flip(im, 1)
                im_arr = np.asarray(im)
                aug_im = None
                if 'align2d' in aug_type or 'blur' in aug_type:
                    lmark = self.cur_land.get(image_key)
                    lmark = np.frombuffer(lmark, dtype='float64').reshape(68,2)
                    lmarks = np.zeros((1,68,2))
                    lmarks[0] = lmark
                    aug_im = self.aug_tr.augment_fast(aug_type=aug_type,img=im,landmarks=lmarks,flipON=flipON)
                elif 'render' in aug_type:                    
                    prj_matrix = np.frombuffer(self.cur_pose.get(image_key+'_'+aug_type), dtype='float64').reshape(3,4)
                    prj_matrix = np.asmatrix(prj_matrix)
                    aug_im = self.aug_tr.augment_fast(aug_type=aug_type,img=im,prj_matrix=prj_matrix,flipON=flipON)
                try:
                    aug_im = cv2.resize(aug_im, ( self.im_shape[0], self.im_shape[1] ),\
                                          interpolation=cv2.INTER_LINEAR )
                    batch_img = self.transformer.preprocess(aug_im)
                except Exception as ex:
                    util.myprint("Warning: Was not able to use aug_img because: " + str(ex))
                    util.myprint( "Skipping the image: " + image_file_name)
                count += 1
                ##If image have been processes correctly, add it to the mini-batch            
                if batch_img is not None:
                    data = {'img': batch_img , 'label' : label}
                    listData[countStep] = data 
                    countStep+=1
                    if countStep == self.batch_ck_size:
                        isDone = False
                        while not isDone:
                            try:
                                ##This mini-batch is ready to be sent for train
                                ## Resetting the relative listData and countStep
                                self.queue.put_nowait( list(listData) )
                            except std_Queue.Full as full:
                                pass
                            else:
                                #self.send_conn.send( (listData) )
                                countStep = 0
                                isDone = True
                                listData = [None]*self.batch_ck_size