      if numpy.random.random() < random_flip:
          result = result[:, ::-1]
      return result
  
  # get pair of random warped images from aligened face image
  
  def random_warp(image):
      assert image.shape == (256, 256, 3)
      range_ = numpy.linspace(128 - 80, 128 + 80, 5)
      mapx = numpy.broadcast_to(range_, (5, 5))
      mapy = mapx.T
 
</s> remove     range_ = numpy.linspace(128 - 80, 128 + 80, 5)
 </s> add     range_ = numpy.linspace(128 - coverage//2, 128 + coverage//2, 5)
 </s> remove def get_training_data(images, batch_size):
    indices = numpy.random.randint(len(images), size=batch_size)
    for i, index in enumerate(indices):
        image = images[index]
        image = random_transform(image, **random_transform_args)
        warped_img, target_img = random_warp(image)

        if i == 0:
            warped_images = numpy.empty(
                (batch_size,) + warped_img.shape, warped_img.dtype)
            target_images = numpy.empty(
                (batch_size,) + target_img.shape, warped_img.dtype)

        warped_images[i] = warped_img
        target_images[i] = target_img

    return warped_images, target_images
 </s> add # GAN
# random_transform_args = {
#     'rotation_range': 20,
#     'zoom_range': 0.1,
#     'shift_range': 0.05,
#     'random_flip': 0.5,
#     }
def read_image(fn, random_transform_args=random_transform_args):
    image = cv2.imread(fn) / 255.0
    image = cv2.resize(image, (256,256))
    image = random_transform( image, **random_transform_args )
    warped_img, target_img = random_warp( image )
    
    return warped_img, target_img

# A generator function that yields epoch, batchsize of warped_img and batchsize of target_img
def minibatch(data, batchsize):
    length = len(data)
    epoch = i = 0
    shuffle(data)
    while True:
        size = batchsize
        if i+size > length:
            shuffle(data)
            i = 0
            epoch+=1        
        rtn = numpy.float32([read_image(data[j]) for j in range(i,i+size)])
        i+=size
        yield epoch, rtn[:,0,:,:,:], rtn[:,1,:,:,:]       

def minibatchAB(images, batchsize):
    batch = BackgroundGenerator(minibatch(images, batchsize), 1)
    for ep1, warped_img, target_img in batch.iterator():
        yield ep1, warped_img, target_img
 </s> remove 
        self.finalize()
 </s> add     
    def get_faces(self, image):
        faces_count = 0
        for face in detect_faces(image):
            if self.filter is not None and not self.filter.check(face):
                print('Skipping not recognized face!')
                continue

            yield faces_count, face

            self.faces_detected = self.faces_detected + 1
            faces_count +=1
        
        if faces_count > 0 and self.arguments.verbose:
            print('Note: Found more than one face in an image!')
            self.verify_output = True
    
    def load_filter(self):
        filter_file = "filter.jpg" # TODO Pass as argument
        if Path(filter_file).exists():
            print('Loading reference image for filtering')
            return FaceFilter(filter_file) </s> remove def load_images(image_paths, convert=None):
    iter_all_images = (cv2.imread(fn) for fn in image_paths)
    if convert:
        iter_all_images = (convert(img) for img in iter_all_images)
    for i, image in enumerate(iter_all_images):
        if i == 0:
            all_images = numpy.empty((len(image_paths), ) + image.shape, dtype=image.dtype)
        all_images[i] = image
    return all_images
 </s> add     def iterator(self):
        while True:
            next_item = self.queue.get()
            if next_item is None:
                break
            yield next_item </s> remove         images_A = load_images(images_A) / 255.0
        images_B = load_images(images_B) / 255.0

        images_A += images_B.mean(axis=(0, 1, 2)) - images_A.mean(axis=(0, 1, 2))

        print('press "q" to stop training and save model')

        BATCH_SIZE = 64

        for epoch in range(1000000):
            if self.arguments.verbose:
                print("Iteration number {}".format(epoch + 1))
                start_time = time.time()
            warped_A, target_A = get_training_data(images_A, BATCH_SIZE)
            warped_B, target_B = get_training_data(images_B, BATCH_SIZE)

            loss_A = autoencoder_A.train_on_batch(warped_A, target_A)
            loss_B = autoencoder_B.train_on_batch(warped_B, target_B)
            print(loss_A, loss_B)

            if epoch % self.arguments.save_interval == 0:
                self.save_model_weights()
                self.show_sample(target_A[0:14], target_B[0:14])

            key = cv2.waitKey(1)
            if key == ord('q'):
                self.save_model_weights()
                exit()
            if self.arguments.verbose:
                end_time = time.time()
                time_elapsed = int(round((end_time - start_time)))
                m, s = divmod(time_elapsed, 60)
                h, m = divmod(m, 60)
                print("Iteration done in {:02d}h{:02d}m{:02d}s".format(h, m, s))
 </s> add         trainer = PluginLoader.get_trainer(variant)(model, images_A, images_B)

        try:
            print('Starting. Press "Enter" to stop training and save model')

            for epoch in range(0, 1000000):

                save_iteration = epoch % self.arguments.save_interval == 0

                trainer.train_one_step(epoch, self.show if save_iteration else None)

                if save_iteration:
                    model.save_weights()

                if self.stop:
                    model.save_weights()
                    exit()

        except KeyboardInterrupt:
            try:
                model.save_weights()
            except KeyboardInterrupt:
                print('Saving model weights has been cancelled!')
            exit(0)

    preview_buffer = {}

    def show(self, image, name=''):
        try:
            if self.arguments.preview:
                self.preview_buffer[name] = image
            elif self.arguments.write_image:
                cv2.imwrite('_sample_{}.jpg'.format(name), image)
        except Exception as e:
            print("could not preview sample")
            print(e)
# get pair of random warped images from aligned face image

      if numpy.random.random() < random_flip:
          result = result[:, ::-1]
      return result
  
# get pair of random warped images from aligned face image
# get pair of random warped images from aligned face image
  def random_warp(image):
      assert image.shape == (256, 256, 3)
      range_ = numpy.linspace(128 - 80, 128 + 80, 5)
      mapx = numpy.broadcast_to(range_, (5, 5))
      mapy = mapx.T
keep keep keep keep replace replace keep keep keep keep keep
 Adding models as plugins + Face filtering (#53) + #39 + #43 + #44 + #49 (#61)

* Making Models as plugins

* Do not reload model on each image #39 + Adding FaceFilter #53

* Adding @lukaville PR for #43 and #44 (possibly)

* Training done in a separate thread

* Better log for plugin load

* Adding a prefetch to train.py #49
(Note that we prefetch 2 batches of images, due to the queue behavior)
+ More compact logging with verbose info included

* correction of DirectoryProcessor signature

* adding missing import

* Convert with parallel preprocessing of files

* Added coverage var for trainer

Added a var with comment. Feel free to add it as argument

* corrections

* Modifying preview and normalization of image + correction

* Cleanup 
lib/training_data.py