from flask import Flask, request, jsonify, render_template, redirect, url_for from keras.models import load_model from PIL import Image from keras.preprocessing import image as keras_image from PIL import Image import numpy as np from datetime import datetime import io import cv2 from werkzeug.utils import secure_filename from PIL import ImageOps import os app = Flask(__name__) # Muat model dari file .h5 model = load_model('model/klasifikasi-Parkinson-93.13.h5') UPLOAD_FOLDER = 'static/upload/' app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif', 'tiff', 'webp', 'jfif'} MIN_FILE_SIZE_KB = 20 MAX_FILE_SIZE_MB = 5 def allowed_file(filename): return ( '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS and request.content_length >= MIN_FILE_SIZE_KB * 1024 and request.content_length <= MAX_FILE_SIZE_MB * 1024 * 1024 ) @app.route('/', methods=['GET', 'POST']) def home(): return render_template('home.html', judul='Home') @app.route('/informasi/', methods=['GET', 'POST']) def informasi(): return render_template('informasi.html', judul='Informasi') @app.route('/klasifikasi', methods=['GET', 'POST']) def klasifikasi(): return render_template('klasifikasi.html', judul='Klasifikasi') @app.route('/submit', methods=['POST']) def predict(): if 'file' not in request.files: resp = jsonify({'message': 'No image in the request'}) resp.status_code = 400 return resp files = request.files.getlist('file') filename = "temp_image.png" errors = {} success = False for file in files: if file and allowed_file(file.filename): file.save(os.path.join('static/upload/', filename)) success = True elif file and not allowed_file(file.filename): errors["message"] = 'File size of {} exceeds the maximum allowed size of {} MB or below the minimum allowed size of {} KB'.format(file.filename, MAX_FILE_SIZE_MB, MIN_FILE_SIZE_KB) success = False if not success: resp = jsonify(errors) resp.status_code = 400 return resp img_url = os.path.join(app.config['UPLOAD_FOLDER'], filename) img = Image.open(img_url).convert('RGB') # Convert image to numpy array img_array = np.array(img) # Preprocessing image using OpenCV blur = cv2.GaussianBlur(img_array, (5, 5), 0) gray = cv2.cvtColor(blur, cv2.COLOR_BGR2GRAY) kernel = np.ones((3, 3), np.uint8) edges = cv2.erode(gray, kernel, iterations=1) _, imfill = cv2.threshold(edges, 220, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) imgResize = cv2.resize(imfill, (224, 224)) # Save preprocessed image # now = datetime.now() # predict_image_path = 'static/upload/' + now.strftime("%d%m%y-%H%M%S") + ".png" predict_image_path = 'static/upload/process_image.png' cv2.imwrite(predict_image_path, imgResize) img.close() img = keras_image.load_img(predict_image_path, target_size=(224, 224, 3)) x = keras_image.img_to_array(img) x = x / 127.5 - 1 x = np.expand_dims(x, axis=0) images = np.vstack([x]) prediction_tremor = model.predict(images) class_names = {0: 'non tremor', 1: 'tremor'} predicted_class_index = np.argmax(prediction_tremor) predicted_class_name = class_names[predicted_class_index] if predicted_class_index == 0: saran = "Stay healthy and exercise often, avoid alcohol-containing drinks" else: saran = "Immediately consult a Neurologist for further treatment." predict_image_path = 'static/upload/process_image.png' return render_template("klasifikasi.html", img_path=img_url, predictiontremor=predicted_class_name, confidencetremor='{:.2%}'.format(np.max(prediction_tremor)), saran=saran, predict_image_path=predict_image_path) @app.route('/refresh', methods=['GET', 'POST']) def refresh(): return redirect(url_for('klasifikasi')) if __name__=='__main__': app.run(debug=True)