import cv2 import numpy as np from skimage.feature import local_binary_pattern import matplotlib.pyplot as plt import dlib import imutils import os from PIL import Image from utils.cv_utils import get_image from typing import Tuple class GetFaceTexture: def __init__(self) -> None: pass def preprocess_image(self, image) -> np.array: image = imutils.resize(image, width=400) gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) return gray_image def get_face(self, 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 def get_face_texture(self, 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 def postprocess_image(self, lbp: np.array) -> Image: lbp = (lbp * 255).astype(np.uint8) return Image.fromarray(lbp) def main(self, image_input) -> Image: 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) return face_texture_image, face_image, std if __name__ == "__main__": image_path = 'data/images_symmetry/gigi_hadid.webp' print(GetFaceTexture().main(image_path))