File size: 1,782 Bytes
75557db
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""
utils/image.py — Tiện ích xử lý ảnh: decode, encode, annotate, crop face
"""
import base64
import cv2
import numpy as np


def decode_image(file_bytes: bytes) -> np.ndarray | None:
    """Giải mã bytes ảnh thành numpy array (BGR)."""
    nparr = np.frombuffer(file_bytes, np.uint8)
    img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
    return img


def image_to_base64(img: np.ndarray) -> str:
    """Chuyển numpy array thành chuỗi base64 JPEG."""
    _, buffer = cv2.imencode(".jpg", img)
    return base64.b64encode(buffer).decode("utf-8")


def image_to_bytes(img: np.ndarray) -> bytes:
    """Chuyển numpy array thành JPEG bytes."""
    _, buffer = cv2.imencode(".jpg", img)
    return buffer.tobytes()


def annotate_frame(frame: np.ndarray, bbox, label: str, color: tuple) -> None:
    """Vẽ bounding box + nhãn lên frame."""
    x1, y1, x2, y2 = [int(v) for v in bbox]
    cv2.rectangle(frame, (x1, y1), (x2, y2), color, 3)
    cv2.putText(
        frame, label,
        (x1, max(y1 - 10, 15)),
        cv2.FONT_HERSHEY_SIMPLEX, 0.65, color, 2,
    )


def crop_face(img: np.ndarray, bbox, padding: int = 20) -> tuple[np.ndarray, dict]:
    """
    Cắt khuôn mặt từ ảnh gốc với padding.
    Returns:
        face_crop: numpy array
        coords: dict với x1, y1, x2, y2 sau khi clamp
    """
    h, w = img.shape[:2]
    x1 = int(max(0, bbox[0] - padding))
    y1 = int(max(0, bbox[1] - padding))
    x2 = int(min(w, bbox[2] + padding))
    y2 = int(min(h, bbox[3] + padding))
    face_crop = img[y1:y2, x1:x2]
    return face_crop, {"x1": x1, "y1": y1, "x2": x2, "y2": y2}


def get_image_dimensions(img: np.ndarray) -> tuple[int, int]:
    """Trả về (width, height) của ảnh."""
    h, w = img.shape[:2]
    return w, h