AtthalaricNero
Remove brightness normalization function and update preprocessing pipeline to directly use normalized image data
1590197
Raw
History Blame Contribute Delete
4.11 kB
import numpy as np
import cv2
import joblib
import base64
import io
from flask import Flask, request, render_template
from PIL import Image
from skimage.feature import local_binary_pattern
app = Flask(__name__)
try:
model = joblib.load("svm_fruit_model.pkl")
pca = joblib.load("pca_transformer.pkl")
except Exception as e:
print(f"Error loading model: {e}")
CLASS_NAMES = [
"Avocado",
"Avocado ripe",
"Banana Lady",
"Banana Red",
"Banana Yellow",
"Carambula",
"Cherimoya",
"Dates",
"Fig",
"Guava",
"Kaki",
"Kiwi",
"Lychee",
"Mango",
"Mango Red",
"Mangostan",
"Papaya",
"Pineapple",
"Pineapple Mini",
"Pomegranate",
"Quince",
"Rambutan",
"Salak",
]
def extract_color_histogram(img, bins=(8, 8, 8)):
hist = cv2.calcHist([img], [0, 1, 2], None, bins, [0, 256, 0, 256, 0, 256])
hist = cv2.normalize(hist, hist).flatten()
return hist
def extract_lbp_features(gray_img, P=8, R=1, method="uniform"):
lbp = local_binary_pattern(gray_img, P, R, method)
hist, _ = np.histogram(lbp.ravel(), bins=np.arange(0, P + 3), range=(0, P + 2))
hist = hist.astype("float")
hist /= hist.sum() + 1e-6
return hist
def preprocessing_pipeline(pil_img):
img = np.array(pil_img.convert('RGB'))
img = cv2.resize(img, (100, 100), interpolation=cv2.INTER_AREA)
img_float = img.astype(np.float32) / 255.0
img_uint8 = (img_float * 255).astype(np.uint8)
feat_color = extract_color_histogram(img_uint8)
img_gray = cv2.cvtColor(img_uint8, cv2.COLOR_RGB2GRAY)
feat_lbp = extract_lbp_features(img_gray)
combined = np.hstack([feat_color, feat_lbp])
combined = combined.reshape(1, -1)
final_features = pca.transform(combined)
return final_features
@app.route("/", methods=["GET", "POST"])
def index():
prediction_text = None
img_data = None
confidence = None
top_3_predictions = None
if request.method == "POST":
if "file" not in request.files:
return render_template("index.html", msg="Tidak ada file")
file = request.files["file"]
if file.filename == "":
return render_template("index.html", msg="Nama file kosong")
if file:
try:
image = Image.open(file.stream)
features = preprocessing_pipeline(image)
preprocessed_img = cv2.resize(np.array(image.convert('RGB')), (100, 100), interpolation=cv2.INTER_AREA)
preprocessed_pil = Image.fromarray(preprocessed_img)
img_io = io.BytesIO()
preprocessed_pil.save(img_io, "PNG")
encoded_img = base64.b64encode(img_io.getvalue()).decode("ascii")
img_data = f"data:image/png;base64, {encoded_img}"
pred_index = model.predict(features)[0]
prediction_text = CLASS_NAMES[int(pred_index)]
if hasattr(model, 'predict_proba'):
probabilities = model.predict_proba(features)[0]
confidence = float(probabilities[int(pred_index)]) * 100
top_3_indices = probabilities.argsort()[-3:][::-1]
top_3_predictions = [
{
'name': CLASS_NAMES[idx],
'probability': float(probabilities[idx]) * 100
}
for idx in top_3_indices
]
else:
confidence = None
top_3_predictions = None
except Exception as e:
prediction_text = f"Error: {str(e)}"
confidence = None
top_3_predictions = None
return render_template("index.html", prediction=prediction_text, img_data=img_data,
confidence=confidence, top_predictions=top_3_predictions)
if __name__ == "__main__":
app.run(debug=True, port=7860)