MIF_E31230820/python_ai/app.py

581 lines
6.7 KiB
Python

from flask import Flask, request, jsonify
from flask_cors import CORS
import os
from datetime import datetime
import numpy as np
from PIL import Image
from tensorflow.keras.models import load_model
# ==========================================
# FLASK CONFIG
# ==========================================
app = Flask(__name__)
CORS(app)
# ==========================================
# FOLDER & MODEL
# ==========================================
UPLOAD_FOLDER = os.path.join(
os.path.dirname(__file__),
'uploads'
)
os.makedirs(
UPLOAD_FOLDER,
exist_ok=True
)
MODEL_PATH = os.path.join(
os.path.dirname(__file__),
'model_padi.h5'
)
# ==========================================
# CLASS SESUAI TRAINING MODEL
# ==========================================
CLASS_NAMES = [
'Healthy',
'Blast',
'Blight',
'Non-Padi',
'Tungro'
]
# ==========================================
# DESKRIPSI HASIL
# ==========================================
DESCRIPTIONS = {
'Healthy': {
'deskripsi':
'Daun padi dalam kondisi sehat.',
'solusi':
'Pertahankan pemupukan, pengairan, dan perawatan tanaman secara rutin.'
},
'Blast': {
'deskripsi':
'Blast merupakan penyakit daun padi yang disebabkan oleh jamur Pyricularia oryzae.',
'solusi':
'Gunakan fungisida dan varietas padi yang tahan terhadap penyakit blast.'
},
'Blight': {
'deskripsi':
'Blight merupakan penyakit hawar daun yang disebabkan oleh bakteri.',
'solusi':
'Gunakan benih sehat dan lakukan sanitasi lahan.'
},
'Tungro': {
'deskripsi':
'Tungro merupakan penyakit virus yang ditularkan oleh wereng hijau.',
'solusi':
'Lakukan pengendalian wereng dan gunakan varietas tahan tungro.'
},
'Non-Padi': {
'deskripsi':
'Gambar yang diunggah bukan daun padi.',
'solusi':
'Silakan upload gambar daun padi yang jelas.'
}
}
# ==========================================
# LOAD MODEL
# ==========================================
model = None
try:
model = load_model(MODEL_PATH)
print("Model berhasil dimuat")
print(
"Input Shape :",
model.input_shape
)
print(
"Output Shape:",
model.output_shape
)
except Exception as e:
print(
"Gagal load model:",
e
)
# ==========================================
# PREPROCESS IMAGE
# ==========================================
def preprocess_image(path):
image = Image.open(path)
image = image.convert('RGB')
image = image.resize(
(224,224)
)
image_array = np.array(image)
image_array = (
image_array.astype('float32')
/
255.0
)
image_array = np.expand_dims(
image_array,
axis=0
)
return image_array
# ==========================================
# TEST API
# ==========================================
@app.route('/')
def home():
return jsonify({
"status":
"API Klasifikasi Penyakit Daun Padi Aktif"
})
# ==========================================
# PREDIKSI
# ==========================================
@app.route(
'/prediksi',
methods=['POST']
)
def prediksi():
if 'gambar' not in request.files:
return jsonify({
"error":
"Tidak ada gambar dikirim"
}),400
file = request.files['gambar']
if file.filename == '':
return jsonify({
"error":
"File kosong"
}),400
filename = (
datetime.now()
.strftime('%Y%m%d%H%M%S_')
+
file.filename
)
filepath = os.path.join(
UPLOAD_FOLDER,
filename
)
file.save(filepath)
print("\n====================")
print(
"Gambar diterima:",
filename
)
if model is None:
return jsonify({
"error":
"Model tidak tersedia"
}),500
try:
# preprocessing
image_array = preprocess_image(filepath)
# prediksi
predictions = model.predict(
image_array,
verbose=0
)
predicted_index = int(
np.argmax(predictions[0])
)
confidence = float(
np.max(predictions[0])
)
confidence_percent = confidence * 100
label = CLASS_NAMES[
predicted_index
]
print("\nHASIL PREDIKSI")
for i,nama in enumerate(CLASS_NAMES):
print(
nama,
":",
round(
predictions[0][i]*100,
2
),
"%"
)
print(
"HASIL AKHIR:",
label
)
print(
"CONFIDENCE:",
confidence_percent
)
# ==============================
# FILTER GAMBAR TIDAK JELAS
# ==============================
if confidence_percent < 60:
return jsonify({
"error":
"Gambar tidak dikenali. Pastikan gambar daun padi."
}),400
# ==============================
# TOLAK NON PADI
# ==============================
if label == "Non-Padi":
return jsonify({
"error":
"Gambar bukan daun padi. Silakan upload daun padi."
}),400
all_predictions = {}
for i in range(len(CLASS_NAMES)):
all_predictions[
CLASS_NAMES[i]
] = round(
float(
predictions[0][i]*100
),
2
)
detail = DESCRIPTIONS[label]
return jsonify({
"penyakit":
label,
"confidence":
f"{confidence_percent:.2f}%",
"all_predictions":
all_predictions,
"deskripsi":
detail['deskripsi'],
"solusi":
detail['solusi']
})
except Exception as e:
print(
"ERROR:",
e
)
return jsonify({
"error":
str(e)
}),500
# ==========================================
# RUN FLASK
# ==========================================
if __name__ == '__main__':
print("="*50)
print(
"Klasifikasi Penyakit Daun Padi"
)
print("="*50)
app.run(
host='127.0.0.1',
port=5000,
debug=False
)