diff --git a/bob/bio/vein/preprocessor/utils/__init__.py b/bob/bio/vein/preprocessor/utils/__init__.py
index 516dc5e01c69f2675d3d388ce290a02b2ddc79de..9992cb1d2637003c25066c4930c6b9962eac2333 100644
--- a/bob/bio/vein/preprocessor/utils/__init__.py
+++ b/bob/bio/vein/preprocessor/utils/__init__.py
@@ -1,6 +1,6 @@
 from .utils import ManualRoiCut
 from .utils import ConstructVeinImage
-from .utils import RotateImage
+from .utils import NormalizeImageRotation
 
 # gets sphinx autodoc done right - don't remove it
 __all__ = [_ for _ in dir() if not _.startswith('_')]
diff --git a/bob/bio/vein/preprocessor/utils/utils.py b/bob/bio/vein/preprocessor/utils/utils.py
index b323781a46e19bec11b08d0ad5947973761d92fa..a1f99d0b773f94218bdb8a95bd060c1acad0231c 100644
--- a/bob/bio/vein/preprocessor/utils/utils.py
+++ b/bob/bio/vein/preprocessor/utils/utils.py
@@ -17,102 +17,108 @@ class ManualRoiCut():
   """
   Class for manual roi extraction -- ``ManualRoiCut``.
   
-  Parameters:
+  Args:
+    annotation (``File``, :py:class:`list`): The name of annotation file, with full path containing 
+      ROI annotation data (``Bob`` format, ``(x, y)``) **or** the list of annotation 
+      points (tuples) in ``Bob`` format -- ``(x, y)``. A *fail-safe* operation is implemented
+      ensuring that the annotation points are inside the image to be annotated.
+    image (``File``, :py:class:`numpy.ndarray`), optional: The name of the image to be annotation -  
+      full path or image data as :py:class:`numpy.ndarray`. Image is an optional parameter
+      because it isn't needed to generate ROI binary mask.
+    sizes (``tuple``): optional - a tuple of image size in ``Bob`` format ``(x,y)``.
+      This parameter is used **if** no image is given to generate binary mask.
   
-  annotation (File, list): The name of annotation file, with full path containing 
-  ROI annotation data (``Bob`` format, ``(x, y)``) **or** the list of annotation 
-  points (tuples) in ``Bob`` format -- ``(x, y)``
-    
-  image (File, :py:class:`numpy.ndarray`), optional: The name of the image to be annotation -  
-  full path or image data as :py:class:`numpy.ndarray`. Image is an optional parameter,
-  because it isn't needed to generate ROI binary mask.
-  
-  sizes (tuple): optional - a tuple of image size in ``Bob`` format ``(x,y)``.
-  This parameter is used **if** no image is given to generate binary mask.
-    
   Returns:
-  
-  A ``uint8`` :py:class:`numpy.ndarray` 2D array (image) containing ROI mask.
-  Value ``1`` determines ROI area, value ``0`` -- outside ROI area. ``uint8``
-  is chosen so that annotations could be used in the ``bob.bio.vein`` platform
-  (there seems to be problems when saving / loading ``bool`` objects).
+    A ``uint8`` :py:class:`numpy.ndarray` 2D array (image) containing ROI mask.
+    Value ``1`` determines ROI area, value ``0`` -- outside ROI area. ``uint8``
+    is chosen so that annotations could be used in the ``bob.bio.vein`` platform
+    (there seems to be problems when saving / loading ``bool`` objects).
     
   Examples:
+    -  generate ROI mask::
+    
+        from bob.bio.vein.preprocessors.utils import ManualRoiCut
+        roi = ManualRoiCut(roi_annotation_points).roi_mask()
   
-  -  generate ROI mask::
-  
-      from bob.bio.vein.preprocessors.utils import ManualRoiCut
-      roi = ManualRoiCut(roi_annotation_points).roi_mask()
-
-  - replace image's outside-ROI with value ``pixel_value``::
-  
-      from bob.bio.vein.preprocessors.utils import ManualRoiCut
-      image_cutted = ManualRoiCut(roi_annotation_points, image).roi_image(pixel_value=0)
-  
+    - replace image's outside-ROI with value ``pixel_value``::
+    
+        from bob.bio.vein.preprocessors.utils import ManualRoiCut
+        image_cutted = ManualRoiCut(roi_annotation_points, image).roi_image(pixel_value=0)
   """
