                  rotated_height=self.rotation_height)
          return image
  
  
  class Faces():
      """ Holds the faces """
      def __init__(self, arguments):
          self.args = arguments
          self.extractor = self.load_extractor()
          self.mtcnn_kwargs = self.get_mtcnn_kwargs()
          self.filter = self.load_face_filter()
          self.align_eyes = self.args.align_eyes if hasattr(
              self.args, 'align_eyes') else False
          self.output_dir = get_folder(self.args.output_dir)
  
          self.faces_detected = dict()
          self.num_faces_detected = 0
          self.verify_output = False
  
 
</s> remove         self.faces_detected = dict()
        self.num_faces_detected = 0
        self.verify_output = False
 </s> add         return data </s> remove     def have_face(self, filename):
        """ return path of images that have faces """
        return os.path.basename(filename) in self.faces_detected

    def get_faces(self, image, rotation=0):
        """ Extract the faces from an image """
        faces_count = 0
        faces = detect_faces(image,
                             self.args.detector,
                             self.args.verbose,
                             rotation=rotation,
                             dlib_buffer=self.args.dlib_buffer,
                             mtcnn_kwargs=self.mtcnn_kwargs)

        for face in faces:
            if self.filter and not self.filter.check(face):
                if self.args.verbose:
                    print("Skipping not recognized face!")
                continue
            yield faces_count, face

            self.num_faces_detected += 1
            faces_count += 1

        if faces_count > 1 and self.args.verbose:
            self.verify_output = True

    def get_faces_alignments(self, filename, image):
        """ Retrieve the face alignments from an image """
        faces_count = 0
        faces = self.faces_detected[os.path.basename(filename)]
        for rawface in faces:
            face = DetectedFace(**rawface)
            # Rotate the image if necessary
            # NB: Rotation of landmarks now occurs at extract stage
            # This is here for legacy alignments
            if face.r != 0:
                image, _ = rotate_image_by_angle(image, face.r)
            face.image = image[face.y: face.y + face.h,
                               face.x: face.x + face.w]
            if self.filter and not self.filter.check(face):
                if self.args.verbose:
                    print("Skipping not recognized face!")
                continue
 </s> add class Images():
    """ Holds the full frames/images """
    def __init__(self, arguments):
        self.args = arguments
        self.input_images = self.get_input_images()
        self.images_found = len(self.input_images) </s> remove     def rotate_image(self, image, rotation, reverse=False):
        """ Rotate the image forwards or backwards """
        if rotation == 0:
            return image
        if not reverse:
            self.rotation_height, self.rotation_width = image.shape[:2]
            image, _ = rotate_image_by_angle(image, rotation)
        else:
            image, _ = rotate_image_by_angle(
                image,
                rotation * -1,
                rotated_width=self.rotation_width,
                rotated_height=self.rotation_height)
        return image
 </s> add         try:
            with open(self.location, self.serializer.roptions) as align:
                data = self.serializer.unmarshal(align.read()) </s> remove 
 </s> add         self.output_dir = get_folder(self.args.output_dir)
        print("Output Directory: {}".format(self.args.output_dir)) </s> remove class Convert(object):
 </s> add class Convert():
        if skip_faces:
            # Remove items from algnments that have no faces so they will
            # be re-detected
            del_keys = [key for key, val in data.items() if not val]
            for key in del_keys:
                if key in data:
                    del data[key]
                  rotated_height=self.rotation_height)
          return image
  
  
        if skip_faces:
            # Remove items from algnments that have no faces so they will
            # be re-detected
            del_keys = [key for key, val in data.items() if not val]
            for key in del_keys:
                if key in data:
                    del data[key]
        if skip_faces:
            # Remove items from algnments that have no faces so they will
            # be re-detected
            del_keys = [key for key, val in data.items() if not val]
            for key in del_keys:
                if key in data:
                    del data[key]
        if skip_faces:
            # Remove items from algnments that have no faces so they will
            # be re-detected
            del_keys = [key for key, val in data.items() if not val]
            for key in del_keys:
                if key in data:
                    del data[key]
        if skip_faces:
            # Remove items from algnments that have no faces so they will
            # be re-detected
            del_keys = [key for key, val in data.items() if not val]
            for key in del_keys:
                if key in data:
                    del data[key]
        if skip_faces:
            # Remove items from algnments that have no faces so they will
            # be re-detected
            del_keys = [key for key, val in data.items() if not val]
            for key in del_keys:
                if key in data:
                    del data[key]
        if skip_faces:
            # Remove items from algnments that have no faces so they will
            # be re-detected
            del_keys = [key for key, val in data.items() if not val]
            for key in del_keys:
                if key in data:
                    del data[key]
        if skip_faces:
            # Remove items from algnments that have no faces so they will
            # be re-detected
            del_keys = [key for key, val in data.items() if not val]
            for key in del_keys:
                if key in data:
                    del data[key]
        if skip_faces:
            # Remove items from algnments that have no faces so they will
            # be re-detected
            del_keys = [key for key, val in data.items() if not val]
            for key in del_keys:
                if key in data:
                    del data[key]
        if skip_faces:
            # Remove items from algnments that have no faces so they will
            # be re-detected
            del_keys = [key for key, val in data.items() if not val]
            for key in del_keys:
                if key in data:
                    del data[key]
        if skip_faces:
            # Remove items from algnments that have no faces so they will
            # be re-detected
            del_keys = [key for key, val in data.items() if not val]
            for key in del_keys:
                if key in data:
                    del data[key]
  
          self.faces_detected = dict()
          self.num_faces_detected = 0
          self.verify_output = False
  
keep keep keep keep replace replace replace replace replace replace replace replace replace replace keep keep keep keep keep
 Extraction - Speed improvements (#522) (#523)

* Extraction - Speed improvements (#522)

* Initial Plugin restructure

* Detectors to plugins. Detector speed improvements

* Re-implement dlib aligner, remove models, FAN to TF. Parallel processing

* Update manual, update convert, implement parallel/serial switching

* linting + fix cuda check (setup.py). requirements update keras 2.2.4

* Add extract size option. Fix dlib hog init

* GUI: Increase tooltip width

* Update alignment tool to support new DetectedFace

* Add skip existing faces option

* Fix sort tool to new plugin structure

* remove old align plugin

* fix convert -skip faces bug

* Fix convert skipping no faces frames

* Convert - draw onto transparent layer

* Fix blur threshold bug

* fix skip_faces convert bug

* Fix training 
scripts/fsmedia.py