              if not angle:
                  return
              rotation_matrix = self.get_original_rotation_matrix(dimensions,
                                                                  angle)
              face = DetectedFace()
              face.alignment_to_face(None, alignment)
              face = rotate_landmarks(face, rotation_matrix)
              alignment = face.face_to_alignment(alignment)
              del alignment["r"]
  
      @staticmethod
      def get_original_rotation_matrix(dimensions, angle):
          """ Calculate original rotation matrix and invert """
 
</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         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         face.alignment_to_face(image, alignment)
 </s> add         face.from_alignment(alignment, image=image) </s> remove class DetectedFace():
    """ Detected face and landmark information """
    def __init__(self):
        self.image = None
        self.x = None
        self.w = None
        self.y = None
        self.h = None
        self.landmarksXY = None

    def alignment_to_face(self, image, alignment):
        """ Convert a face alignment to detected face object """
        self.image = image
        self.x = alignment["x"]
        self.w = alignment["w"]
        self.y = alignment["y"]
        self.h = alignment["h"]
        self.landmarksXY = alignment["landmarksXY"]

    def face_to_alignment(self, alignment):
        """ Convert a face alignment to detected face object """
        alignment["x"] = self.x
        alignment["w"] = self.w
        alignment["y"] = self.y
        alignment["h"] = self.h
        alignment["landmarksXY"] = self.landmarksXY
        return alignment

    def landmarks_as_xy(self):
        """ Landmarks as XY """
        return self.landmarksXY


 </s> add  </s> remove     def process_single_image(self, filename):
        """ Detect faces in an image. Rotate the image the specified amount
            until at least one face is found, or until image rotations are
            depleted.
            Once at least one face has been detected, pass to
            process_single_face to process the individual faces """
        retval = filename, list()
        try:
            image = Utils.cv2_read_write('read', filename)

            for angle in self.images.rotation_angles:
                currentimage, rotation_matrix = rotate_image_by_angle(image,
                                                                      angle)
                faces = self.faces.get_faces(currentimage, angle)
                process_faces = [[idx, face] for idx, face in faces]
                if not process_faces:
                    continue

                if angle != 0 and self.args.verbose:
                    print("found face(s) by rotating image "
                          "{} degrees".format(angle))
                if angle != 0:
                    process_faces = [[idx,
                                      rotate_landmarks(face, rotation_matrix)]
                                     for idx, face in process_faces]

                if process_faces:
                    break
 </s> add         if self.export_face:
            queue_manager.get_queue("save").put("EOF")
        save_thread.join_threads()
            rotate_landmarks(alignment, rotation_matrix)
              if not angle:
                  return
              rotation_matrix = self.get_original_rotation_matrix(dimensions,
                                                                  angle)
            rotate_landmarks(alignment, rotation_matrix)
            rotate_landmarks(alignment, rotation_matrix)
            rotate_landmarks(alignment, rotation_matrix)
            rotate_landmarks(alignment, rotation_matrix)
              del alignment["r"]
  
      @staticmethod
      def get_original_rotation_matrix(dimensions, angle):
          """ Calculate original rotation matrix and invert """
keep keep keep keep 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 
tools/lib_alignments/media.py