-
   def __init__(self,annotation, image = None, sizes = (480, 480)):
-    if isinstance(annotation, six.string_types):
-        if os.path.exists(annotation):
-            with open(annotation,'r') as f:
-                retval = np.loadtxt(f, ndmin=2)
-            self.annotation = list([tuple([k[1], k[0]]) for k in retval])
+    if image is not None:
+      if isinstance(image, six.string_types):
+        if os.path.exists(image):
+          image = Image.open(image)
+          self.image = np.array(image)
         else:
-            raise IOError("Doesn' t exist file: {}".format(annotation))
-            return 1
+          raise IOError("Doesn't exist file: {}".format(annotation))
+          return 1
+      else:
+        self.image = np.array(image)
+      self.size_y = self.image.shape[0]
+      self.size_x = self.image.shape[1]
+    else:
+      self.image = None
+      self.size_y = sizes[1]
+      self.size_x = sizes[0]
+    if isinstance(annotation, six.string_types):
+      if os.path.exists(annotation):
+        with open(annotation,'r') as f:
+          retval = np.loadtxt(f, ndmin=2)
+        self.annotation = list([tuple([self.__test_size__(k[1],self.size_y), self.__test_size__(k[0],self.size_x)]) for k in retval])
+      else:
+        raise IOError("Doesn' t exist file: {}".format(annotation))
+        return 1
     else :
-        # Convert from Bob format(x,y) to regular (y, x)
-        self.annotation = list([tuple([k[1], k[0]]) for k in annotation])
-    
-    #load image:
-    if image is not None:
-          if isinstance(image, six.string_types):
-              if os.path.exists(image):
-                  image = Image.open(image)
-                  self.image = np.array(image)
-              else:
-                  raise IOError("Doesn't exist file: {}".format(annotation))
-                  return 1
-          else:
-              self.image = np.array(image)
-          self.size_y = self.image.shape[0]
-          self.size_x = self.image.shape[1]
+      # Convert from Bob format(x,y) to regular (y, x)
+      self.annotation = list([tuple([self.__test_size__(k[1],self.size_y), self.__test_size__(k[0],self.size_x)]) for k in annotation])
+
+
+  def __test_size__(self, test_value, max_value):
+    if test_value >= 0 and test_value < max_value:
+      return test_value
     else:
-        self.image = None
-        self.size_y = sizes[1]
-        self.size_x = sizes[0]
+      return 0
+
+
   def roi_mask(self):
-      """Method roi_mask - generates ROI mask.
-        
-      Returns: A ``uint8`` :py:class:`numpy.ndarray` 2D array (image)
+    """Method ``roi_mask`` - generates ROI mask.
+    
+    Returns:
+      A ``uint8`` :py:class:`numpy.ndarray` 2D array (image)
       containing ROI mask. Value ``1`` determines ROI area, ``0`` -- outside
       ROI area.
-      """
-      mask = Image.new('L', (self.size_x, self.size_y), 0)
-      ImageDraw.Draw(mask).polygon(self.annotation, outline=1, fill=1)
-      mask = np.array(mask, dtype = np.uint8)
-      mask = 0 < mask
-      return mask
+    """
+    mask = Image.new('L', (self.size_x, self.size_y), 0)
+    ImageDraw.Draw(mask).polygon(self.annotation, outline=1, fill=1)
+    mask = np.array(mask, dtype = np.uint8)
+    mask = 0 < mask
+    return mask
+
+
   def roi_image(self, pixel_value = 0):
-      """Method roi_image - replaces outside ROI pixel values with ``pixel_value``
-      (default - 0).
+    """Method roi_image - replaces outside ROI pixel values with ``pixel_value``
+    (default - 0).
+    
+    Args:
+      pixel_value (``integer``): if given, outside-ROI region is replaced with this 
+        value. By default replaced with 0.
       
-      pixel_value (integer): if given, outside-ROI region is replaced with this 
-      value. By default replaced with 0.
-        
-      Returns: A copy of image that class was initialized with, outside ROI pixel
+    Returns:
+      A copy of image that class was initialized with, outside ROI pixel
       values are replaced with ``pixel_value``.
