File size: 6,321 Bytes
19d3e3d
 
8f5bde4
 
 
19d3e3d
 
8f5bde4
19d3e3d
8f5bde4
 
19d3e3d
8f5bde4
 
 
19d3e3d
 
8f5bde4
 
19d3e3d
8f5bde4
19d3e3d
 
 
 
 
 
 
 
 
 
 
8f5bde4
19d3e3d
 
 
 
8f5bde4
 
 
 
 
 
 
 
 
19d3e3d
8f5bde4
 
 
 
 
 
 
19d3e3d
8f5bde4
19d3e3d
8f5bde4
 
 
 
19d3e3d
8f5bde4
19d3e3d
 
8f5bde4
19d3e3d
 
 
 
 
 
 
 
 
 
 
 
 
 
8f5bde4
 
 
 
 
19d3e3d
8f5bde4
 
19d3e3d
 
 
8f5bde4
 
 
 
 
 
19d3e3d
8f5bde4
19d3e3d
8f5bde4
19d3e3d
 
 
 
 
 
 
 
8f5bde4
19d3e3d
8f5bde4
 
19d3e3d
 
8f5bde4
19d3e3d
8f5bde4
 
 
 
 
 
19d3e3d
8f5bde4
19d3e3d
8f5bde4
19d3e3d
 
8f5bde4
 
 
19d3e3d
8f5bde4
19d3e3d
8f5bde4
19d3e3d
8f5bde4
19d3e3d
8f5bde4
 
 
19d3e3d
8f5bde4
19d3e3d
8f5bde4
 
19d3e3d
8f5bde4
19d3e3d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8f5bde4
19d3e3d
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
import os
import json
import base64
import secrets
import numpy as np
import cv2
from deepface import DeepFace
from pymongo import MongoClient
import gradio as gr

# ========================
# MongoDB connection
# ========================
mongo_uri = "mongodb+srv://huyh01480_db_user:zxvAwzAhr8yk3lWe@cluster0.n8pboqq.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0"
client = MongoClient(mongo_uri)
db = client["userdb"]
users_col = db["users"]

# ========================
# Helper functions
# ========================
def convert_numpy(obj):
    if isinstance(obj, dict):
        return {k: convert_numpy(v) for k, v in obj.items()}
    elif isinstance(obj, list):
        return [convert_numpy(i) for i in obj]
    elif isinstance(obj, (np.float32, np.float64)):
        return float(obj)
    elif isinstance(obj, (np.int32, np.int64)):
        return int(obj)
    else:
        return obj

# ========================
# Internal API functions
# ========================
def register_internal(data):
    username = data.get('username')
    password = data.get('password')
    img_data = data.get('img')
    fullName = data.get('fullName')
    email = data.get('email')
    phone = data.get('phone')
    gender = data.get('gender')

    if not username or not password or not img_data:
        return {'error': 'username, password và ảnh là bắt buộc'}, 400

    img_str = img_data.split(",")[1] if "," in img_data else img_data
    try:
        decoded = base64.b64decode(img_str)
        nparr = np.frombuffer(decoded, np.uint8)
        img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
        if img is None:
            return {'error': 'Ảnh không thể đọc được'}, 400
    except Exception:
        return {'error': 'Ảnh không hợp lệ'}, 400

    try:
        DeepFace.extract_faces(img, enforce_detection=True)
    except Exception:
        return {'error': 'Ảnh không có khuôn mặt hợp lệ'}, 400

    if users_col.find_one({"userName": username}):
        return {'error': 'Tên người dùng đã tồn tại'}, 409

    user_info = {
        "userName": username,
        "password": password,
        "img": img_str,
        "fullName": fullName,
        "email": email,
        "phone": phone,
        "gender": gender,
    }
    users_col.insert_one(user_info)
    return {'message': 'Đăng ký thành công!', 'user': username}, 201


