176 lines
6.4 KiB
Python
176 lines
6.4 KiB
Python
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)
|