diff --git a/bob/bio/face/preprocessor/Base.py b/bob/bio/face/preprocessor/Base.py
index 0e296e423f547daf987377aa1e3168fe2396a36d..3170b408733f8e92081782fd5487b5f7c40ac826 100644
--- a/bob/bio/face/preprocessor/Base.py
+++ b/bob/bio/face/preprocessor/Base.py
@@ -1,27 +1,59 @@
-import numpy
 import bob.io.image
 import bob.ip.color
+import numpy
+from sklearn.base import BaseEstimator
+from sklearn.base import TransformerMixin
+
+
+def change_color_channel(image, color_channel):
+    if image.ndim == 2:
+        if color_channel == "rgb":
+            return bob.ip.color.gray_to_rgb(image)
+        if color_channel != "gray":
+            raise ValueError(
+                "There is no rule to extract a "
+                + color_channel
+                + " image from a gray level image!"
+            )
+        return image
 
-from sklearn.base import TransformerMixin, BaseEstimator
+    if color_channel == "rgb":
+        return image
+    if color_channel == "gray":
+        return bob.ip.color.rgb_to_gray(image)
+    if color_channel == "red":
+        return image[0, :, :]
+    if color_channel == "green":
+        return image[1, :, :]
+    if color_channel == "blue":
+        return image[2, :, :]
+
+    raise ValueError(
+        "The image channel '%s' is not known or not yet implemented", color_channel
+    )
 
 
 class Base(TransformerMixin, BaseEstimator):
     """Performs color space adaptations and data type corrections for the given
-  image.
+    image.
 
-  **Parameters:**
+    **Parameters:**
 
-  dtype : :py:class:`numpy.dtype` or convertible or ``None``
-    The data type that the resulting image will have.
+    dtype : :py:class:`numpy.dtype` or convertible or ``None``
+      The data type that the resulting image will have.
 
-  color_channel : one of ``('gray', 'red', 'gren', 'blue', 'rgb')``
-    The specific color channel, which should be extracted from the image.
-  """
+    color_channel : one of ``('gray', 'red', 'gren', 'blue', 'rgb')``
+      The specific color channel, which should be extracted from the image.
+    """
 
     def __init__(self, dtype=None, color_channel="gray", **kwargs):
-        self.channel = color_channel
+        self.color_channel = color_channel
         self.dtype = dtype
 
+    @property
+    def channel(self):
+        return self.color_channel
+
     def _more_tags(self):
         return {"stateless": True, "requires_fit": False}
 
@@ -31,85 +63,62 @@ class Base(TransformerMixin, BaseEstimator):
     def color_channel(self, image):
         """color_channel(image) -> channel
 
-    Returns the channel of the given image, which was selected in the
-    constructor. Currently, gray, red, green and blue channels are supported.
+        Returns the channel of the given image, which was selected in the
+        constructor. Currently, gray, red, green and blue channels are supported.
 
-    **Parameters:**
+        **Parameters:**
 
-    image : 2D or 3D :py:class:`numpy.ndarray`
-      The image to get the specified channel from.
+        image : 2D or 3D :py:class:`numpy.ndarray`
+          The image to get the specified channel from.
 
-    **Returns:**
+        **Returns:**
 
-    channel : 2D or 3D :py:class:`numpy.ndarray`
-      The extracted color channel.
-    """
+        channel : 2D or 3D :py:class:`numpy.ndarray`
+          The extracted color channel.
+        """
 
