acne-api-hf / predict.py
ItsFarros's picture
Tambah info legalitas, interaksi obat, dan kategori kehamilan
e1d0bea verified
Raw
History Blame Contribute Delete
3.49 kB
import os
import base64
import cv2
import numpy as np
MODEL_DIR = os.path.join(os.path.dirname(__file__), "models")
MODEL_PATH = os.path.join(MODEL_DIR, "best.onnx")
_model = None
CLASS_NAMES = {0: "comedone", 1: "nodules", 2: "papules", 3: "pustules"}
CLASS_ID_TO_NAME = {0: "comedone", 1: "nodules", 2: "papules", 3: "pustules"}
CLASS_COLORS = {
"comedone": (0, 200, 255),
"nodules": (0, 0, 255),
"papules": (0, 165, 255),
"pustules": (255, 0, 0),
}
def get_model():
from ultralytics import YOLO
global _model
if _model is None:
_model = YOLO(MODEL_PATH)
return _model
def draw_annotations(image_bgr: np.ndarray, results) -> str:
"""Gambar bbox + label pada gambar, return sebagai base64 JPEG string."""
annotated = image_bgr.copy()
if results.boxes is not None and len(results.boxes) > 0:
boxes = results.boxes.xyxy.cpu().numpy()
confs = results.boxes.conf.cpu().numpy()
cls_ids = results.boxes.cls.cpu().numpy().astype(int)
for box, conf, cls_id in zip(boxes, confs, cls_ids):
cls_name = CLASS_ID_TO_NAME.get(cls_id, "unknown")
color = CLASS_COLORS.get(cls_name, (0, 255, 0))
x1, y1, x2, y2 = map(int, box)
cv2.rectangle(annotated, (x1, y1), (x2, y2), color, 2)
label = f"{cls_name} {conf:.2f}"
(tw, th), _ = cv2.getTextSize(label, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 1)
cv2.rectangle(annotated, (x1, y1 - th - 6), (x1 + tw + 4, y1), color, -1)
cv2.putText(annotated, label, (x1 + 2, y1 - 3),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)
_, buffer = cv2.imencode('.jpg', annotated, [cv2.IMWRITE_JPEG_QUALITY, 85])
return base64.b64encode(buffer).decode('utf-8')
def detect_acne(image_bgr: np.ndarray, conf_threshold: float = 0.05, iou_threshold: float = 0.35) -> dict:
"""
Deteksi jerawat pada gambar (numpy array BGR).
Return dict berisi list deteksi, ringkasan, dan gambar anotasi (base64).
"""
model = get_model()
if model is None:
return {
"detections": [],
"detected_classes": [],
"summary": {},
"total_detections": 0,
"model_loaded": False,
"annotated_image": None,
}
results = model.predict(
source=image_bgr,
conf=conf_threshold,
iou=iou_threshold,
verbose=False,
imgsz=640,
)[0]
detections = []
summary: dict[str, int] = {}
if results.boxes is not None and len(results.boxes) > 0:
for box, conf, cls_id in zip(
results.boxes.xyxy.tolist(),
results.boxes.conf.tolist(),
results.boxes.cls.tolist(),
):
cls_name = CLASS_ID_TO_NAME.get(int(cls_id), "unknown")
summary[cls_name] = summary.get(cls_name, 0) + 1
detections.append({
"class": cls_name,
"confidence": round(float(conf), 4),
"bbox_xyxy": [round(v, 4) for v in box],
})
annotated_b64 = draw_annotations(image_bgr, results)
return {
"detections": detections,
"detected_classes": list(summary.keys()),
"summary": summary,
"total_detections": len(detections),
"model_loaded": True,
"annotated_image": annotated_b64,
"conf_threshold": conf_threshold,
"iou_threshold": iou_threshold,
}