-      """
-      if self.image is not None:
-          mask = self.roi_mask()
-          self.image[mask == 0] = pixel_value
-          return self.image
-      else:
-          raise IOError("No input image given, can't perform non-ROI region removal")
-          return 1
+    """
+    if self.image is not None:
+        mask = self.roi_mask()
+        self.image[mask == 0] = pixel_value
+        return self.image
+    else:
+        raise IOError("No input image given, can't perform non-ROI region removal")
+        return 1
 
-            
-class ConstructVeinImage():
+
+def ConstructVeinImage(annotation_dictionary, center = False):
   """
   Constructs a binary image from manual annotations. The class is made to be used with
   the ``bob.db.biowave_v1`` database.
@@ -120,241 +126,232 @@ class ConstructVeinImage():
   The returned 2D array (see ``return value``, below) corresponds to a person's
   vein pattern, marked by human-expert.
   
-  Parameters:
-  
-  annotation_dictionary (:py:class:`dict`): Dictionary containing image and annotation data.
-  Such :py:class:`dict` can be returned by the high level ``bob.db.biowave_v1`` 
-  implementation of the ``bob.db.biowave_v1`` database. It is supposed to contain
-  fields:
-  - ``image``
-  - ``roi_annotations``
-  - ``vein_annotations``
-  
-  Although only the ``image.shape[0]``, ``image.shape[1]`` and variable 
-  ``vein_annotations`` are used.
-  
-  center (:py:class:`bool`): Flag, if set to ``True``, annotations are centered.
+  Args:
+    annotation_dictionary (:py:class:`dict`): Dictionary containing image and annotation data.
+      Such :py:class:`dict` can be returned by the high level ``bob.db.biowave_v1`` 
+      implementation of the ``bob.db.biowave_v1`` database. It is supposed to contain
+      fields (as can be returned by the ``bob.db.biowave_v1`` high level implementation):
+
+      - ``image``
+      - ``roi_annotations``
+      - ``vein_annotations``
+      
+      Although only the ``image.shape[0]``, ``image.shape[1]`` and variable 
+      ``vein_annotations`` are used.
+    center (:py:class:`bool`): Flag, if set to ``True``, annotations are centered.
   
   Returns:
-  
-  :py:class:`numpy.ndarray` : A 2D array with ``uint8`` values - value ``1``
-  represents annotated vein object. The output image is constructed using
-  annotation information - points.
-  Each line's points are connected and 5 pixels wide line is drawn. After 
-  all lines are drawn, lines are smoothed using Median filter with 
-  size 5x5 pixels.
+    :py:class:`numpy.ndarray` : A 2D array with ``uint8`` values - value ``1``
+    represents annotated vein object. The output image is constructed using
+    annotation information - points.
+    Each line's points are connected and 5 pixels wide line is drawn. After 
+    all lines are drawn, lines are smoothed using Median filter with 
+    size 5x5 pixels.
     
-  Examples::
-  
-      from bob.bio.vein.preprocessors.utils import ConstructVeinImage
-      vein_image = ConstructVeinImage(annotation_dictionary, center = self.center).return_annotations()
+  Examples:
+    Example to import the utils and run the function::
+        
+        from bob.bio.vein.preprocessors.utils import ConstructVeinImage
+        vein_image = ConstructVeinImage(annotation_dictionary, center = True)
   """
