import time import os import cv2 import numpy as np import mediapipe as mp import tensorflow as tf from flask import Flask, request, jsonify from flask_cors import CORS app = Flask(__name__) CORS(app) # Load model dari folder yang sama MODEL_PATH = "best_sibi_landmark.keras" print("[INFO] Memuat model Keras...") model = tf.keras.models.load_model(MODEL_PATH) classes = list("ABCDEFGHIJKLMNOPQRSTUVWXYZ") mp_hands = mp.solutions.hands hands = mp_hands.Hands(static_image_mode=True, max_num_hands=2, min_detection_confidence=0.5) def normalize(points): points = np.array(points) wrist = points[0] points[:, 0] -= wrist[0] points[:, 1] -= wrist[1] points[:, 2] -= wrist[2] return points.flatten() @app.route('/predict', methods=['POST']) def predict(): # Catat waktu mulai dari awal request masuk start_time = time.time() try: file = request.files['image'] npimg = np.frombuffer(file.read(), np.uint8) img = cv2.imdecode(npimg, cv2.IMREAD_COLOR) rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) result = hands.process(rgb) # Hitung durasi sementara jika tangan tidak terdeteksi end_time = time.time() processing_time = round((end_time - start_time) * 1000) if not result.multi_hand_landmarks: return jsonify({ "status": "error", "message": "Tangan tidak terdeteksi!", "latency": f"{processing_time} ms" }) left = [0] * 63 right = [0] * 63 for idx, hand in enumerate(result.multi_hand_landmarks): pts = [[lm.x, lm.y, lm.z] for lm in hand.landmark] pts = normalize(pts) hand_type = result.multi_handedness[idx].classification[0].label if hand_type == "Left": left = pts.tolist() else: right = pts.tolist() feature = np.array(right + left, dtype=np.float32).reshape(1, 126, 1) pred = model.predict(feature, verbose=0)[0] best_idx = np.argmax(pred) # Hitung total waktu proses sampai prediksi selesai end_time = time.time() processing_time = round((end_time - start_time) * 1000) return jsonify({ "status": "success", "letter": classes[best_idx], "confidence": f"{pred[best_idx] * 100:.2f}%", "latency": f"{processing_time} ms" }) except Exception as e: end_time = time.time() processing_time = round((end_time - start_time) * 1000) return jsonify({ "status": "error", "message": str(e), "latency": f"{processing_time} ms" }) if __name__ == '__main__': app.run(port=5000, debug=True)