File size: 3,062 Bytes
2fbad05
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import cv2
from PIL import Image
import numpy as np



def preprocess_image(image):
    """
    Preprocesses an input image for prediction.
    
    Args:
        image (Union[str, numpy.ndarray]): File path to an image or a numpy array.
    
    Returns:
        PIL.Image: Preprocessed image.
    """
    if isinstance(image, str):  # Handle file path
        image = Image.open(image).convert("RGB")
    elif isinstance(image, np.ndarray):  # Handle numpy array
        image = Image.fromarray(image).convert("RGB")
    else:
        raise ValueError("Unsupported image type. Must be a file path or numpy array.")
    return image


def resize_shorter_side(img, min_length):
    """
    Resize the shorter side of img to min_length while
    preserving the aspect ratio.
    """
    ow, oh = img.size
    mult = 8
    if ow < oh:
        if ow == min_length and oh % mult == 0:
            return img, (ow, oh)
        w = min_length
        h = int(min_length * oh / ow)
    else:
        if oh == min_length and ow % mult == 0:
            return img, (ow, oh)
        h = min_length
        w = int(min_length * ow / oh)
    return img.resize((w, h), Image.BICUBIC), (w, h)


def generate_local_image(image):
    """
    Detects the face in the input image and extracts it as a 'local image'.
    If no face is detected, returns the global image as the local image.

    Args:
        image (Union[PIL.Image, numpy.ndarray]): The input image.
    
    Returns:
        PIL.Image: The cropped face or the original image if no face is detected.
    """
    # Convert numpy array to PIL.Image if necessary
    if isinstance(image, np.ndarray):
        image = Image.fromarray(image)

    # Convert PIL image to OpenCV format for face detection
    image_cv = np.array(image)
    image_gray = cv2.cvtColor(image_cv, cv2.COLOR_RGB2GRAY)

    # Load OpenCV's pre-trained Haar Cascade for face detection
    face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml")
    faces = face_cascade.detectMultiScale(image_gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))

    if len(faces) == 0:
        print("No face detected. Using the global image as the local image.")
        return image  # Return the global image as fallback

    # Use the first detected face
    x, y, w, h = faces[0]

    # Crop the face region
    face_image = image.crop((x, y, x + w, y + h))
    return face_image


def preprocess_video(video_path, frame_count=32):
    cap = cv2.VideoCapture(video_path)
    if not cap.isOpened():
        return []  # Return an empty list if video can't be opened

    frames = []
    total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
    if total_frames == 0:
        return []  # Handle videos with no frames

    interval = max(1, total_frames // frame_count)
    for i in range(frame_count):
        cap.set(cv2.CAP_PROP_POS_FRAMES, i * interval)
        ret, frame = cap.read()
        if ret:
            frames.append(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
    cap.release()
    return frames