-  def __init__(self, annotation_dictionary, center = False):
-    self.image            = annotation_dictionary["image"]
-    #self.roi_annotations  = annotation_dictionary["roi_annotations"]
-    self.vein_annotations = annotation_dictionary["vein_annotations"]
-    self.center           = center
-  def return_annotations(self):
-    """method that returns annotations"""
-    im = Image.new('L', (self.image.shape[0], self.image.shape[1]), (0)) 
-    draw = ImageDraw.Draw(im)
-    if self.center == True:
-      xes_all = [point[1] for line in self.vein_annotations for point in line]
-      yes_all = [point[0] for line in self.vein_annotations for point in line]
-      for line in self.vein_annotations:
-        xes = [point[1] - np.round(np.mean(xes_all)) + 239 for point in line]
-        yes = [point[0] - np.round(np.mean(yes_all)) + 239 for point in line]
-        for point in range(len(line) - 1):
-          draw.line((xes[point],yes[point], xes[point+1], yes[point+1]), fill=1, width = 5)
-    else:
-      for line in self.vein_annotations:
-        xes = [point[1] for point in line]
-        yes = [point[0] for point in line]
-        for point in range(len(line) - 1):
-          draw.line((xes[point],yes[point], xes[point+1], yes[point+1]), fill=1, width = 5)
-    im = im.filter(ImageFilter.MedianFilter(5))
-    im = np.array(im, dtype = np.uint8)
-    return im
+  image            = annotation_dictionary["image"]
+  #roi_annotations  = annotation_dictionary["roi_annotations"]
+  vein_annotations = annotation_dictionary["vein_annotations"]
+
+  im = Image.new('L', (image.shape[0], image.shape[1]), (0)) 
+  draw = ImageDraw.Draw(im)
+  if center == True:
+    xes_all = [point[1] for line in vein_annotations for point in line]
+    yes_all = [point[0] for line in vein_annotations for point in line]
+    for line in vein_annotations:
+      xes = [point[1] - np.round(np.mean(xes_all)) + 239 for point in line]
+      yes = [point[0] - np.round(np.mean(yes_all)) + 239 for point in line]
+      for point in range(len(line) - 1):
+        draw.line((xes[point],yes[point], xes[point+1], yes[point+1]), fill=1, width = 5)
+  else:
+    for line in vein_annotations:
+      xes = [point[1] for point in line]
+      yes = [point[0] for point in line]
+      for point in range(len(line) - 1):
+        draw.line((xes[point],yes[point], xes[point+1], yes[point+1]), fill=1, width = 5)
+  im = im.filter(ImageFilter.MedianFilter(5))
+  im = np.array(im, dtype = np.uint8)
+  return im
+
+
+# help functions for the ``NormalizeImageRotation`` function
+def __rotate_point__(x,y, angle):
+  """
+  [xp, yp] = __rotate_point__(x,y, angle)
+  """
+  if type(x) is list:
+    if len(x) != len(y):
+      raise IOError("Length of x and y should be equal")
+    xp = []
+    yp = []
+    for nr in range(len(x)):
+      xp.append(x[nr] * np.cos(np.radians(angle)) - y[nr] * np.sin(np.radians(angle)))
+      yp.append(y[nr] * np.cos(np.radians(angle)) + x[nr] * np.sin(np.radians(angle)))
+  else:
+    xp = x * np.cos(np.radians(angle)) - y * np.sin(np.radians(angle))
+    yp = y * np.cos(np.radians(angle)) + x * np.sin(np.radians(angle))
   
-    
-    
-    
-    
-    
-class RotateImage():
+  return int(np.round(xp)), int(np.round(yp))
+
+
+def __guss_mask__(guss_size=27, sigma=6):
+    """Returns a 2D Gaussian kernel array."""
+    inp = np.zeros((guss_size, guss_size))
+    inp[guss_size//2, guss_size//2] = 1
+    return fi.gaussian_filter(inp, sigma)
+
+
+def __ramp__(a):
+  a = np.array(a)
+  a[a < 0]=0 
+  return a
+
+
+def __vein_filter__(image, a = 3, b = 4, sigma = 4, guss_size = 15, only_lines = True, dark_lines = True):
+  """
+  Vein filter
   """
-  RotateImage - automatically rotates image.
+  if dark_lines == True:
+    Z = 1
+  else:
+    Z = -1
   
-  So far tested only with annotations (binary images). Algorithm iteratively
-  search for rotation angle such that when image is filtered with the 
-  ``vein filter`` (As published in the BIOSIG 2015), the ``mean`` filtered 
-  image's vector angle (for the pixels in filtered image with a magnitude at least 1/2 of the 
-  maximal value of the filtered image) is ``+/- 0.5`` [deg].
+  if type(image) != np.ndarray:
+    image = np.array(image, dtype = np.float)
   
-  Parameters:
+  padsize = 2*a+b
+  gaussian_mask = __guss_mask__(guss_size, sigma)
   