def login_internal(data):
    username = data.get('username')
    password = data.get('password')
    img_data = data.get('img')

    if not username or not password or not img_data:
        return {'error': 'username, password và ảnh là bắt buộc'}, 400

    img_str = img_data.split(",")[1] if "," in img_data else img_data
    user = users_col.find_one({"userName": username, "password": password})
    if not user:
        return {'error': 'Username hoặc password sai'}, 401

    try:
        nparr_input = np.frombuffer(base64.b64decode(img_str), np.uint8)
        img_input = cv2.imdecode(nparr_input, cv2.IMREAD_COLOR)
        nparr_db = np.frombuffer(base64.b64decode(user['img']), np.uint8)
        img_db = cv2.imdecode(nparr_db, cv2.IMREAD_COLOR)
        result = DeepFace.verify(img_input, img_db, enforce_detection=True)
    except Exception as e:
        return {'error': f'Lỗi khi nhận diện khuôn mặt: {e}'}, 400

    distance = result.get("distance", 1)
    similarity = max(0, (1 - distance)) * 100
    similarity = round(similarity, 2)

    if result['verified']:
        token = secrets.token_hex(16)
        user_info = {k: user[k] for k in ["userName", "fullName", "email", "phone", "gender", "img"]}
        return {'message': 'Login thành công!', 'token': token, 'similarity': similarity, 'user': user_info}, 200
    else:
        return {'error': 'Khuôn mặt không trùng khớp', 'similarity': similarity}, 401


def analyze_internal(data):
    img_data = data.get('img')
    if not img_data:
        return {'error': 'Ảnh là bắt buộc'}, 400
    img_str = img_data.split(",")[1] if "," in img_data else img_data
    try:
        nparr = np.frombuffer(base64.b64decode(img_str), np.uint8)
        img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
        result = DeepFace.analyze(img, actions=['age','gender','emotion','race'], enforce_detection=True)
        result = convert_numpy(result)
        return {'result': result}, 200
    except Exception as e:
        return {'error': f'Lỗi khi phân tích khuôn mặt: {e}'}, 400


def compare_internal(data):
    img1_data = data.get("img1")
    img2_data = data.get("img2")
    if not img1_data or not img2_data:
        return {'error': 'Cần 2 ảnh base64 để so sánh'}, 400
    try:
        nparr1 = np.frombuffer(base64.b64decode(img1_data.split(",")[1] if "," in img1_data else img1_data), np.uint8)
        img1 = cv2.imdecode(nparr1, cv2.IMREAD_COLOR)
        nparr2 = np.frombuffer(base64.b64decode(img2_data.split(",")[1] if "," in img2_data else img2_data), np.uint8)
        img2 = cv2.imdecode(nparr2, cv2.IMREAD_COLOR)
        result = DeepFace.verify(img1, img2, enforce_detection=True)
        distance = result.get("distance", 1)
        similarity = max(0, (1 - distance)) * 100
        similarity = round(similarity, 2)
        return {"verified": result.get("verified", False), "distance": distance, "similarity": similarity}, 200
    except Exception as e:
        return {'error': str(e)}, 500

# ========================
# Gradio wrapper
# ========================
def gradio_handler(json_str, action="login"):
    try:
        data = json.loads(json_str)
    except Exception:
        return json.dumps({'error': 'Invalid JSON input'})
    
    if action == "register":
        res, status = register_internal(data)
    elif action == "login":
        res, status = login_internal(data)
    elif action == "analyze":
        res, status = analyze_internal(data)
    elif action == "compare":
        res, status = compare_internal(data)
    else:
        res = {'error': 'Unknown action'}
    return json.dumps(res)


iface = gr.Interface(
    fn=gradio_handler,
    inputs=[gr.Textbox(label="JSON input"), gr.Dropdown(["register","login","analyze","compare"], label="Action")],
    outputs="textbox",
    live=False
)

iface.launch(server_name="0.0.0.0", server_port=int(os.environ.get("PORT", 7860)))