diff --git a/bob/bio/vein/configurations/maximum_curvature.py b/bob/bio/vein/configurations/maximum_curvature.py
index ba69e197996bc9a0424d72878531c7f0ca412db0..46c86ea792b568c4145d10de7cbe6852e1a96c27 100644
--- a/bob/bio/vein/configurations/maximum_curvature.py
+++ b/bob/bio/vein/configurations/maximum_curvature.py
@@ -20,8 +20,8 @@ or the attribute ``sub_directory`` in a configuration file loaded **after**
 this resource.
 """
 
-from ..preprocessor import Padder, TomesLeeMask, HuangNormalization, NoFilter
-from ..preprocessor import Preprocessor
+from ..preprocessor import NoCropper, Padder, TomesLeeMask, \
+    HuangNormalization, NoFilter, Preprocessor
 
 # Filter sizes for the vertical "high-pass" filter
 FILTER_HEIGHT = 4
@@ -32,6 +32,7 @@ PAD_WIDTH = 5
 PAD_CONST = 51
 
 preprocessor = Preprocessor(
+    crop=NoCropper(),
     mask=TomesLeeMask(filter_height=FILTER_HEIGHT, filter_width=FILTER_WIDTH),
     normalize=HuangNormalization(padding_width=PAD_WIDTH,
       padding_constant=PAD_CONST),
diff --git a/bob/bio/vein/configurations/repeated_line_tracking.py b/bob/bio/vein/configurations/repeated_line_tracking.py
index 2050174a072c6250d38b0769a7ec429da2ee4fc9..accd87142e541857fce28986a01a43fa9cfeebc2 100644
--- a/bob/bio/vein/configurations/repeated_line_tracking.py
+++ b/bob/bio/vein/configurations/repeated_line_tracking.py
@@ -20,8 +20,8 @@ or the attribute ``sub_directory`` in a configuration file loaded **after**
 this resource.
 """
 
-from ..preprocessor import Padder, TomesLeeMask, HuangNormalization, NoFilter
-from ..preprocessor import Preprocessor
+from ..preprocessor import NoCropper, Padder, TomesLeeMask, \
+    HuangNormalization, NoFilter, Preprocessor
 
 # Filter sizes for the vertical "high-pass" filter
 FILTER_HEIGHT = 4