-  image (:py:class:`numpy.ndarray`) : A 2D array containing input image. 
-  Currently tested only with binary images.
+  f2 = np.lib.pad(image, ((padsize, padsize), (padsize, padsize)), 'edge')
+  f2 = convolve2d(f2, gaussian_mask, mode='same')
   
-  dark_lines (:py:class:`bool`) : A flag (default value - ``False``)
-  that determines what kind of lines algorithm is going to search for.
-  With default value ``False`` it will search for *whiter than
-  background* lines (as is the case with annotations). If set 
-  to ``True`` -- will search for *darker than background* lines 
-  (as is the case with vein images).
-      
-  Returns:
+  result = np.zeros(image.shape)
   
-    :py:class:`numpy.ndarray` : A 2D array with rotated input image
+  for angle in np.arange(0,179,11.25 / 2):
+    [ap, bp] = __rotate_point__(-b,-2*a, angle)
+    mask_1 = f2[padsize+ap:-padsize+ap,padsize+bp:-padsize+bp]
     
-  Examples::
-  
-      from bob.bio.vein.preprocessors.utils import RotateImage
-      image = RotateImage(image, dark_lines = False).rotate()
-  """
-  def __init__(self, image, dark_lines = False):
-    self.image            = image
-    self.dark_lines       = dark_lines
-  def __rotate_point__(self, x,y, angle):
-    """
-    [xp, yp] = __rotate_point__(x,y, angle)
-    """
-    if type(x) is list:
-      if len(x) != len(y):
-        raise IOError("Length of x and y should be equal")
-      xp = []
-      yp = []
-      for nr in range(len(x)):
-        xp.append(x[nr] * np.cos(np.radians(angle)) - y[nr] * np.sin(np.radians(angle)))
-        yp.append(y[nr] * np.cos(np.radians(angle)) + x[nr] * np.sin(np.radians(angle)))
-    else:
-      xp = x * np.cos(np.radians(angle)) - y * np.sin(np.radians(angle))
-      yp = y * np.cos(np.radians(angle)) + x * np.sin(np.radians(angle))
+    [ap, bp] = __rotate_point__(-b,-1*a, angle)
+    mask_2 = f2[padsize+ap:-padsize+ap,padsize+bp:-padsize+bp]
     
-    return int(np.round(xp)), int(np.round(yp))
-  
-  def __guss_mask__(self, guss_size=27, sigma=6):
-      """Returns a 2D Gaussian kernel array."""
-      inp = np.zeros((guss_size, guss_size))
-      inp[guss_size//2, guss_size//2] = 1
-      return fi.gaussian_filter(inp, sigma)
-  
-  def __ramp__(self, a):
-    a = np.array(a)
-    a[a < 0]=0 
-    return a
-  
-  def __vein_filter__(self, image, a = 3, b = 4, sigma = 4, guss_size = 15, only_lines = True, dark_lines = True):
-    """
-    Vein filter
-    """
-    if dark_lines == True:
-      Z = 1
-    else:
-      Z = -1
+    [ap, bp] = __rotate_point__(-b,   0, angle)
+    mask_3 = f2[padsize+ap:-padsize+ap,padsize+bp:-padsize+bp]
     
-    if type(image) != np.ndarray:
-      image = np.array(image, dtype = np.float)
+    [ap, bp] = __rotate_point__(-b, 1*a, angle)
+    mask_4 = f2[padsize+ap:-padsize+ap,padsize+bp:-padsize+bp]
     
-    padsize = 2*a+b
-    gaussian_mask = self.__guss_mask__(guss_size, sigma)
+    [ap, bp] = __rotate_point__(-b, 2*a, angle)
+    mask_5 = f2[padsize+ap:-padsize+ap,padsize+bp:-padsize+bp]
     
+    [ap, bp] = __rotate_point__(+b,-2*a, angle)
+    mask_6 = f2[padsize+ap:-padsize+ap,padsize+bp:-padsize+bp] 
     
-    f2 = np.lib.pad(image, ((padsize, padsize), (padsize, padsize)), 'edge')
-    f2 = convolve2d(f2, gaussian_mask, mode='same')
+    [ap, bp] = __rotate_point__(+b,-1*a, angle)
+    mask_7 = f2[padsize+ap:-padsize+ap,padsize+bp:-padsize+bp]
     
-    result = np.zeros(image.shape)
+    [ap, bp] = __rotate_point__(+b,   0, angle)
+    mask_8 = f2[padsize+ap:-padsize+ap,padsize+bp:-padsize+bp]
     
-    for angle in np.arange(0,179,11.25 / 2):
-      [ap, bp] = self.__rotate_point__(-b,-2*a, angle)
-      mask_1 = f2[padsize+ap:-padsize+ap,padsize+bp:-padsize+bp]
-      
-      [ap, bp] = self.__rotate_point__(-b,-1*a, angle)
-      mask_2 = f2[padsize+ap:-padsize+ap,padsize+bp:-padsize+bp]
-      
-      [ap, bp] = self.__rotate_point__(-b,   0, angle)
-      mask_3 = f2[padsize+ap:-padsize+ap,padsize+bp:-padsize+bp]
-      
-      [ap, bp] = self.__rotate_point__(-b, 1*a, angle)
-      mask_4 = f2[padsize+ap:-padsize+ap,padsize+bp:-padsize+bp]
-      
-      [ap, bp] = self.__rotate_point__(-b, 2*a, angle)
-      mask_5 = f2[padsize+ap:-padsize+ap,padsize+bp:-padsize+bp]
-      
-      [ap, bp] = self.__rotate_point__(+b,-2*a, angle)
-      mask_6 = f2[padsize+ap:-padsize+ap,padsize+bp:-padsize+bp] 
-      
-      [ap, bp] = self.__rotate_point__(+b,-1*a, angle)
-      mask_7 = f2[padsize+ap:-padsize+ap,padsize+bp:-padsize+bp]
-      
-      [ap, bp] = self.__rotate_point__(+b,   0, angle)
-      mask_8 = f2[padsize+ap:-padsize+ap,padsize+bp:-padsize+bp]
-      
-      [ap, bp] = self.__rotate_point__(+b, 1*a, angle)
-      mask_9 = f2[padsize+ap:-padsize+ap,padsize+bp:-padsize+bp]
-      
-      [ap, bp] = self.__rotate_point__(+b, 2*a, angle)
-      mask_10 = f2[padsize+ap:-padsize+ap,padsize+bp:-padsize+bp]
-      
-      amplitude_rez = self.__ramp__(Z*(mask_1+mask_5+mask_6+mask_10)*3 \
-                       -Z*(mask_2+mask_3+mask_4+mask_7+mask_8+mask_9)*2)
-                       
-      if only_lines == True:
-        col = np.zeros((6,image.shape[0], image.shape[1]))
-        col[0] = np.minimum(self.__ramp__(-Z*mask_2+Z*mask_1),self.__ramp__(-Z*mask_2+Z*mask_5))
-        col[1] = np.minimum(self.__ramp__(-Z*mask_3+Z*mask_1),self.__ramp__(-Z*mask_3+Z*mask_5))
-        col[2] = np.minimum(self.__ramp__(-Z*mask_4+Z*mask_1),self.__ramp__(-Z*mask_4+Z*mask_5))
-        col[3] = np.minimum(self.__ramp__(-Z*mask_7+Z*mask_6),self.__ramp__(-Z*mask_7+Z*mask_10))
-        col[4] = np.minimum(self.__ramp__(-Z*mask_8+Z*mask_6),self.__ramp__(-Z*mask_8+Z*mask_10))
-        col[5] = np.minimum(self.__ramp__(-Z*mask_9+Z*mask_6),self.__ramp__(-Z*mask_9+Z*mask_10))
-        angle_rez = np.min(col, axis = 0)
-        amplitude_rez[angle_rez==0] = 0
-        
-      result = result + amplitude_rez*np.exp(1j*2*(angle - 90)*np.pi/180)
-      
-    result = np.abs(result) * np.exp(1j*np.angle(result)/2)
-    return result
+    [ap, bp] = __rotate_point__(+b, 1*a, angle)
+    mask_9 = f2[padsize+ap:-padsize+ap,padsize+bp:-padsize+bp]
+
+    [ap, bp] = __rotate_point__(+b, 2*a, angle)
+    mask_10 = f2[padsize+ap:-padsize+ap,padsize+bp:-padsize+bp]
     
-  def __get_rotatation_angle__(self,image, dark_lines = False):
-    """
-    angle = get_rotatation_angle(image)
+    amplitude_rez = __ramp__(Z*(mask_1+mask_5+mask_6+mask_10)*3 \
+                     -Z*(mask_2+mask_3+mask_4+mask_7+mask_8+mask_9)*2)
+                     
+    if only_lines == True:
+      col = np.zeros((6,image.shape[0], image.shape[1]))
+      col[0] = np.minimum(__ramp__(-Z*mask_2+Z*mask_1),__ramp__(-Z*mask_2+Z*mask_5))
+      col[1] = np.minimum(__ramp__(-Z*mask_3+Z*mask_1),__ramp__(-Z*mask_3+Z*mask_5))
+      col[2] = np.minimum(__ramp__(-Z*mask_4+Z*mask_1),__ramp__(-Z*mask_4+Z*mask_5))
+      col[3] = np.minimum(__ramp__(-Z*mask_7+Z*mask_6),__ramp__(-Z*mask_7+Z*mask_10))
+      col[4] = np.minimum(__ramp__(-Z*mask_8+Z*mask_6),__ramp__(-Z*mask_8+Z*mask_10))
+      col[5] = np.minimum(__ramp__(-Z*mask_9+Z*mask_6),__ramp__(-Z*mask_9+Z*mask_10))
+      angle_rez = np.min(col, axis = 0)
+      amplitude_rez[angle_rez==0] = 0
+      
+    result = result + amplitude_rez*np.exp(1j*2*(angle - 90)*np.pi/180)
     
