CoolFace
Apppublic

kazakiakayami/Weed-Detection-Computer-Vision-GC7

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes
app.py163 linesDownload Raw Back to src
1import os2os.environ["TF_USE_LEGACY_KERAS"] = "1"  # ← HARUS sebelum import tensorflow3 4import streamlit as st5import numpy as np6import tensorflow as tf7import cv28from PIL import Image9from tensorflow.keras.models import load_model10from tensorflow.keras.models import Model11from huggingface_hub import hf_hub_download12 13 14# ── Page Config ───────────────────────────────────────────────────15st.set_page_config(16    page_title="Weed Detector",17    page_icon="🌿",18    layout="centered"19)20 21# ── Load Model ────────────────────────────────────────────────────22@st.cache_resource   # ← cache supaya model tidak reload tiap interaksi23def load_inference_model():24    from keras.applications.vgg16 import VGG1625    26    # Rebuild arsitektur persis sama seperti di notebook27    pretrained_model_vgg16 = VGG16(28        weights=None,                        # tidak load weights imagenet29        include_top=False,30        input_shape=(224, 224, 3)31    )32    pretrained_model_vgg16.trainable = False33    34    model = tf.keras.Sequential([35        pretrained_model_vgg16,36        tf.keras.layers.Flatten(),37        tf.keras.layers.Dense(512, activation='relu'),38        tf.keras.layers.Dense(1, activation='sigmoid')39    ])40    41    model.compile(42        loss='binary_crossentropy',43        optimizer='adam',44        metrics=['accuracy']45    )46    47    # Load weights saja dari file .h548    model_path = hf_hub_download(49        repo_id="kazakiakayami/Computer-Vision-GC7",50        filename="best_model_weights.weights.h5"51    )52    model.load_weights(model_path)53    54    return model55    56# ── Helper Functions ──────────────────────────────────────────────57def preprocess_image(img, img_size=(224, 224)):58    img = img.convert('RGB')59    img = img.resize(img_size)60    img_array = np.array(img) / 255.061    img_array = np.expand_dims(img_array, axis=0)62    return img_array63 64def predict_flower(img, model, low_threshold=0.25, high_threshold=0.75):65    img_array = preprocess_image(img)66    prob = model.predict(img_array)[0][0]67 68    if prob <= low_threshold:69        class_name = 'Daisy'70        confidence = 1 - prob71        weed_status = 'Weed'72    elif prob >= high_threshold:73        class_name = 'Dandelion'74        confidence = prob75        weed_status = 'Weed'76    else:77        class_name = 'Unknown'78        confidence = None79        weed_status = 'Not a Weed'80 81    return class_name, round(float(confidence), 4) if confidence else None, weed_status82 83def make_gradcam(img, model):84    vgg16_layer  = model.get_layer('vgg16')85    dense_layer  = model.get_layer('dense')86    dense1_layer = model.get_layer('dense_1')87 88    grad_model = Model(89        inputs=vgg16_layer.input,90        outputs=[91            vgg16_layer.get_layer('block5_conv3').output,92            vgg16_layer.output93        ]94    )95 96    img_array  = preprocess_image(img)97    img_tensor = tf.cast(img_array, tf.float32)98 99    with tf.GradientTape() as tape:100        conv_outputs, vgg_out = grad_model(img_tensor)101        tape.watch(conv_outputs)102        x             = tf.reshape(vgg_out, [tf.shape(vgg_out)[0], -1])103        x             = dense_layer(x)104        predictions   = dense1_layer(x)105        pred_index    = tf.argmax(predictions[0])106        class_channel = predictions[:, pred_index]107 108    grads        = tape.gradient(class_channel, conv_outputs)109    pooled_grads = tf.reduce_mean(grads, axis=(0, 1, 2))110    conv_out     = conv_outputs[0]111    heatmap      = conv_out @ pooled_grads[..., tf.newaxis]112    heatmap      = tf.squeeze(heatmap)113    heatmap      = tf.maximum(heatmap, 0)114    heatmap      = heatmap / (tf.math.reduce_max(heatmap) + 1e-8)115    heatmap      = heatmap.numpy()116 117    # Overlay ke gambar asli118    img_cv          = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)119    heatmap_resized = cv2.resize(heatmap, (img_cv.shape[1], img_cv.shape[0]))120    heatmap_colored = cv2.applyColorMap(np.uint8(255 * heatmap_resized), cv2.COLORMAP_JET)121    superimposed    = cv2.addWeighted(img_cv, 0.6, heatmap_colored, 0.4, 0)122    superimposed    = cv2.cvtColor(superimposed, cv2.COLOR_BGR2RGB)123 124    return superimposed125 126# ── UI ────────────────────────────────────────────────────────────127st.title("🌿 Weed Detector")128st.write("Upload a flower image to detect whether it is a weed or not.")129st.markdown("---")130 131model = load_inference_model()132uploaded_file = st.file_uploader(133    "Choose a flower image",134    type=["jpg", "jpeg", "png"]135)136 137if uploaded_file is not None:138    img = Image.open(uploaded_file)139 140    with st.spinner("Analyzing image..."):141        class_name, confidence, weed_status = predict_flower(img, model)142        gradcam_img = make_gradcam(img, model)143 144    # ── Result ────────────────────────────────────────────────────145    st.markdown("---")146 147    col1, col2 = st.columns(2)148    with col1:149        st.subheader("Original Image")150        st.image(img, use_container_width=True)151    with col2:152        st.subheader("Grad-CAM Attention")153        st.image(gradcam_img, use_container_width=True)154 155    st.markdown("---")156 157    # Prediction result158    conf_text = f"{confidence * 100:.2f}%" if confidence else "N/A"159 160    if weed_status == 'Not a Weed ✅':161        st.success(f"**Predicted:** {class_name}  |  **Confidence:** {conf_text}  |  **Status:** {weed_status}")162    else:163        st.error(f"**Predicted:** {class_name}  |  **Confidence:** {conf_text}  |  **Status:** {weed_status}")