@@ -32,6 +32,7 @@ PAD_WIDTH = 5
 PAD_CONST = 51
 
 preprocessor = Preprocessor(
+    crop=NoCropper(),
     mask=TomesLeeMask(filter_height=FILTER_HEIGHT, filter_width=FILTER_WIDTH),
     normalize=HuangNormalization(padding_width=PAD_WIDTH,
       padding_constant=PAD_CONST),
diff --git a/bob/bio/vein/configurations/wide_line_detector.py b/bob/bio/vein/configurations/wide_line_detector.py
index aef74c0e2f8f4cb5b6739ef53ecdd17b5762e185..b82cf420f1a819d8bbd2ffc31f2e314244ae42dc 100644
--- a/bob/bio/vein/configurations/wide_line_detector.py
+++ b/bob/bio/vein/configurations/wide_line_detector.py
@@ -20,8 +20,8 @@ or the attribute ``sub_directory`` in a configuration file loaded **after**
 this resource.
 """
 
-from ..preprocessor import Padder, TomesLeeMask, HuangNormalization, NoFilter
-from ..preprocessor import Preprocessor
+from ..preprocessor import NoCropper, Padder, TomesLeeMask, \
+    HuangNormalization, NoFilter, Preprocessor
 
 # Filter sizes for the vertical "high-pass" filter
 FILTER_HEIGHT = 4
@@ -32,6 +32,7 @@ PAD_WIDTH = 5
 PAD_CONST = 51
 
 preprocessor = Preprocessor(
+    crop=NoCropper(),
     mask=TomesLeeMask(filter_height=FILTER_HEIGHT, filter_width=FILTER_WIDTH),
     normalize=HuangNormalization(padding_width=PAD_WIDTH,
       padding_constant=PAD_CONST),
diff --git a/bob/bio/vein/preprocessor/__init__.py b/bob/bio/vein/preprocessor/__init__.py
index 7d24970ca55a638d4f29a83364c96f9e873e98bf..d9cb613ded7d164d1aa6978f4557eaf35b027135 100644
--- a/bob/bio/vein/preprocessor/__init__.py
+++ b/bob/bio/vein/preprocessor/__init__.py
@@ -1,4 +1,5 @@
-from .mask import Padder, Masker, NoMask, AnnotatedRoIMask
+from .cropper import Cropper, FixedCropper, NoCropper
+from .mask import Padder, Masker, FixedMask, AnnotatedRoIMask
 from .mask import KonoMask, LeeMask, TomesLeeMask
 from .normalize import Normalizer, NoNormalization, HuangNormalization
 from .filters import Filter, NoFilter, HistogramEqualization
@@ -19,9 +20,12 @@ def __appropriate__(*args):
   for obj in args: obj.__module__ = __name__
 
 __appropriate__(
+    Cropper,
+    FixedCropper,
+    NoCropper,
     Padder,
     Masker,
-    NoMask,
+    FixedMask,
     AnnotatedRoIMask,
     KonoMask,
     LeeMask,
diff --git a/bob/bio/vein/preprocessor/cropper.py b/bob/bio/vein/preprocessor/cropper.py
new file mode 100644
index 0000000000000000000000000000000000000000..1dc545471e3f4005da55a6a16d2bde5aed86b45e
--- /dev/null
+++ b/bob/bio/vein/preprocessor/cropper.py
@@ -0,0 +1,107 @@
+#!/usr/bin/env python
+# vim: set fileencoding=utf-8 :
+
+
+'''Base utilities for pre-cropping images'''
+
+import numpy
+
+
+class Cropper(object):
+    """This is the base class for all croppers
+
+    It defines the minimum requirements for all derived cropper classes.
+
+
+    """
+
+    def __init__(self):
+      pass
+
+
+    def __call__(self, image):
+      """Overwrite this method to implement your masking method
+
+
+      Parameters:
+
+        image (numpy.ndarray): A 2D numpy array of type ``uint8`` with the
+          input image
+
+
+      Returns:
+
+        numpy.ndarray: A 2D numpy array of the same type as the input, with
+        cropped rows and columns as per request
+
+      """
+
+      raise NotImplemented('You must implement the __call__ slot')
+
+
+class FixedCropper(object):
+  """Implements cropping using a fixed suppression of border pixels
+
+  The defaults supress no lines from the image and returns an image like the
+  original.
+
+
+  .. note::
+
+     Before choosing values, note you're responsible for knowing what is the
+     orientation of images fed into this cropper.
+
+
+  Parameters:
+
+    top (:py:class:`int`, optional): Number of lines to suppress from the top
+      of the image. The top of the image corresponds to ``y = 0``.
+
+    bottom (:py:class:`int`, optional): Number of lines to suppress from the
+      bottom of the image. The bottom of the image corresponds to ``y =
+      height``.
+
+    left (:py:class:`int`, optional): Number of lines to suppress from the left
+      of the image. The left of the image corresponds to ``x = 0``.
+
+    right (:py:class:`int`, optional): Number of lines to suppress from the
+      right of the image. The right of the image corresponds to ``x = width``.
+
+  """
+
+  def __init__(self, top=0, bottom=0, left=0, right=0):
+    self.top = top
+    self.bottom = bottom
+    self.left = left
+    self.right = right
+
+
+  def __call__(self, image):
+    """Returns a big mask
+
+
+    Parameters:
+
+      image (numpy.ndarray): A 2D numpy array of type ``uint8`` with the
+        input image
+
+
+    Returns:
+
+      numpy.ndarray: A 2D numpy array of type boolean with the caculated
+      mask. ``True`` values correspond to regions where the finger is
+      situated
+
+
+    """
+
+    # this should work even if limits are zeros
+    h, w = image.shape
+    return image[self.top:h-self.bottom, self.left:w-self.right]
+
+
+class NoCropper(FixedCropper):
+  """Convenience: same as FixedCropper()"""
+
+  def __init__(self):
+    super(NoCropper, self).__init__(0, 0, 0, 0)
diff --git a/bob/bio/vein/preprocessor/mask.py b/bob/bio/vein/preprocessor/mask.py
index aa09d17f14edd183a56caccc4ef20131f2810750..b558ae69c22f296e8d9f5a7132b74e732744a47b 100644
--- a/bob/bio/vein/preprocessor/mask.py
+++ b/bob/bio/vein/preprocessor/mask.py
@@ -89,12 +89,41 @@ class Masker(object):
       raise NotImplemented('You must implement the __call__ slot')
 
 
-class NoMask(object):
-  """Implements no masking - i.e. returns a mask the same size as input
+class FixedMask(object):
+  """Implements masking using a fixed suppression of border pixels
+
+  The defaults mask no lines from the image and returns a mask of the same size
+  of the original image where all values are ``True``.
+
+
+  .. note::
+
+     Before choosing values, note you're responsible for knowing what is the
+     orientation of images fed into this masker.
+
+
+  Parameters:
+
+    top (:py:class:`int`, optional): Number of lines to suppress from the top
+      of the image. The top of the image corresponds to ``y = 0``.
+
+    bottom (:py:class:`int`, optional): Number of lines to suppress from the
+      bottom of the image. The bottom of the image corresponds to ``y =
+      height``.
+
+    left (:py:class:`int`, optional): Number of lines to suppress from the left
+      of the image. The left of the image corresponds to ``x = 0``.
+
+    right (:py:class:`int`, optional): Number of lines to suppress from the
+      right of the image. The right of the image corresponds to ``x = width``.
+
   """
 
-  def __init__(self):
-    pass
+  def __init__(self, top=0, bottom=0, left=0, right=0):
+    self.top = top
+    self.bottom = bottom
+    self.left = left
+    self.right = right
 
 
   def __call__(self, image):
@@ -115,7 +144,15 @@ class NoMask(object):
 
 
     """
-    return numpy.ones(image.shape, dtype='bool')
+    retval = numpy.ones(image.shape, dtype='bool')
+
+    # this should work even if limits are zeros
+    retval[:self.top] = False
+    retval[-self.bottom:] = False
+    retval[:,:self.left] = False
+    retval[:,-self.right:] = False
+
+    return retval
 
 
 class AnnotatedRoIMask(object):
@@ -428,3 +465,6 @@ class TomesLeeMask(Masker):
     else:
       w = self.padder.padding_width
       return finger_mask[w:-w,w:-w]
+
+
+
diff --git a/bob/bio/vein/preprocessor/preprocessor.py b/bob/bio/vein/preprocessor/preprocessor.py
index f925ef051efcbd5baf9fb83387c81a361b2ec266..549877fbf5860dcc77aa74b420d57d6b083e1119 100644
--- a/bob/bio/vein/preprocessor/preprocessor.py
+++ b/bob/bio/vein/preprocessor/preprocessor.py
@@ -11,7 +11,8 @@ class Preprocessor (BasePreprocessor):
 
   In this implementation, the finger image is (in this order):
 
-    #. The mask is expolated from the image using one of our
+    #. The image is pre-cropped to remove obvious non-finger image parts
+    #. The mask is extrapolated from the image using one of our
        :py:class:`Masker`'s concrete implementations
     #. The image is normalized with one of our :py:class:`Normalizer`'s
     #. The image is filtered with one of our :py:class:`Filter`'s
@@ -19,6 +20,11 @@ class Preprocessor (BasePreprocessor):
 
   Parameters:
 
+    crop (:py:class:`Cropper`): An object that will perform pre-cropping on
+      the input image before a mask can be estimated. It removes parts of the
+      image which are surely not part of the finger region you'll want to
+      consider for the next steps.
+
     mask (:py:class:`Masker`): An object representing a Masker instance which
       will extrapolate the mask from the input image.
 
@@ -34,15 +40,17 @@ class Preprocessor (BasePreprocessor):
   """
 
 
-  def __init__(self, mask, normalize, filter, **kwargs):
+  def __init__(self, crop, mask, normalize, filter, **kwargs):
 
     BasePreprocessor.__init__(self,
+        crop = crop,
         mask = mask,
         normalize = normalize,
         filter = filter,
         **kwargs
         )
 
+    self.crop = crop
     self.mask = mask
     self.normalize = normalize
     self.filter = filter
@@ -66,7 +74,8 @@ class Preprocessor (BasePreprocessor):
 
     """
 
-    mask = self.mask(data)
+    cropped = self.crop(data)
+    mask = self.mask(cropped)
     data, mask = self.normalize(data, mask)
     data = self.filter(data, mask)
     return data, mask
diff --git a/bob/bio/vein/tests/test.py b/bob/bio/vein/tests/test.py
index b9e1752b80291af52884755b470909957d594138..908d3fb8d01a1f95a1eece3d8fa2f773c5bd00f6 100644
--- a/bob/bio/vein/tests/test.py
+++ b/bob/bio/vein/tests/test.py
@@ -42,10 +42,11 @@ def test_finger_crop():
 
   img = bob.io.base.load(input_filename)
 
-  from bob.bio.vein.preprocessor import Preprocessor, LeeMask, \
+  from bob.bio.vein.preprocessor import Preprocessor, NoCropper, LeeMask, \
       HuangNormalization, NoFilter
 
   processor = Preprocessor(
+      NoCropper(),
       LeeMask(filter_height=40, filter_width=4),
       HuangNormalization(padding_width=0, padding_constant=0),
       NoFilter(),
@@ -112,9 +113,10 @@ def test_max_curvature_HE():
   input_img = bob.io.base.load(input_img_filename)
 
   # Preprocess the data and apply Histogram Equalization postprocessing (same parameters as in maximum_curvature.py configuration file + postprocessing)
-  from bob.bio.vein.preprocessor import Preprocessor, LeeMask, \
+  from bob.bio.vein.preprocessor import Preprocessor, NoCropper, LeeMask, \
       HuangNormalization, HistogramEqualization
   processor = Preprocessor(
+      NoCropper(),
       LeeMask(filter_height=40, filter_width=4),
       HuangNormalization(padding_width=0, padding_constant=0),
       HistogramEqualization(),
@@ -161,9 +163,10 @@ def test_repeated_line_tracking_HE():
   input_img = bob.io.base.load(input_img_filename)
 
   # Preprocess the data and apply Histogram Equalization postprocessing (same parameters as in repeated_line_tracking.py configuration file + postprocessing)
-  from bob.bio.vein.preprocessor import Preprocessor, LeeMask, \
+  from bob.bio.vein.preprocessor import Preprocessor, NoCropper, LeeMask, \
       HuangNormalization, HistogramEqualization
   processor = Preprocessor(
+      NoCropper(),
       LeeMask(filter_height=40, filter_width=4),
       HuangNormalization(padding_width=0, padding_constant=0),
       HistogramEqualization(),
@@ -214,9 +217,10 @@ def test_wide_line_detector_HE():
   input_img = bob.io.base.load(input_img_filename)
 
   # Preprocess the data and apply Histogram Equalization postprocessing (same parameters as in wide_line_detector.py configuration file + postprocessing)
-  from bob.bio.vein.preprocessor import Preprocessor, LeeMask, \
+  from bob.bio.vein.preprocessor import Preprocessor, NoCropper, LeeMask, \
       HuangNormalization, HistogramEqualization
   processor = Preprocessor(
+      NoCropper(),
       LeeMask(filter_height=40, filter_width=4),
       HuangNormalization(padding_width=0, padding_constant=0),
       HistogramEqualization(),