Coverage for src/bob/bio/vein/preprocessor/crop.py: 93%

29 statements  

« prev     ^ index     » next       coverage.py v7.6.0, created at 2024-07-12 23:27 +0200

1#!/usr/bin/env python 

2# vim: set fileencoding=utf-8 : 

3 

4 

5"""Base utilities for pre-cropping images""" 

6 

7 

8class Cropper(object): 

9 """This is the base class for all croppers 

10 

11 It defines the minimum requirements for all derived cropper classes. 

12 

13 

14 """ 

15 

16 def __init__(self): 

17 pass 

18 

19 def __call__(self, image): 

20 """Overwrite this method to implement your masking method 

21 

22 

23 Parameters: 

24 

25 image (numpy.ndarray): A 2D numpy array of type ``uint8`` with the 

26 input image 

27 

28 

29 Returns: 

30 

31 numpy.ndarray: A 2D numpy array of the same type as the input, with 

32 cropped rows and columns as per request 

33 

34 """ 

35 

36 raise NotImplementedError("You must implement the __call__ slot") 

37 

38 

39class FixedCrop(Cropper): 

40 """Implements cropping using a fixed suppression of border pixels 

41 

42 The defaults supress no lines from the image and returns an image like the 

43 original. If an :py:class:`bob.bio.vein.database.AnnotatedArray` is passed, 

44 then we also check for its ``.metadata['roi']`` component and correct it so 

45 that annotated RoI points are consistent on the cropped image. 

46 

47 

48 .. note:: 

49 

50 Before choosing values, note you're responsible for knowing what is the 

51 orientation of images fed into this cropper. 

52 

53 

54 Parameters: 

55 

56 top (:py:class:`int`, optional): Number of lines to suppress from the top 

57 of the image. The top of the image corresponds to ``y = 0``. 

58 

59 bottom (:py:class:`int`, optional): Number of lines to suppress from the 

60 bottom of the image. The bottom of the image corresponds to ``y = 

61 height``. 

62 

63 left (:py:class:`int`, optional): Number of lines to suppress from the left 

64 of the image. The left of the image corresponds to ``x = 0``. 

65 

66 right (:py:class:`int`, optional): Number of lines to suppress from the 

67 right of the image. The right of the image corresponds to ``x = width``. 

68 

69 """ 

70 

71 def __init__(self, top=0, bottom=0, left=0, right=0): 

72 self.top = top 

73 self.bottom = bottom 

74 self.left = left 

75 self.right = right 

76 

77 def __call__(self, image): 

78 """Returns a big mask 

79 

80 

81 Parameters: 

82 

83 image (numpy.ndarray): A 2D numpy array of type ``uint8`` with the 

84 input image 

85 

86 

87 Returns: 

88 

89 numpy.ndarray: A 2D numpy array of type boolean with the caculated 

90 mask. ``True`` values correspond to regions where the finger is 

91 situated 

92 

93 

94 """ 

95 

96 # this should work even if limits are zeros 

97 h, w = image.shape 

98 retval = image[self.top : h - self.bottom, self.left : w - self.right] 

99 

100 if hasattr(retval, "metadata") and "roi" in retval.metadata: 

101 # adjust roi points to new cropping 

102 retval = retval.copy() # don't override original 

103 h, w = retval.shape 

104 points = [] 

105 for y, x in retval.metadata["roi"]: 

106 y = max(y - self.top, 0) # adjust 

107 y = min(y, h - 1) # verify it is not over the limits 

108 x = max(x - self.left, 0) # adjust 

109 x = min(x, w - 1) # verify it is not over the limits 

110 points.append((y, x)) 

111 retval.metadata["roi"] = points 

112 

113 return retval 

114 

115 

116class NoCrop(FixedCrop): 

117 """Convenience: same as FixedCrop()""" 

118 

119 def __init__(self): 

120 super(NoCrop, self).__init__(0, 0, 0, 0)