  
          return bins
  
      def group_face_cnn(self, img_list):
          """ Group into bins by dlib CNN face similarity """
          print("Grouping by face-cnn similarity...")
  
          # Groups are of the form: group_num -> reference faces
          reference_groups = dict()
  
 
</s> remove         """ Sort by dlib CNN similarity """
 </s> add         """ Sort by CNN similarity """
        self.launch_aligner() </s> remove         """ Sort by dlib CNN dissimilarity """
 </s> add         """ Sort by CNN dissimilarity """
        self.launch_aligner() </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     @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))
        """ Group into bins by CNN face similarity """
  
          return bins
  
      def group_face_cnn(self, img_list):
        """ Group into bins by CNN face similarity """
          print("Grouping by face-cnn similarity...")
  
          # Groups are of the form: group_num -> reference faces
          reference_groups = dict()
  
keep keep keep keep 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/sort.py