| import os
|
| import pickle
|
|
|
| import numpy as np
|
| import streamlit as st
|
| import tensorflow as tf
|
| from PIL import Image
|
|
|
|
|
|
|
|
|
|
|
| st.set_page_config(
|
| page_title="German Traffic Sign Recognition",
|
| page_icon="🚗",
|
| layout="centered"
|
| )
|
|
|
|
|
|
|
|
|
|
|
|
|
| BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
|
| MODEL_PATH = os.path.join(BASE_DIR, "traffic_sign.h5")
|
| LABEL_PATH = os.path.join(BASE_DIR, "labels.pkl")
|
|
|
|
|
|
|
|
|
|
|
| @st.cache_resource
|
| def load_assets():
|
| model = tf.keras.models.load_model(MODEL_PATH)
|
|
|
| with open(LABEL_PATH, "rb") as file:
|
| label_dict = pickle.load(file)
|
|
|
| return model, label_dict
|
|
|
|
|
| model, label_dict = load_assets()
|
|
|
|
|
|
|
|
|
|
|
| input_shape = model.input_shape
|
|
|
| IMG_HEIGHT = input_shape[1]
|
| IMG_WIDTH = input_shape[2]
|
|
|
|
|
|
|
|
|
|
|
| def prepare_image(image):
|
| image = image.convert("RGB")
|
|
|
| resized_image = image.resize(
|
| (IMG_WIDTH, IMG_HEIGHT),
|
| Image.Resampling.LANCZOS
|
| )
|
|
|
| image_array = np.array(resized_image, dtype=np.float32)
|
| image_array = image_array / 255.0
|
| image_array = np.expand_dims(image_array, axis=0)
|
|
|
| return resized_image, image_array
|
|
|
|
|
|
|
|
|
|
|
| def get_label(class_id):
|
| if isinstance(label_dict, dict):
|
| return label_dict.get(class_id, f"Class {class_id}")
|
|
|
| return label_dict[class_id]
|
|
|
|
|
|
|
|
|
|
|
| st.markdown("""
|
| <style>
|
| .main-title {
|
| text-align: center;
|
| font-size: 38px;
|
| font-weight: 800;
|
| margin-bottom: 8px;
|
| }
|
|
|
| .sub-title {
|
| text-align: center;
|
| font-size: 16px;
|
| color: #6b7280;
|
| margin-bottom: 20px;
|
| }
|
|
|
| .result-card {
|
| padding: 22px;
|
| border-radius: 16px;
|
| text-align: center;
|
| font-size: 25px;
|
| font-weight: 800;
|
| background: #ecfdf5;
|
| border: 1px solid #86efac;
|
| color: #166534 !important;
|
| margin-top: 18px;
|
| margin-bottom: 18px;
|
| }
|
| </style>
|
| """, unsafe_allow_html=True)
|
|
|
| st.markdown(
|
| "<div class='main-title'>🚗 German Traffic Sign Classifier</div>",
|
| unsafe_allow_html=True
|
| )
|
|
|
| st.markdown(
|
| "<div class='sub-title'>Trafik levhası fotoğrafı çekin veya görsel yükleyin.</div>",
|
| unsafe_allow_html=True
|
| )
|
|
|
| st.info(
|
| "En doğru sonuç için görselde yalnızca trafik levhası görünmelidir. "
|
| "İnternetten alınan fotoğraflarda levha küçükse önce levhayı kırpıp yükleyin."
|
| )
|
|
|
| st.divider()
|
|
|
|
|
|
|
|
|
|
|
| camera_file = st.camera_input("Kameradan trafik levhası çek")
|
|
|
| uploaded_file = st.file_uploader(
|
| "Ya da bilgisayarından trafik levhası görseli yükle",
|
| type=["jpg", "jpeg", "png"]
|
| )
|
|
|
| target_file = camera_file if camera_file is not None else uploaded_file
|
|
|
|
|
|
|
|
|
|
|
| if target_file is not None:
|
| original_image = Image.open(target_file).convert("RGB")
|
|
|
| col1, col2 = st.columns(2)
|
|
|
| with col1:
|
| st.image(
|
| original_image,
|
| caption="Yüklenen Görsel",
|
| use_container_width=True
|
| )
|
|
|
| processed_image, model_input = prepare_image(original_image)
|
|
|
| with col2:
|
| st.image(
|
| processed_image,
|
| caption=f"Modelin Gördüğü Görsel ({IMG_WIDTH}x{IMG_HEIGHT})",
|
| use_container_width=True
|
| )
|
|
|
| with st.spinner("Trafik levhası analiz ediliyor..."):
|
| prediction = model.predict(model_input, verbose=0)[0]
|
|
|
| class_id = int(np.argmax(prediction))
|
| confidence = float(np.max(prediction) * 100)
|
|
|
| top_3_ids = np.argsort(prediction)[-3:][::-1]
|
|
|
| st.divider()
|
|
|
| confidence_threshold = 80
|
|
|
| if confidence < confidence_threshold:
|
| st.warning(
|
| f"Model bu görselden yeterince emin değil. Güven seviyesi: %{confidence:.2f}"
|
| )
|
|
|
| st.info(
|
| "Görsel trafik levhası olmayabilir veya levha fotoğrafta çok küçük kalmış olabilir. "
|
| "Levhanın yakın plan, net ve ortada olduğu bir görsel deneyin."
|
| )
|
| else:
|
| st.markdown(
|
| f"<div class='result-card'>Tahmin: {get_label(class_id)}</div>",
|
| unsafe_allow_html=True
|
| )
|
|
|
| st.write(f"**Güven Seviyesi:** %{confidence:.2f}")
|
|
|
| st.progress(int(confidence))
|
|
|
| st.subheader("En Güçlü 3 Tahmin")
|
|
|
| for rank, idx in enumerate(top_3_ids, start=1):
|
| label = get_label(int(idx))
|
| score = float(prediction[idx] * 100)
|
|
|
| st.write(
|
| f"{rank}. **{label}** — %{score:.2f}"
|
| )
|
|
|
| with st.expander("Teknik Bilgiler"):
|
| st.write(f"Model giriş boyutu: {model.input_shape}")
|
| st.write(f"Tahmin edilen sınıf numarası: {class_id}")
|
| st.write(f"Güven seviyesi: %{confidence:.2f}")
|
|
|
| else:
|
| st.info("Analiz için bir trafik levhası fotoğrafı çekin veya yükleyin.")
|
|
|
| st.divider()
|
|
|
| st.caption(
|
| "Bu uygulama eğitim amaçlıdır. Model, GTSRB veri setindeki trafik işareti sınıflarına göre tahmin yapar."
|
| ) |