          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
  
      @staticmethod
      def load_extractor(extractor_name="Align"):
          """ Load the requested extractor for extraction """
          extractor = PluginLoader.get_extractor(extractor_name)()
 
</s> remove     @staticmethod
    def load_extractor(extractor_name="Align"):
        """ Load the requested extractor for extraction """
        extractor = PluginLoader.get_extractor(extractor_name)()
 </s> add     def save(self):
        """ Write the serialized alignments file """
        try:
            print("Writing alignments to: {}".format(self.location))
            with open(self.location, self.serializer.woptions) as align:
                align.write(self.serializer.marshal(self.data))
        except Exception as err:
            print("{} not written!".format(self.location))
            print(str(err)) </s> remove 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)
 </s> add         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] </s> remove         return extractor
 </s> add     def frame_exists(self, frame):
        """ return path of images that have faces """
        return frame in self.data.keys()

    def get_alignments_for_frame(self, frame):
        """ Return the alignments for the selected frame """
        return self.data.get(frame, list())

    def get_legacy_frames(self):
        """ Return a list of frames with legacy rotations """
        keys = list()
        for key, val in self.data.items():
            if any(alignment.get("r", None) for alignment in val):
                keys.append(key)
        return keys

    def rotate_existing_landmarks(self, frame, dimensions):
        """ Backwards compatability fix. Rotates the landmarks to
            their correct position and deletes r """
        for face in self.get_alignments_for_frame(frame):
            angle = face.get("r", 0)
            if not angle:
                return
            rotation_matrix = self.get_original_rotation_matrix(dimensions,
                                                                angle)
            rotate_landmarks(face, rotation_matrix)
            del face["r"] </s> remove     def get_mtcnn_kwargs(self):
        """ Add the mtcnn arguments into a kwargs dictionary """
        mtcnn_threshold = [float(thr.strip())
                           for thr in self.args.mtcnn_threshold]
        return {"minsize": self.args.mtcnn_minsize,
                "threshold": mtcnn_threshold,
                "factor": self.args.mtcnn_scalefactor}
 </s> add     @staticmethod
    def get_original_rotation_matrix(dimensions, angle):
        """ Calculate original rotation matrix and invert """
        height, width = dimensions
        center = (width/2, height/2)
        rotation_matrix = cv2.getRotationMatrix2D(center, -1.0*angle, 1.) </s> remove         self.faces = Faces(self.args)
        self.alignments = Alignments(self.args)
 </s> add         self.alignments = Alignments(self.args, False)

        # Legacy rotation conversion
        Rotate(self.alignments, self.args.verbose, self.images.input_images)

        self.post_process = PostProcess(arguments)
        self.verify_output = False
        return data
          self.align_eyes = self.args.align_eyes if hasattr(
              self.args, 'align_eyes') else False
          self.output_dir = get_folder(self.args.output_dir)
  
        return data
        return data
        return data
  
      @staticmethod
      def load_extractor(extractor_name="Align"):
          """ Load the requested extractor for extraction """
          extractor = PluginLoader.get_extractor(extractor_name)()
keep keep keep keep 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