-        if image.ndim == 2:
-            if self.channel == "rgb":
-                return bob.ip.color.gray_to_rgb(image)
-            if self.channel != "gray":
-                raise ValueError(
-                    "There is no rule to extract a "
-                    + self.channel
-                    + " image from a gray level image!"
-                )
-            return image
-
-        if self.channel == "rgb":
-            return image
-        if self.channel == "gray":
-            return bob.ip.color.rgb_to_gray(image)
-        if self.channel == "red":
-            return image[0, :, :]
-        if self.channel == "green":
-            return image[1, :, :]
-        if self.channel == "blue":
-            return image[2, :, :]
-
-        raise ValueError(
-            "The image channel '%s' is not known or not yet implemented", self.channel
-        )
+        return change_color_channel(image, self.color_channel)
 
     def data_type(self, image):
         """data_type(image) -> image
 
-    Converts the given image into the data type specified in the constructor of
-    this class. If no data type was specified, or the ``image`` is ``None``, no
-    conversion is performed.
+        Converts the given image into the data type specified in the constructor of
+        this class. If no data type was specified, or the ``image`` is ``None``, no
+        conversion is performed.
 
-    **Parameters:**
+        **Parameters:**
 
-    image : 2D or 3D :py:class:`numpy.ndarray`
-      The image to convert.
+        image : 2D or 3D :py:class:`numpy.ndarray`
+          The image to convert.
 
-    **Returns:**
+        **Returns:**
 
-    image : 2D or 3D :py:class:`numpy.ndarray`
-      The image converted to the desired data type, if any.
-    """
+        image : 2D or 3D :py:class:`numpy.ndarray`
+          The image converted to the desired data type, if any.
+        """
         if self.dtype is not None and image is not None:
             image = image.astype(self.dtype)
         return image
 
-    def transform(self, image, annotations=None):
-        """__call__(image, annotations = None) -> image
+    def transform(self, images, annotations=None):
+        """Extracts the desired color channel and converts to the desired data type.
 
-    Extracts the desired color channel and converts to the desired data type.
+        **Parameters:**
 
-    **Parameters:**
+        image : 2D or 3D :py:class:`numpy.ndarray`
+          The image to preprocess.
 
-    image : 2D or 3D :py:class:`numpy.ndarray`
-      The image to preprocess.
+        annotations : any
+          Ignored.
 
-    annotations : any
-      Ignored.
+        **Returns:**
 
-    **Returns:**
+        image : 2D :py:class:`numpy.ndarray`
+          The image converted converted to the desired color channel and type.
+        """
+        return [self._transform_one_image(img) for img in images]
 
-    image : 2D :py:class:`numpy.ndarray`
-      The image converted converted to the desired color channel and type.
-    """
+    def _transform_one_image(self, image):
         assert isinstance(image, numpy.ndarray) and image.ndim in (2, 3)
         # convert to grayscale
         image = self.color_channel(image)
diff --git a/bob/bio/face/preprocessor/utils.py b/bob/bio/face/preprocessor/utils.py
index ffd5602632cb909a465d2238a3f58e0b74325e0c..d59c9bd85e8b1c961df11e65909f5515f5ed48c0 100644
--- a/bob/bio/face/preprocessor/utils.py
+++ b/bob/bio/face/preprocessor/utils.py
@@ -1,5 +1,4 @@
 import bob.bio.base
-import six
 
 
 def load_cropper(face_cropper):
@@ -7,25 +6,9 @@ def load_cropper(face_cropper):
 
     if face_cropper is None:
         cropper = None
-    elif isinstance(face_cropper, six.string_types):
+    elif isinstance(face_cropper, str):
         cropper = bob.bio.base.load_resource(face_cropper, "preprocessor")
     else:
         cropper = face_cropper
 
     return cropper
-
-
-def load_cropper_only(face_cropper):
-    from .FaceCrop import FaceCrop
-
-    if face_cropper is None:
-        cropper = None
-    elif isinstance(face_cropper, six.string_types):
-        cropper = bob.bio.base.load_resource(face_cropper, "preprocessor")
-    elif isinstance(face_cropper, FaceCrop):
-        cropper = face_cropper
-    else:
-        raise ValueError("The given face cropper type is not understood")
-
-    assert cropper is None or isinstance(cropper, FaceCrop)
-    return cropper