import io import os from dotenv import load_dotenv import numpy as np from flask import Flask, jsonify, render_template, request, send_from_directory from PIL import Image import tensorflow as tf from tensorflow.keras.preprocessing import image from model import Conv2DBatchNMaxP, Conv2DModel from google import genai # Cara membuat file .env: # 1. Buat file bernama ".env" di folder proyek (sama dengan app.py). # 2. Tambahkan baris: GENAI_API_KEY=your_api_key_here # 3. Jangan commit .env ke repositori (tambahkan ke .gitignore). load_dotenv() GENAI_API_KEY = os.getenv('GENAI_API_KEY') if not GENAI_API_KEY: print('Peringatan: GENAI_API_KEY tidak ditemukan di environment') client = genai.Client(api_key=GENAI_API_KEY) CLASS_NAMES = [ 'Apple___Apple_scab', 'Apple___Black_rot', 'Apple___Cedar_apple_rust', 'Apple___healthy', 'Blueberry___healthy', 'Cherry_(including_sour)___Powdery_mildew', 'Cherry_(including_sour)___healthy', 'Corn_(maize)___Cercospora_leaf_spot Gray_leaf_spot', 'Corn_(maize)___Common_rust_', 'Corn_(maize)___Northern_Leaf_Blight', 'Corn_(maize)___healthy', 'Grape___Black_rot', 'Grape___Esca_(Black_Measles)', 'Grape___Leaf_blight_(Isariopsis_Leaf_Spot)', 'Grape___healthy', 'Orange___Haunglongbing_(Citrus_greening)', 'Peach___Bacterial_spot', 'Peach___healthy', 'Pepper,_bell___Bacterial_spot', 'Pepper,_bell___healthy', 'Potato___Early_blight', 'Potato___Late_blight', 'Potato___healthy', 'Raspberry___healthy', 'Soybean___healthy', 'Squash___Powdery_mildew', 'Strawberry___Leaf_scorch', 'Strawberry___healthy', 'Tomato___Bacterial_spot', 'Tomato___Early_blight', 'Tomato___Late_blight', 'Tomato___Leaf_Mold', 'Tomato___Septoria_leaf_spot', 'Tomato___Spider_mites Two-spotted_spider_mite', 'Tomato___Target_Spot', 'Tomato___Tomato_Yellow_Leaf_Curl_Virus', 'Tomato___Tomato_mosaic_virus', 'Tomato___healthy', 'test' ] BASE_DIR = os.path.dirname(os.path.abspath(__file__)) MODEL_PATH = os.path.join(BASE_DIR, 'model.keras') model = None try: model = tf.keras.models.load_model( MODEL_PATH, custom_objects={'Conv2DBatchNMaxP': Conv2DBatchNMaxP, 'Conv2DModel': Conv2DModel}, compile=False ) model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) print(f"Model loaded: {MODEL_PATH}") except Exception as e: print(f"Failed to load model: {e}") app = Flask(__name__) def preprocess_image(image_file, target_size=(150, 150)): img = Image.open(io.BytesIO(image_file.read())).convert('L').resize(target_size) img_array = image.img_to_array(img) img_array = np.expand_dims(img_array, axis=0) / 255.0 return img_array @app.route('/', methods=['GET']) def index(): try: return render_template('index.html') except Exception: return send_from_directory(BASE_DIR, 'index.html') @app.route('/predict', methods=['POST']) def predict(): if model is None: print(f"Model = {model}") return jsonify({'error': 'Model belum dimuat'}), 500 if 'file' not in request.files or request.files['file'].filename == '': return jsonify({'error': 'Tidak ada file gambar yang diunggah'}), 400 try: processed_image = preprocess_image(request.files['file']) predictions = model.predict(processed_image) idx = np.argmax(predictions, axis=1)[0] prompt = f"Tolong berikan penjelasan tentang penyakit tanaman {CLASS_NAMES[idx]}. Dan berikan solusinya" response = client.models.generate_content( model="gemini-2.5-flash", contents=prompt ) print(response.text) return jsonify({ 'predicted_class': CLASS_NAMES[idx], 'confidence': f"{predictions[0][idx] * 100:.2f}%", '':response.text }) except Exception as e: print(f"Error: {e}") return jsonify({'error': f'Gagal memproses gambar: {str(e)}'}), 500 if __name__ == '__main__': # Wajib host 0.0.0.0 dan port 7860 untuk Hugging Face Space app.run(host='0.0.0.0', port=7860, debug=False)