-    Returns the rotation angle in deg.
-    """
-    result = self.__vein_filter__(image, a = 4, b = 1, sigma = 2, guss_size = 15, only_lines = True, dark_lines = False)
-    result_nonzero = result[np.abs(result) > np.abs(result).max() / 2]
-    result_angle = np.angle(result_nonzero, deg=True)
-    angle = result_angle.mean()
-    return angle
-  
-  def __rotate_image__(self, image, angle):
-    """
-    image = rotate_image(image, angle)
-    """
-    image = scipy.ndimage.rotate(image, angle, reshape = False, cval=0)
-    image[image > 255] = 255
-    image[image < 0]   = 0
-    return image
+  result = np.abs(result) * np.exp(1j*np.angle(result)/2)
+  return result
+
+
+def __get_rotatation_angle__(image, dark_lines = False):
+  """
+  angle = get_rotatation_angle(image)
   
-  def __align_image__(self, image, precision = 0.5, iterations = 25, dark_lines = False):
-    """
-    [image, rotation_angle, angle_error] = align_image(image, precision = 0.5, iterations = 25)
-    """
-    rotation_angle = 0
-    angle_error = self.__get_rotatation_angle__(image, dark_lines)
-    if abs(angle_error) <= precision:
+  Returns the rotation angle in deg.
+  """
+  result = __vein_filter__(image, a = 4, b = 1, sigma = 2, guss_size = 15, only_lines = True, dark_lines = False)
+  result_nonzero = result[np.abs(result) > np.abs(result).max() / 2]
+  result_angle = np.angle(result_nonzero, deg=True)
+  angle = result_angle.mean()
+  return angle
+
+
+def __rotate_image__(image, angle):
+  """
+  image = rotate_image(image, angle)
+  """
+  image = scipy.ndimage.rotate(image, angle, reshape = False, cval=0)
+  image[image > 255] = 255
+  image[image < 0]   = 0
+  return image
+
+
+def __align_image__(image, precision = 0.5, iterations = 25, dark_lines = False):
+  """
+  [image, rotation_angle, angle_error] = align_image(image, precision = 0.5, iterations = 25)
+  """
+  rotation_angle = 0
+  angle_error = __get_rotatation_angle__(image, dark_lines)
+  if abs(angle_error) <= precision:
+    return image, rotation_angle, angle_error
+  for k in range(iterations):
+    rotation_angle = rotation_angle + (angle_error * 0.33)
+    image = __rotate_image__(image, angle_error * 0.33)
+    angle_error = __get_rotatation_angle__(image, dark_lines)
+    #print(rotation_angle)
+    if abs(angle_error) <= precision or k == iterations - 1:
       return image, rotation_angle, angle_error
-    for k in range(iterations):
-      rotation_angle = rotation_angle + (angle_error * 0.33)
-      image = self.__rotate_image__(image, angle_error * 0.33)
-      angle_error = self.__get_rotatation_angle__(image, dark_lines)
-      #print(rotation_angle)
-      if abs(angle_error) <= precision or k == iterations - 1:
-        return image, rotation_angle, angle_error
 
-  def rotate(self):
-    """A call method that executes image rotation
-    """
-    [rotated_image, rotation_angle, angle_error] = self.__align_image__(image = self.image, dark_lines = self.dark_lines)
-    rotated_image = np.array(rotated_image, dtype = self.image.dtype)
-    return rotated_image
+
+def NormalizeImageRotation(image, dark_lines = False):
+  """
+  function ``NormalizeImageRotation`` - automatically rotates image by a self-defined angle.
+  
+  So far tested only with annotations (binary images). Algorithm iteratively
+  searches for rotation angle such that when image is filtered with the 
+  ``vein filter`` (As published in the BIOSIG 2015), the ``mean`` filtered 
+  image's vector angle (for the pixels in filtered image with a magnitude at least 1/2 of the 
+  maximal value of the filtered image) is ``+/- 0.5`` [deg].
+  
+  Args:
+    image (:py:class:`numpy.ndarray`) : A 2D array containing input image. 
+      Currently tested only with binary images.
+    dark_lines (:py:class:`bool`) : A flag (default value - ``False``)
+      that determines what kind of lines algorithm is going to search for to 
+      align the image. With default value ``False`` it will search for *whiter than
+      background* lines (as is the case with annotations). If set 
+      to ``True`` -- will search for *darker than background* lines 
+      (as is the case with vein images).
+      
+  Returns:
+    :py:class:`numpy.ndarray` : A 2D array with rotated input image
+  
+  Examples:
+    Example to import the utils and use the function::
+        
+        from bob.bio.vein.preprocessors.utils import NormalizeImageRotation
+        image = NormalizeImageRotation(image, dark_lines = False)
+  """
+  [rotated_image, rotation_angle, angle_error] = __align_image__(image = image, dark_lines = dark_lines)
+  rotated_image = np.array(rotated_image, dtype = image.dtype)
+  return rotated_image
diff --git a/bob/bio/vein/tests/test.py b/bob/bio/vein/tests/test.py
index 9d96f7c2d9c32e12a2c80c37a17c6219d9eb7fe9..e55d10537c97622c6c5006856ccb2830e3534187 100644
--- a/bob/bio/vein/tests/test.py
+++ b/bob/bio/vein/tests/test.py
@@ -231,7 +231,7 @@ def test_ConstructAnnotations():
   image_filename = F( ( 'preprocessors', 'ConstructAnnotations.png' ) )
   roi_annotations_filename = F( ( 'preprocessors', 'ConstructAnnotations.txt' ) )
   vein_annotations_filename = F( ( 'preprocessors', 'ConstructAnnotations.npy' ) )
-  
+
   image = bob.io.base.load( image_filename )
   roi_annotations = np.loadtxt(roi_annotations_filename, dtype='uint16')
   roi_annotations =  [tuple([point[0], point[1]]) for point in roi_annotations]
@@ -243,9 +243,9 @@ def test_ConstructAnnotations():
   
   annotation_dictionary = {"image" : image, "roi_annotations" : roi_annotations, "vein_annotations" : vein_annotations}
   from bob.bio.vein.preprocessor.utils import ConstructVeinImage
-  from bob.bio.vein.preprocessor.utils import RotateImage
-  output = ConstructVeinImage(annotation_dictionary, center = True).return_annotations()
-  output = RotateImage(output, dark_lines = False).rotate()
+  from bob.bio.vein.preprocessor.utils import NormalizeImageRotation
+  output = ConstructVeinImage(annotation_dictionary, center = True)
+  output = NormalizeImageRotation(output, dark_lines = False)
   assert np.array_equal(output, image)