File size: 2,288 Bytes
e5ce3a7
 
 
 
 
59ece0e
0347340
59ece0e
e5ce3a7
 
 
 
 
59ece0e
 
 
4ff0905
e5ce3a7
 
59ece0e
 
 
e5ce3a7
 
 
 
 
59ece0e
 
 
 
 
 
988dde3
e5ce3a7
59ece0e
 
 
e5ce3a7
 
 
59ece0e
 
 
e5ce3a7
 
 
59ece0e
 
 
e5ce3a7
59ece0e
 
0347340
e5ce3a7
 
 
 
 
0347340
988dde3
 
 
e5ce3a7
 
59ece0e
54e742e
e5ce3a7
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
import cv2
import numpy as np
from skimage.feature import local_binary_pattern
import dlib
import imutils
from PIL import Image as PILImage
from src.cv_utils import get_image, resize_image_height
from typing import Tuple, List, Union


class GetFaceTexture:
    def __init__(self) -> None:
        pass

    @staticmethod
    def preprocess_image(image) -> np.array:
        image = imutils.resize(image, width=500)
        gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        return gray_image

    @staticmethod
    def get_face(gray_image: np.array) -> np.array:
        detector = dlib.get_frontal_face_detector()
        faces = detector(gray_image, 1)
        if len(faces) == 0:
            return "No face detected."

        x, y, w, h = (
            faces[0].left(),
            faces[0].top(),
            faces[0].width(),
            faces[0].height(),
        )
        face_image = gray_image[y : y + h, x : x + w]
        return face_image

    @staticmethod
    def get_face_texture(face_image: np.array) -> Tuple[np.array, float]:
        radius = 1
        n_points = 8 * radius
        lbp = local_binary_pattern(face_image, n_points, radius, method="uniform")
        hist, _ = np.histogram(
            lbp.ravel(), bins=np.arange(0, n_points + 3), range=(0, n_points + 2)
        )
        variance = np.var(hist)
        std = np.sqrt(variance)
        return lbp, std

    @staticmethod
    def postprocess_image(lbp: np.array) -> PILImage:
        lbp = (lbp * 255).astype(np.uint8)
        return PILImage.fromarray(lbp)

    def main(self, image_input) -> List[Union[PILImage.Image, PILImage.Image, dict]]:
        image = get_image(image_input)
        gray_image = self.preprocess_image(image)
        face_image = self.get_face(gray_image)
        lbp, std = self.get_face_texture(face_image)
        face_texture_image = self.postprocess_image(lbp)
        face_image = PILImage.fromarray(face_image)
        face_image = resize_image_height(face_image, new_height=300)
        face_texture_image = resize_image_height(face_texture_image, new_height=300)
        return face_image, face_texture_image, {"texture_std": round(std, 2)}


if __name__ == "__main__":
    image_path = "data/gigi_hadid.webp"
    print(GetFaceTexture().main(image_path))