Spaces:
Sleeping
Sleeping
File size: 6,631 Bytes
d68952e 91075e7 d68952e 24b2f85 6087c55 91075e7 6087c55 d68952e 6087c55 91075e7 24b2f85 91075e7 24b2f85 91075e7 d68952e 6087c55 91075e7 d68952e 91075e7 d68952e 6087c55 d68952e 91075e7 d68952e 91075e7 d68952e 91075e7 d68952e 6087c55 d68952e 6087c55 d68952e 6087c55 d68952e 6087c55 d68952e 91075e7 d68952e 6087c55 d68952e 6087c55 d68952e 6087c55 d68952e 6087c55 d68952e 6087c55 d68952e 91075e7 | 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 178 179 180 | import os
import gc
import time
import shutil
import logging
import psutil
from fastapi import FastAPI, UploadFile, File, Form
from fastapi.responses import JSONResponse
from deepface import DeepFace
# Setup Logging
logging.basicConfig(level=logging.INFO, format="%(message)s")
logger = logging.getLogger("AIMonitor")
app = FastAPI()
# ----------------------------------------------------------------------------
# Helper Pengukur RAM
# ----------------------------------------------------------------------------
def get_mem():
ram = psutil.virtual_memory()
proc = psutil.Process(os.getpid())
app_gb = proc.memory_info().rss / (1024 ** 3)
free_gb = ram.available / (1024 ** 3)
return app_gb, free_gb
# Path database lokal (bawaan lama)
DB_PATH = "/app/face_db"
if not os.path.exists(DB_PATH):
os.makedirs(DB_PATH)
# ============================================================================
# MIDDLEWARE RAM TRACKER
# ============================================================================
@app.middleware("http")
async def ram_tracker_middleware(request, call_next):
# Abaikan logging jika hanya healthcheck root "/"
if request.url.path == "/":
return await call_next(request)
start_time = time.time()
ram_awal, free_awal = get_mem()
# Catat log saat request mulai masuk
print("\n" + "-" * 70)
logger.info(f"[HIT MASUK] {request.method} {request.url.path}")
logger.info(f" |-- RAM Awal App : {ram_awal:.2f} GB")
logger.info(f" |-- Sisa RAM Server: {free_awal:.2f} GB")
logger.info(f" |-- Status : Sedang memproses AI...")
# Jalankan kode AI
response = await call_next(request)
# Catat durasi dan bersihkan RAM sementara (Garbage Collector)
duration_ms = (time.time() - start_time) * 1000
ram_proses, _ = get_mem()
gc.collect() # Langsung lepaskan RAM sementara
ram_akhir, free_akhir = get_mem()
# Cetak alur naik dan turunnya RAM
logger.info(f"[SELESAI] Status: {response.status_code} | Durasi: {duration_ms:.0f} ms")
logger.info(
f"[SIKLUS RAM] {ram_awal:.2f} GB --(naik proses)--> {ram_proses:.2f} GB --(turun cooldown)--> {ram_akhir:.2f} GB"
)
logger.info(f"[SISA RAM SERVER] {free_akhir:.2f} GB")
print("-" * 70 + "\n")
return response
# ============================================================================
# CODINGAN MODEL AI
# ============================================================================
@app.get("/")
async def root():
ram_app, ram_free = get_mem()
return {
"status": "AI Face Recognition System is Running",
"app_ram_gb": round(ram_app, 2),
"available_ram_gb": round(ram_free, 2)
}
@app.post("/api/represent")
async def represent_face(
image: UploadFile = File(...),
name: str = Form(None),
detector_backend: str = Form("retinaface")
):
"""Endpoint stateless untuk mengekstrak vektor embedding wajah (512 dimensi untuk Facenet512)"""
temp_path = f"temp_{int(time.time()*1000)}.jpg"
try:
if name:
logger.info(f" |-- Subjek: {name} (detector: {detector_backend})")
# Simpan gambar secara temporer
with open(temp_path, "wb") as buffer:
shutil.copyfileobj(image.file, buffer)
# Hitung representasi vektor wajah
representations = DeepFace.represent(
img_path=temp_path,
model_name="Facenet512",
detector_backend=detector_backend,
enforce_detection=False
)
if len(representations) > 0:
embedding = representations[0]["embedding"]
return {"success": True, "embedding": embedding}
return JSONResponse(status_code=400, content={"success": False, "error": "Wajah tidak dapat dideteksi."})
except Exception as e:
logger.error(f" [ERROR] Error in represent: {str(e)}")
return JSONResponse(status_code=500, content={"success": False, "error": str(e)})
finally:
if os.path.exists(temp_path):
os.remove(temp_path)
@app.post("/api/register")
async def register_face(name: str = Form(...), image: UploadFile = File(...)):
try:
clean_name = name.replace(" ", "_").lower()
img_path = os.path.join(DB_PATH, f"{clean_name}.jpg")
with open(img_path, "wb") as buffer:
shutil.copyfileobj(image.file, buffer)
for file in os.listdir(DB_PATH):
if file.endswith(".pkl"):
os.remove(os.path.join(DB_PATH, file))
return {"success": True, "message": f"Wajah {name} berhasil didaftarkan."}
except Exception as e:
return JSONResponse(status_code=500, content={"success": False, "error": str(e)})
@app.post("/api/recognize")
async def recognize_face(image: UploadFile = File(...)):
temp_path = f"temp_scan_{int(time.time()*1000)}.jpg"
try:
with open(temp_path, "wb") as buffer:
shutil.copyfileobj(image.file, buffer)
has_images = any(f.lower().endswith(('.jpg', '.jpeg', '.png')) for f in os.listdir(DB_PATH))
if not has_images:
return {"success": False, "name": "Tidak Dikenali"}
dfs = DeepFace.find(
img_path=temp_path,
db_path=DB_PATH,
model_name="VGG-Face",
enforce_detection=False,
silent=True
)
if len(dfs) > 0 and not dfs[0].empty:
result_path = dfs[0]["identity"][0]
name = os.path.basename(result_path).replace(".jpg", "").replace("_", " ").title()
return {"success": True, "name": name}
return {"success": False, "name": "Tidak Dikenali"}
except Exception as e:
return JSONResponse(status_code=500, content={"success": False, "error": str(e)})
finally:
if os.path.exists(temp_path):
os.remove(temp_path)
@app.post("/api/reset-ai")
async def reset_ai():
try:
for filename in os.listdir(DB_PATH):
file_path = os.path.join(DB_PATH, filename)
if os.path.isfile(file_path) or os.path.islink(file_path):
os.unlink(file_path)
elif os.path.isdir(file_path):
shutil.rmtree(file_path)
return {"success": True, "message": "Database AI lokal dibersihkan."}
except Exception as e:
return JSONResponse(status_code=500, content={"success": False, "error": str(e)})
|