Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

from imutils.face_utils import FaceAligner 

from imutils.face_utils import rect_to_bb 

from hutts_utils.hutts_logger import logger 

from pathlib import Path 

from hutts_utils.pypath import correct_path 

import dlib 

import os 

import cv2 

 

TEMPLATE_DIR = correct_path(Path(os.path.abspath(os.path.dirname(__file__)), 'templates')) 

 

FACE_NOT_FOUND_PLACE_HOLDER = cv2.imread(TEMPLATE_DIR + "/profile.jpg") 

 

 

class FaceDetector: 

""" 

The FaceDetector class is responsible for 

1. Detecting the face. 

2. Extracting a face from an image. 

3. Applying blurring on a detected face in an image. 

""" 

def __init__(self, shape_predictor_path): 

""" 

Initialise Face Detector Manager. 

Authors(s): 

Nicolai van Niekerk, Stephan Nell 

Args: 

shape_predictor_path (str): Describes the path the Shape Predictor 

trained data. 

Returns: 

None 

 

""" 

self.shape_predictor_path = shape_predictor_path 

self.predictor = dlib.shape_predictor(self.shape_predictor_path) 

self.detector = dlib.get_frontal_face_detector() 

self.face_aligner = FaceAligner(self.predictor, desiredFaceWidth=256) 

 

def detect(self, image): 

""" 

This function detects the face in the image passed. 

By making use of the dlib HOG feature image_preprocessing and linear classifier for frontal face detection 

we are able to detect the face with less false-positive results and without a major time penalty. 

More Information dlib frontal_face detection: http://dlib.net/imaging.html#get_frontal_face_detector 

 

A check will be done to see if a face is present in the image. 

If a face is not detected in the image the execution should log that the face was not found and continue 

with execution. This is due to the fact that face detection might not be critical to 

a function (like with text extraction) and rather be used to increase accuracy. 

Author(s): 

Stephan Nell 

Args: 

image (:obj:'OpenCV image'): Image containing the face we need to detect. 

Raises: 

ValueError: If no face can be detected. 

Returns: 

Integer List: This list contains the box coordinates for the region in which the face resides. 

""" 

rectangles = self.detector(image, 1) 

if len(rectangles) == 0: 

logger.warning('No valid face found. Returning None') 

return rectangles[0] if rectangles else None 

 

def extract_face(self, image): 

""" 

This function finds a face in the image passed and is optimised 

to align the face before being returned. 

Author(s): 

Stephan Nell 

Args: 

image (:obj:'OpenCV image'): Image containing the face we need to detect and extract. 

Raises: 

ValueError: If no face can be detected. 

Returns: 

obj:'OpenCV image': Any background and unnecessary components are removed and only 

the aligned face is returned. 

obj:'OpenCV image': A copy of the original image is returned. 

""" 

rectangle = self.detect(image) 

if rectangle is None: 

return FACE_NOT_FOUND_PLACE_HOLDER 

face_aligned = self.face_aligner.align(image, image, rectangle) 

return face_aligned 

 

def blur_face(self, image): 

""" 

This function find the faces and apply a blurring effect on the detected region. 

After the region has been blurred, the blurred region is reapplied to the original image. 

Blurring the face is implemented as a method in the attempt to reduce noise when extracting 

text from the image later in the image pipeline. 

Author(s): 

Stephan Nell 

Args: 

image (:obj:'OpenCV image'): Image containing the face we need to detect and blur. 

Raises: 

ValueError: If no face can be detected. 

Returns: 

obj:'OpenCV image': A copy of the original image is returned but with the applied 

blurring to the face region. 

 

Remove hard coded y and h adjustment values. 

 

""" 

rectangle = self.detect(image) 

if rectangle is None: 

logger.warning('No face found. Facial Blur ignored.') 

return image 

(x, y, w, h) = rect_to_bb(rectangle) 

# To Extend the entire region of face since face detector does not include upper head. 

y = y-75 

h = h+75 

sub_face = image[y:y + h, x:x + w] 

sub_face = cv2.dilate(sub_face, None, iterations=3) 

sub_face = cv2.GaussianBlur(sub_face, (31, 31), 0) 

image[y:y + sub_face.shape[0], x:x + sub_face.shape[1]] = sub_face 

return image