# -*- coding: utf-8 -*- """FastAPI.ipynb Automatically generated by Colab. Original file is located at https://colab.research.google.com/drive/1aRYWOGz0S2N2oVN33c0uv3PzGsoWc02F """ import io import cv2 import json import numpy as np import tensorflow as tf from fastapi import FastAPI, File, UploadFile, HTTPException from fastapi.responses import JSONResponse from fastapi.middleware.cors import CORSMiddleware app = FastAPI(title="NusantaraLens API", description="API Klasifikasi Gambar Budaya Indonesia") # 1. SETUP CORS app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # 2. BATASAN UKURAN FILE MAX_FILE_SIZE = 5 * 1024 * 1024 # Load Model MODEL_PATH = "model_nusantara_lens.keras" try: model = tf.keras.models.load_model(MODEL_PATH) print("Model berhasil dimuat!") except Exception as e: print(f"Gagal memuat model: {e}") model = None LABEL_MAP = {0: "Kuliner", 1: "Lagu_Daerah", 2: "Pahlawan", 3: "Tarian"} # 3. LOAD DATA JSON try: with open("/content/Data deksripsi budaya.json", "r", encoding="utf-8") as f: DATA_BUDAYA = json.load(f) print("File Data deksripsi budaya.json berhasil dimuat!") except Exception as e: print("File Data deksripsi budaya.json tidak ditemukan. Pastikan sudah dibuat di Colab!") DATA_BUDAYA = [] def preprocess_image_consistent(img): h, w, _ = img.shape min_dim = min(h, w) start_x = w // 2 - min_dim // 2 start_y = h // 2 - min_dim // 2 cropped_img = img[start_y:start_y+min_dim, start_x:start_x+min_dim] img_resized = cv2.resize(cropped_img, (224, 224), interpolation=cv2.INTER_AREA) img_array = img_resized.astype("float32") / 255.0 return np.expand_dims(img_array, axis=0) @app.get("/") def read_root(): return {"message": "Server NusantaraLens API aktif dan berjalan."} @app.post("/predict") async def predict_image(file: UploadFile = File(...)): if model is None: raise HTTPException(status_code=500, detail="Model AI belum siap di server.") # Proteksi 1: Cek Format File if not file.content_type.startswith("image/"): raise HTTPException(status_code=400, detail="File harus berupa gambar (JPEG/PNG).") # Proteksi 2: Baca isi gambar sekaligus cek ukuran file-nya contents = await file.read() if len(contents) > MAX_FILE_SIZE: raise HTTPException(status_code=413, detail="Ukuran gambar terlalu besar! Maksimal 5MB.") try: nparr = np.frombuffer(contents, np.uint8) img = cv2.imdecode(nparr, cv2.IMREAD_COLOR) if img is None: raise HTTPException(status_code=400, detail="Gambar rusak atau format tidak didukung.") img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img_batch = preprocess_image_consistent(img) predictions = model.predict(img_batch) predicted_class_index = int(np.argmax(predictions[0])) confidence = float(predictions[0][predicted_class_index]) kategori_hasil = LABEL_MAP.get(predicted_class_index, "Tidak diketahui") rekomendasi_budaya = [item for item in DATA_BUDAYA if item.get("Kategori") == kategori_hasil] return JSONResponse(content={ "status": "success", "kategori_tebakan_ai": kategori_hasil, "confidence_percentage": round(confidence * 100, 2), "jumlah_data_ditemukan": len(rekomendasi_budaya), "daftar_rekomendasi": rekomendasi_budaya }) except Exception as e: import traceback traceback.print_exc() # Perintah ini akan mencetak tulisan merah error aslinya ke Colab raise HTTPException(status_code=500, detail=f"Terjadi kesalahan pemrosesan: {str(e)}") from pyngrok import ngrok import nest_asyncio import uvicorn # 1. SETUP TOKEN NGROK (HAPUS TULISAN DI BAWAH DAN GANTI DENGAN TOKEN MAS) ngrok.set_auth_token("3ETJl4pAvTJnNSngeLUElXEJK0N_6H1mGVSiY3gvKKrNHCDKy") # 2. MENGIZINKAN ASYNC DI COLAB nest_asyncio.apply() # 3. MEMBUAT TUNNEL NGROK public_url = ngrok.connect(8000) print("==================================================================") print(f"BERHASIL! PUBLIC URL API: {public_url.public_url}") print("==================================================================") # 4. MENJALANKAN SERVER (Menggunakan variabel 'app' dari Cell 2) config = uvicorn.Config( app, host="0.0.0.0", port=8000 ) server = uvicorn.Server(config) await server.serve() from google.colab import files # 1. Teks isi dari requirements.txt isi_requirements = """fastapi uvicorn python-multipart numpy tensorflow-cpu opencv-python-headless """ # 2. Membuat file requirements.txt di dalam Colab with open("requirements.txt", "w") as f: f.write(isi_requirements) print("File requirements.txt berhasil dibuat!") # 3. Memicu download otomatis ke laptop files.download("requirements.txt") print("Sedang mendownload ke laptop, silakan cek folder Downloads mas...") from google.colab import files # 1. Teks instruksi untuk Railway isi_procfile = "web: uvicorn main:app --host 0.0.0.0 --port $PORT" # 2. Membuat file bernama Procfile (tanpa ekstensi apapun) with open("Procfile", "w") as f: f.write(isi_procfile) print("File Procfile berhasil dibuat!") # 3. Memicu download otomatis ke laptop files.download("Procfile") print("Sedang mendownload ke laptop, silakan cek folder Downloads...")