              return image
  
          if detector == "mtcnn":
              self.scale_mtcnn()
          else:
              self.scale_dlib()
  
          if self.input_scale == 1.0:
              return image
  
 
</s> remove         if rotation != 0:
            if not reverse:
                self.rotation_height, self.rotation_width = image.shape[:2]
                image = Utils.rotate_image_by_angle(image, rotation)
            else:
                image = Utils.rotate_image_by_angle(
                    image,
                    rotation * -1,
                    rotated_width=self.rotation_width,
                    rotated_height=self.rotation_height)
 </s> add         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) </s> remove         if detector == "mtcnn":
 </s> add         if self.detector_name == "mtcnn": </s> remove         if detector == "mtcnn":
 </s> add         if self.detector_name == "mtcnn": </s> remove             job = Check(self.alignments, self.args)
        elif self.args.job == "remove":
            job = RemoveAlignments(self.alignments, self.args)
        elif self.args.job == "reformat":
            job = Reformat(self.alignments, self.args)

        job.process()


class AlignmentData():
    """ Class to hold the alignment data """

    def __init__(self, alignments_file, destination_format, verbose):
        print("\n[ALIGNMENT DATA]")  # Tidy up cli output
        self.file = alignments_file
        self.verbose = verbose

        self.check_file_exists()
        self.src_format = self.get_source_format()
        self.dst_format = self.get_destination_format(destination_format)

        if self.src_format == "dfl":
            self.set_destination_serializer()
            return

        self.serializer = Serializer.get_serializer_from_ext(
            self.src_format)
        self.alignments = self.load()
        self.count = len(self.alignments)
        self.count_per_frame = {key: len(value)
                                for key, value in self.alignments.items()}

        self.set_destination_serializer()
        if self.verbose:
            print("{} items loaded".format(self.count))

    def check_file_exists(self):
        """ Check the alignments file exists"""
        if os.path.split(self.file.lower())[1] == "dfl":
            self.file = "dfl"
        if self.file.lower() == "dfl":
            print("Using extracted pngs for alignments")
            return
        if not os.path.isfile(self.file):
            print("ERROR: alignments file not "
                  "found at: {}".format(self.file))
            exit(0)
        if self.verbose:
            print("Alignments file exists at {}".format(self.file))
        return

    def get_source_format(self):
        """ Get the source alignments format """
        if self.file.lower() == "dfl":
            return "dfl"
        return os.path.splitext(self.file)[1].lower()

    def get_destination_format(self, destination_format):
        """ Standardise the destination format to the correct extension """
        extensions = {".json": "json",
                      ".p": "pickle",
                      ".yml": "yaml",
                      ".yaml": "yaml"}
        dst_fmt = None

        if destination_format is not None:
            dst_fmt = destination_format
        elif self.src_format == "dfl":
            dst_fmt = "json"
        elif self.src_format in extensions.keys():
            dst_fmt = extensions[self.src_format]
 </s> add             job = Check </s> remove             VRAM.set_scale_to(detector)
 </s> add             VRAM.set_scale_to(self.detector_name)
        elif detector == "manual":
            self.input_scale = 1.0
              return image
  
          if detector == "mtcnn":
              self.scale_mtcnn()
        elif detector == "manual":
            self.input_scale = 1.0
          else:
              self.scale_dlib()
  
          if self.input_scale == 1.0:
              return image
  
keep keep keep add keep keep keep keep keep keep
 Alignments Tool - Manual (#503)

* Initial alignment tool implementation

* Add face processing. Fix helptext formatting for cli and gui

* Extract faces from alignments file

* Add draw landmarks

* fix analysis hours past 24 bug

* Remove tools flag. Enlarge GUI tooltips

* Add filename extension check for image folders

* Fix folder nonetype bug and linting

* Bugfix renaming of faces

* Import alignments from DeepFaceLab

* Remove frames requirement for dfl

* Alignments Tool: Add remove frames

* Alignments: Add remove frames (#492)

* Alignments Tool: Add remove frames

* Implement Frame display for manual extract

* Alignments refactor

* Further navigation improvements

* Further navigation improvements

* Alignment Tool: Refactor

* Move rotate_image_by_angle() to utils

* Further refactoring improvements

* Reduce key bindings. Add skip to has faces, Add resize frame binding

* More navigation options. Delete faces added. Save alignments added

* Add: Reload alignments. Add extra api calls. Better redraw handling.

* Manual Alignments - Alpha Build

* Rotate landmarks for rotated images

* Rebase to remove OriginalHiRes changes 
lib/face_alignment/extractor.py