from flask import Flask, render_template, request, redirect, url_for, jsonify import os import base64 import tensorflow as tf from tensorflow import keras from keras import preprocessing import numpy as np import cv2 from werkzeug.utils import secure_filename import time app = Flask(__name__) app.config["UPLOAD_FOLDER"] = "static/uploads/" # folder static/uploads if not os.path.exists(app.config["UPLOAD_FOLDER"]): os.makedirs(app.config["UPLOAD_FOLDER"]) # Load model Hard Cascade Classifier tomato_cascade = cv2.CascadeClassifier("model/tomato_classifier.xml") # Load kedua model klasifikasi #model_ripe = keras.models.load_model("model/CNN MobileNetV2-epochs10new-100.0.h5") #model_fresh = keras.models.load_model("model/CNN MobileNetV2-epochs10kesegaran-99.66.h5") modl_newgen = keras.models.load_model("model/CNN MobileNetV2-epochs5newgen-99.41.h5") # Fungsi deteksi tomat def is_tomato(img_path): """Deteksi apakah gambar mengandung tomat atau tidak""" img = cv2.imread(img_path) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) tomatoes = tomato_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30)) return len(tomatoes) > 0 # Fungsi prediksi gambar def predict_image(img_path, model, class_names): img = preprocessing.image.load_img(img_path, target_size=(224, 224)) img_array = preprocessing.image.img_to_array(img) img_array = np.expand_dims(img_array, axis=0) img_array /= 255.0 predictions = model.predict(img_array) result = np.argmax(predictions, axis=1) confidence = int(np.max(predictions) * 100) return class_names[result[0]], confidence @app.route("/") def index(): return render_template("index.html") @app.route("/upload", methods=["GET", "POST"]) def upload(): if request.method == "POST": # Proses file unggahan if 'file' not in request.files: return render_template("upload.html", error="Tidak ada file yang dipilih.") file = request.files['file'] if file.filename == '': return render_template("upload.html", error="Nama file kosong. Silakan pilih file lain.") if file: filename = secure_filename(file.filename) filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename) file.save(filepath) # Validasi gambar menggunakan Hard Cascade if not is_tomato(filepath): return render_template("upload.html", error="Gambar yang diunggah bukan tomat. Harap unggah gambar tomat.") # Simpan path gambar di sesi sementara untuk ditampilkan di halaman hasil return redirect(url_for("predict", img_path=filename)) return render_template("upload.html") @app.route("/predict", methods=["GET", "POST"]) def predict(): if request.method == "POST": # Tangani data gambar dari kamera data = request.get_json() if data and "image" in data: # Decode Base64 menjadi file gambar image_data = data["image"].split(",")[1] image_bytes = base64.b64decode(image_data) filename = f"camera_{int(time.time())}.png" filepath = os.path.join(app.config["UPLOAD_FOLDER"], filename) # Simpan gambar ke folder uploads with open(filepath, "wb") as f: f.write(image_bytes) # Validasi gambar menggunakan Hard Cascade if not is_tomato(filepath): return jsonify({"success": False, "error": "Gambar yang diambil bukan tomat. Harap ambil gambar tomat."}), 400 # Lakukan prediksi setelah validasi #class_names_ripe = ['Belum Matang', 'Matang'] #class_names_fresh = ['Busuk', 'Segar'] class_names_tomat = ['Matang Busuk', 'Matang Segar', 'Mentah Busuk', 'Mentah Segar'] # Prediksi kematangan #predicted_class_ripe, confidence_ripe = predict_image(filepath, model_ripe, class_names_ripe) # Prediksi kesegaran #predicted_class_fresh, confidence_fresh = predict_image(filepath, model_fresh, class_names_fresh) predicted_class_tomat, confidence_tomat = predict_image(filepath, modl_newgen, class_names_tomat) # Gabungkan hasil prediksi #predicted_class = f"{predicted_class_tomat}" #average_confidence = round((confidence_ripe + confidence_fresh) / 2, 2) # Kirim hasil prediksi sebagai respons JSON return jsonify({ "success": True, "filename": filename, "predicted_class": predicted_class_tomat, "confidence": confidence_tomat }) return jsonify({"success": False, "error": "No valid image data received"}), 400 # Tangani metode GET untuk menampilkan halaman prediksi img_path = request.args.get("img_path") if not img_path: return redirect(url_for("upload")) filepath = os.path.join(app.config["UPLOAD_FOLDER"], img_path) if not os.path.exists(filepath): return redirect(url_for("upload")) #class_names_ripe = ['Belum Matang', 'Matang'] #class_names_fresh = ['Busuk', 'Segar'] class_names_tomat = ['Matang Busuk', 'Matang Segar', 'Mentah Busuk', 'Mentah Segar'] # Prediksi kematangan #predicted_class_ripe, confidence_ripe = predict_image(filepath, model_ripe, class_names_ripe) # Prediksi kesegaran #predicted_class_fresh, confidence_fresh = predict_image(filepath, model_fresh, class_names_fresh) #predicted_class = f"{predicted_class_ripe} & {predicted_class_fresh}" #average_confidence = round((confidence_ripe + confidence_fresh) / 2, 2) predicted_class_tomat, confidence_tomat = predict_image(filepath, modl_newgen, class_names_tomat) local_time = time.localtime(time.time()) data_date = time.strftime("%d-%m-%Y", local_time) data_time = time.strftime("%H:%M:%S", local_time) return render_template( "predict.html", img_path=img_path, predicted_class=predicted_class_tomat, confidence=confidence_tomat, data_date=data_date, data_time=data_time ) @app.route("/more") def more(): return render_template("more.html") @app.route("/faq") def faq(): return render_template("faq.html") @app.route("/about") def about(): return render_template("about.html") if __name__ == "__main__": app.run(host="0.0.0.0", port=5000, debug=True)