Coverage for src/bob/bio/face/preprocessor/INormLBP.py: 87%

23 statements  

« prev     ^ index     » next       coverage.py v7.6.0, created at 2024-07-13 00:04 +0200

1#!/usr/bin/env python 

2# vim: set fileencoding=utf-8 : 

3# @author: Manuel Guenther <Manuel.Guenther@idiap.ch> 

4# @author: Tiago de Freitas Pereira <tiago.pereira@idiap.ch> 

5 

6import skimage 

7 

8from .Base import Base 

9from .utils import load_cropper 

10 

11 

12class INormLBP(Base): 

13 """ 

14 Performs I-Norm LBP on the given image. 

15 

16 The supported LBP methods are the ones available on. 

17 https://scikit-image.org/docs/dev/api/skimage.feature.html#skimage.feature.local_binary_pattern 

18 

19 

20 

21 Parameters 

22 ---------- 

23 

24 face_cropper : str or :py:class:`bob.bio.face.preprocessor.FaceCrop` or :py:class:`bob.bio.face.preprocessor.FaceDetect` or ``None`` 

25 The face image cropper that should be applied to the image. 

26 It might be specified as a registered resource, a configuration file, or an instance of a preprocessor. 

27 

28 .. note:: The given class needs to contain a ``crop_face`` method. 

29 

30 neighbors : int 

31 Number of circularly symmetric neighbor set points (quantization of the angular space) 

32 

33 radius : int 

34 The radius of the LBP features to extract 

35 

36 method : str 

37 The type of LBP to use. https://scikit-image.org/docs/dev/api/skimage.feature.html#skimage.feature.local_binary_pattern 

38 

39 

40 """ 

41 

42 def __init__( 

43 self, 

44 face_cropper, 

45 neighbors=8, 

46 radius=2, # Radius of the LBP 

47 method="default", # Type of LBP 

48 **kwargs, 

49 ): 

50 # call base class constructors 

51 Base.__init__(self, **kwargs) 

52 

53 self.face_cropper = face_cropper 

54 self.radius = radius 

55 self.neighbors = neighbors 

56 self.method = method 

57 self.cropper = load_cropper(face_cropper) 

58 

59 def transform(self, X, annotations=None): 

60 """__call__(image, annotations = None) -> face 

61 

62 Aligns the given image according to the given annotations. 

63 

64 First, the desired color channel is extracted from the given image. 

65 Afterward, the face is eventually cropped using the ``face_cropper`` specified in the constructor. 

66 Then, the image is photometrically enhanced by extracting LBP features [HRM06]_. 

67 Finally, the resulting face is converted to the desired data type. 

68 

69 **Parameters:** 

70 

71 image : 2D or 3D :py:class:`numpy.ndarray` 

72 The face image to be processed. 

73 

74 annotations : dict or ``None`` 

75 The annotations that fit to the given image. 

76 Might be ``None``, when the ``face_cropper`` is ``None`` or of type :py:class:`FaceDetect`. 

77 

78 **Returns:** 

79 

80 face : 2D :py:class:`numpy.ndarray` 

81 The cropped and photometrically enhanced face. 

82 """ 

83 

84 def _crop_one_sample(image, annotations=None): 

85 if self.cropper is not None: 

86 # TODO: USE THE TAG `ALLOW_ANNOTATIONS` 

87 image = ( 

88 self.cropper.transform([image]) 

89 if annotations is None 

90 else self.cropper.transform([image], [annotations]) 

91 ) 

92 # LBP's doesn't work with batches, so we have to work this out 

93 # Also, we change the color channel *after* cropping : some croppers use MTCNN internally, that works on multichannel images 

94 image = self.change_color_channel(image[0]) 

95 image = skimage.feature.local_binary_pattern( 

96 image, P=self.neighbors, R=self.radius, method=self.method 

97 ) 

98 else: 

99 # Handle with the cropper is None 

100 image = self.change_color_channel(image) 

101 # image = self.lbp_extractor(image) 

102 image = skimage.feature.local_binary_pattern( 

103 image, P=self.neighbors, R=self.radius, method=self.method 

104 ) 

105 

106 return self.data_type(image) 

107 

108 if annotations is None: 

109 return [_crop_one_sample(data) for data in X] 

110 else: 

111 return [ 

112 _crop_one_sample(data, annot) 

113 for data, annot in zip(X, annotations) 

114 ]