      def write_alignments(self):
          """ Save the alignments file """
          self.alignments.write_alignments(self.faces.faces_detected)
  
      def extract_single_process(self):
          """ Run extraction in a single process """
          frame_no = 0
          for filename in tqdm(self.images.input_images, file=sys.stdout):
              filename, faces = self.process_single_image(filename)
              self.faces.faces_detected[os.path.basename(filename)] = faces
              frame_no += 1
              if frame_no == self.save_interval:
                  self.write_alignments()
                  frame_no = 0
  
      def extract_multi_process(self):
          """ Run the extraction on the correct number of processes """
          frame_no = 0
          for filename, faces in tqdm(
 
</s> remove     def extract_multi_process(self):
        """ Run the extraction on the correct number of processes """
 </s> add         save_queue = queue_manager.get_queue("save")
        while True:
            item = save_queue.get()
            if item == "EOF":
                break
            filename, output_file, resized_face, idx = item
            out_filename = "{}_{}{}".format(str(output_file),
                                            str(idx),
                                            Path(filename).suffix)
            cv2.imwrite(out_filename, resized_face)

    def run_extraction(self, save_thread):
        """ Run Face Detection """
        to_process = self.process_item_count() </s> remove         for filename, faces in tqdm(
                pool_process(
                    self.process_single_image,
                    self.images.input_images),
                total=self.images.images_found,
                file=sys.stdout):
            self.faces.num_faces_detected += 1
            self.faces.faces_detected[os.path.basename(filename)] = faces
 </s> add         if self.plugins.is_parallel:
            self.plugins.launch_aligner()
            self.plugins.launch_detector()

        if not self.plugins.is_parallel:
            self.run_detection(to_process)
            self.plugins.launch_aligner()

        for faces in tqdm(self.plugins.detect_faces(extract_pass="align"),
                          total=to_process,
                          file=sys.stdout,
                          desc="Extracting faces"):

            exception = faces.get("exception", False)
            if exception:
                break
            filename = faces["filename"]

            faces["output_file"] = self.output_dir / Path(filename).stem

            self.post_process.do_actions(faces)

            faces_count = len(faces["detected_faces"])
            if self.args.verbose and faces_count == 0:
                print("Warning: No faces were detected in image: "
                      "{}".format(os.path.basename(filename)))

            if not self.verify_output and faces_count > 1:
                self.verify_output = True

            self.process_faces(filename, faces)
 </s> remove     def write_alignments(self):
        """ Save the alignments file """
        self.alignments.write_alignments(self.faces.faces_detected)
 </s> add     def reload_images(self, detected_faces):
        """ Reload the images and pair to detected face """
        load_queue = queue_manager.get_queue("detect")
        for filename, image in self.images.load():
            detect_item = detected_faces.pop(filename, None)
            if not detect_item:
                continue
            detect_item["image"] = image
            load_queue.put(detect_item)
        load_queue.put("EOF") </s> remove                 self.write_alignments()
 </s> add                 self.alignments.save() </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()
    def save_faces(self):
        """ Save the generated faces """
        if not self.export_face:
            return
      def write_alignments(self):
          """ Save the alignments file """
          self.alignments.write_alignments(self.faces.faces_detected)
  
    def save_faces(self):
        """ Save the generated faces """
        if not self.export_face:
            return
    def save_faces(self):
        """ Save the generated faces """
        if not self.export_face:
            return
    def save_faces(self):
        """ Save the generated faces """
        if not self.export_face:
            return
    def save_faces(self):
        """ Save the generated faces """
        if not self.export_face:
            return
    def save_faces(self):
        """ Save the generated faces """
        if not self.export_face:
            return
    def save_faces(self):
        """ Save the generated faces """
        if not self.export_face:
            return
    def save_faces(self):
        """ Save the generated faces """
        if not self.export_face:
            return
    def save_faces(self):
        """ Save the generated faces """
        if not self.export_face:
            return
    def save_faces(self):
        """ Save the generated faces """
        if not self.export_face:
            return
    def save_faces(self):
        """ Save the generated faces """
        if not self.export_face:
            return
  
      def extract_multi_process(self):
          """ Run the extraction on the correct number of processes """
          frame_no = 0
          for filename, faces in tqdm(
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/extract.py