from fastapi import FastAPI, UploadFile, File import numpy as np import cv2 import tensorflow as tf from PIL import Image import io app = FastAPI() # Load model Keras model = tf.keras.models.load_model("lontara_model_finetuning.keras") @app.get("/") def home(): return {"message": "Aksara Lontara API is running"} def preprocess_image(image: np.ndarray): """ Melakukan segmentasi karakter menggunakan OpenCV """ # **1️⃣ Edge Detection (Canny)** edges = cv2.Canny(image, 50, 150) # **2️⃣ Morphological Cleaning** kernel = np.ones((3, 3), np.uint8) edges_cleaned = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel, iterations=2) # **3️⃣ Connected Component Analysis (CCA)** num_labels, labels, stats, _ = cv2.connectedComponentsWithStats(edges_cleaned, connectivity=8) # **4️⃣ Filter huruf berdasarkan area** min_area = 500 bounding_boxes = [] for i in range(1, num_labels): # Skip background x, y, w, h, area = stats[i] if area > min_area: bounding_boxes.append((x, y, w, h)) # **5️⃣ Urutkan huruf berdasarkan posisi X** bounding_boxes.sort(key=lambda b: b[0]) # **6️⃣ Gabungkan Bounding Box yang Berdekatan** merged_boxes = [] merge_threshold = 20 for i in range(len(bounding_boxes)): x, y, w, h = bounding_boxes[i] if merged_boxes and (x - (merged_boxes[-1][0] + merged_boxes[-1][2])) < merge_threshold: x_prev, y_prev, w_prev, h_prev = merged_boxes.pop() x_new = min(x_prev, x) y_new = min(y_prev, y) w_new = max(x_prev + w_prev, x + w) - x_new h_new = max(y_prev + h_prev, y + h) - y_new merged_boxes.append((x_new, y_new, w_new, h_new)) else: merged_boxes.append((x, y, w, h)) # **7️⃣ Potong dan proses karakter** segmented_chars = [] for (x, y, w, h) in merged_boxes: char_segment = image[y:y+h, x:x+w] char_segment = cv2.resize(char_segment, (128, 128), interpolation=cv2.INTER_AREA) segmented_chars.append(char_segment) return segmented_chars @app.post("/predict") async def predict(file: UploadFile = File(...)): # Baca gambar dari file upload image = Image.open(io.BytesIO(await file.read())).convert("L") image = np.array(image) # **Segmentasi huruf** segmented_chars = preprocess_image(image) # Jika tidak ada huruf terdeteksi if not segmented_chars: return {"prediction": "No characters detected"} # **Prediksi untuk setiap karakter** predictions = [] for char in segmented_chars: char_norm = np.array(char) / 255.0 # Normalisasi char_norm = char_norm.reshape(1, 128, 128, 1) # Reshape untuk model prediction = model.predict(char_norm) predicted_label = labels[np.argmax(prediction)] predictions.append(predicted_label) return {"predictions": predictions}