| from flask import Flask, request, jsonify |
| from flask_cors import CORS |
| import tensorflow as tf |
| from tensorflow.keras.preprocessing.image import load_img, img_to_array |
| from PIL import Image |
| import numpy as np |
| import os |
| import uuid |
|
|
| app = Flask(__name__) |
| |
| |
| origins = [ |
| "https://5173-idx-skripsigit-1741671480633.cluster-3g4scxt2njdd6uovkqyfcabgo6.cloudworkstations.dev", |
| "http://localhost:5173", |
| ] |
| app.config['UPLOAD_FOLDER'] = 'static/uploads' |
| CORS(app, resources={r"/api/*": { |
| "origins": origins, |
| "methods": ["GET", "POST"], |
| "allow_headers": ["Content-Type", "Authorization"] |
| }}) |
| os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True) |
| |
| MODEL_PATH = 'model/model_mobilenetv2.keras' |
|
|
| |
| try: |
| model = tf.keras.models.load_model(MODEL_PATH) |
| except Exception as e: |
| print(f"Error loading model: {e}") |
| model = None |
|
|
| |
| IMG_SIZE = (256, 256) |
| print(tf.__version__) |
| @app.route('/api', methods=['GET', 'POST']) |
| def predict(): |
| if request.method == 'GET': |
| return jsonify({'message': 'Hello from Flask!'}) |
|
|
| if model is None: |
| return jsonify({'error': 'Model not loaded'}), 500 |
|
|
| if 'image' not in request.files: |
| return jsonify({'error': 'No image provided'}), 400 |
|
|
| if request.method == 'POST': |
| file = request.files['image'] |
| if not file.filename: |
| return jsonify({'error': 'No file selected'}), 400 |
| |
| filename = f"{uuid.uuid4().hex}_{file.filename}" |
| filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename) |
| file.save(filepath) |
|
|
| img = Image.open(filepath).convert('RGB') |
| img = load_img(filepath, target_size=IMG_SIZE) |
| img_array = img_to_array(img) |
| img_array = np.expand_dims(img_array, axis=0) / 255.0 |
| |
| |
| |
|
|
| predictions = model.predict(img_array) |
| predicted_class = np.argmax(predictions[0]).tolist() |
| probabilities = predictions[0].tolist() |
|
|
| class_labels = ['Buah Busuk', 'Buah Sehat', 'Daun Bercak Coklat', 'Daun Bercak Hitam', 'Daun Bercak Merah', 'Daun Bercak Putih', 'Daun Berlubang', 'Daun Normal'] |
| result = { |
| 'predicted_class': class_labels[predicted_class], |
| 'probabilities': probabilities, |
| 'class_index': predicted_class |
| } |
|
|
| return jsonify(result) |
| |
| |
|
|
| if __name__ == '__main__': |
| app.run(host='0.0.0.0', port=8080, debug=True) |