      # << LEGACY FUNCTIONS >> #
  
      # < Rotation > #
      # The old rotation method would rotate the image to find a face, then
      # store the rotated landmarks along with a rotation value to tell the
      # convert process that it had to rotate the frame to find the landmarks.
      # This is problematic for numerous reasons. The process now rotates the
      # landmarks to correctly correspond with the original frame. The below are
 
</s> remove         datatype:  [required] A python type class. This limits the type of data that can be
                   provided in the .ini file and ensures that the value is returned in the
                   correct type to faceswap. Valid datatypes are: <class 'int'>, <class 'float'>,
                   <class 'str'>, <class 'bool'>.
        default:   [required] The default value for this option.
        info:      [required] A string describing what this option does.
        choices:   [optional] If this option's datatype is of <class 'str'> then valid
                   selections can be defined here. This validates the option and also enables
                   a combobox / radio option in the GUI.
        gui_radio: [optional] If <choices> are defined, this indicates that the GUI should use
                   radio buttons rather than a combobox to display this option.
        min_max:   [partial] For <class 'int'> and <class 'float'> datatypes this is required
                   otherwise it is ignored. Should be a tuple of min and max accepted values.
                   This is used for controlling the GUI slider range. Values are not enforced.
        rounding:  [partial] For <class 'int'> and <class 'float'> datatypes this is
                   required otherwise it is ignored. Used for the GUI slider. For floats, this
                   is the number of decimal places to display. For ints this is the step size.
        fixed:     [optional] [train only]. Training configurations are fixed when the model is
                   created, and then reloaded from the state file. Marking an item as fixed=False
                   indicates that this value can be changed for existing models, and will override
                   the value saved in the state file with the updated value in config. If not
                   provided this will default to True.
 </s> add     datatype:  [required] A python type class. This limits the type of data that can be
                provided in the .ini file and ensures that the value is returned in the
                correct type to faceswap. Valid datatypes are: <class 'int'>, <class 'float'>,
                <class 'str'>, <class 'bool'>.
    default:   [required] The default value for this option.
    info:      [required] A string describing what this option does.
    group:     [optional]. A group for grouping options together in the GUI. If not
                provided this will not group this option with any others.
    choices:   [optional] If this option's datatype is of <class 'str'> then valid
                selections can be defined here. This validates the option and also enables
                a combobox / radio option in the GUI.
    gui_radio: [optional] If <choices> are defined, this indicates that the GUI should use
                radio buttons rather than a combobox to display this option.
    min_max:   [partial] For <class 'int'> and <class 'float'> datatypes this is required
                otherwise it is ignored. Should be a tuple of min and max accepted values.
                This is used for controlling the GUI slider range. Values are not enforced.
    rounding:  [partial] For <class 'int'> and <class 'float'> datatypes this is
                required otherwise it is ignored. Used for the GUI slider. For floats, this
                is the number of decimal places to display. For ints this is the step size.
    fixed:     [optional] [train only]. Training configurations are fixed when the model is
                created, and then reloaded from the state file. Marking an item as fixed=False
                indicates that this value can be changed for existing models, and will override
                the value saved in the state file with the updated value in config. If not
                provided this will default to True. </s> remove     """ Detected face and landmark information """
    def __init__(  # pylint: disable=invalid-name
            self, image=None, x=None, w=None, y=None, h=None,
            landmarksXY=None):
        logger.trace("Initializing %s", self.__class__.__name__)
 </s> add     """ Detected face and landmark information

    Holds information about a detected face, it's location in a source image
    and the face's 68 point landmarks.

    Methods for aligning a face are also callable from here.

    Parameters
    ----------
    image: np.ndarray, optional
        This is a generic image placeholder that should not be relied on to be holding a particular
        image. It may hold the source frame that holds the face, a cropped face or a scaled image
        depending on the method using this object.
    x: int
        The left most point (in pixels) of the face's bounding box as discovered in
        :mod:`plugins.extract.detect`
    w: int
        The width (in pixels) of the face's bounding box as discovered in
        :mod:`plugins.extract.detect`
    y: int
        The top most point (in pixels) of the face's bounding box as discovered in
        :mod:`plugins.extract.detect`
    h: int
        The height (in pixels) of the face's bounding box as discovered in
        :mod:`plugins.extract.detect`
    landmarks_xy: list
        The 68 point landmarks as discovered in :mod:`plugins.extract.align`. Should be a ``list``
        of 68 `(x, y)` ``tuples`` with each of the landmark co-ordinates.
    """
    def __init__(self, image=None, x=None, w=None, y=None, h=None, landmarks_xy=None):
        logger.trace("Initializing %s: (image: %s, x: %s, w: %s, y: %s, h:%s, landmarks_xy: %s)",
                     self.__class__.__name__,
                     image.shape if image is not None and image.any() else image,
                     x, w, y, h, landmarks_xy) </s> remove     def rotate_image(self, image, angle):
        """ Rotate the image by given angle and return
            Image with rotation matrix """
 </s> add     def _rotate_batch(self, batch, angle):
        """ Rotate images in a batch by given angle
            if any faces have already been detected for a batch, store the existing rotation
            matrix and replace the feed image with a placeholder """
    def update_legacy(self):
        """ Update legacy alignments """
        if self.has_legacy_landmarksxy():
            logger.info("Updating legacy alignments")
            self.update_legacy_landmarksxy()
      # << LEGACY FUNCTIONS >> #
  
    def update_legacy(self):
        """ Update legacy alignments """
        if self.has_legacy_landmarksxy():
            logger.info("Updating legacy alignments")
            self.update_legacy_landmarksxy()
      # < Rotation > #
      # The old rotation method would rotate the image to find a face, then
      # store the rotated landmarks along with a rotation value to tell the
      # convert process that it had to rotate the frame to find the landmarks.
      # This is problematic for numerous reasons. The process now rotates the
      # landmarks to correctly correspond with the original frame. The below are
keep add keep keep keep keep keep keep
 De-Multiprocess Extract (#871)

* requirements.txt: - Pin opencv to 4.1.1 (fixes cv2-dnn error)

* lib.face_detect.DetectedFace: change LandmarksXY to landmarks_xy. Add left, right, top, bottom attributes

* lib.model.session: Session manager for loading models into different graphs (for Nvidia + CPU)

* plugins.extract._base: New parent class for all extract plugins

* plugins.extract.pipeline. Remove MultiProcessing. Dynamically limit batchsize for Nvidia cards. Remove loglevel input

* S3FD + FAN plugins. Standardise to Keras version for all backends

* Standardize all extract plugins to new threaded codebase

* Documentation. Start implementing Numpy style docstrings for Sphinx Documentation

* Remove s3fd_amd. Change convert OTF to expect DetectedFace object

* faces_detect - clean up and documentation

* Remove PoolProcess

* Migrate manual tool to new extract workflow

* Remove AMD specific extractor code from cli and plugins

* Sort tool to new extract workflow

* Remove multiprocessing from project

* Remove multiprocessing queues from QueueManager

* Remove multiprocessing support from logger

* Move face_filter to new extraction pipeline

* Alignments landmarksXY > landmarks_xy and legacy handling

* Intercept get_backend for sphinx doc build

# Add Sphinx documentation 
lib/alignments.py