Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -662,74 +662,90 @@ YOLOv8 will detect all objects and optionally verify them with the best classifi
|
|
| 662 |
|
| 663 |
|
| 664 |
|
|
|
|
|
|
|
| 665 |
|
| 666 |
with st.form("detection_form"):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 667 |
conf_th = st.slider("Confidence threshold", 0.1, 0.9, 0.5, 0.05)
|
| 668 |
use_classifier = st.checkbox("Use ResNet50 classifier verification", value=True)
|
| 669 |
-
|
| 670 |
-
# 2. Add a Submit button
|
| 671 |
-
submitted = st.form_submit_button("Run Detection")
|
| 672 |
-
|
| 673 |
-
uploaded_file = st.file_uploader("Upload an image", type=["jpg", "jpeg", "png"])
|
| 674 |
-
|
| 675 |
-
if uploaded_file is not None:
|
| 676 |
-
pil_img = read_image_file(uploaded_file)
|
| 677 |
|
| 678 |
-
#
|
| 679 |
-
|
| 680 |
|
| 681 |
-
|
| 682 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 683 |
|
| 684 |
-
|
| 685 |
-
|
| 686 |
-
|
| 687 |
-
|
| 688 |
-
|
| 689 |
-
|
| 690 |
-
|
| 691 |
-
|
| 692 |
-
|
| 693 |
-
|
| 694 |
-
|
| 695 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 696 |
else:
|
| 697 |
-
|
| 698 |
-
classifier_model = None
|
| 699 |
-
|
| 700 |
-
with st.spinner("Running detection..."):
|
| 701 |
-
result = run_yolo_with_optional_classifier(
|
| 702 |
-
pil_img=pil_img,
|
| 703 |
-
yolo_model=yolo_model,
|
| 704 |
-
classifier_model=classifier_model,
|
| 705 |
-
conf_threshold=conf_th,
|
| 706 |
-
)
|
| 707 |
-
|
| 708 |
-
# β
ONLY 2 IMAGES SHOWN β SIDE BY SIDE
|
| 709 |
-
col1, col2 = st.columns(2)
|
| 710 |
-
|
| 711 |
-
with col1:
|
| 712 |
-
st.image(pil_img, caption="Uploaded Image", width=520)
|
| 713 |
-
|
| 714 |
-
with col2:
|
| 715 |
-
st.image(result["annotated_image"], caption="Detected Result", width=520)
|
| 716 |
-
|
| 717 |
-
st.write(f"YOLO inference time: {result['yolo_inference_time_sec']*1000:.1f} ms")
|
| 718 |
-
st.write(f"Number of detections: {len(result['detections'])}")
|
| 719 |
-
|
| 720 |
-
if result["detections"]:
|
| 721 |
-
st.markdown("### Detected objects")
|
| 722 |
-
df_det = pd.DataFrame([
|
| 723 |
-
{
|
| 724 |
-
"YOLO label": det["label"],
|
| 725 |
-
"YOLO confidence level": det["conf_yolo"],
|
| 726 |
-
"CLS label": det.get("cls_label"),
|
| 727 |
-
"CLS confidence level": det.get("cls_conf"),
|
| 728 |
-
|
| 729 |
-
}
|
| 730 |
-
for det in result["detections"]
|
| 731 |
-
])
|
| 732 |
-
st.dataframe(df_det, width=520)
|
| 733 |
|
| 734 |
# ------------------------------------------------------------
|
| 735 |
# PAGE 4 β MODEL PERFORMANCE
|
|
@@ -831,7 +847,7 @@ from your webcam and run YOLOv8 detection on it.
|
|
| 831 |
conf_threshold=conf_th,
|
| 832 |
)
|
| 833 |
|
| 834 |
-
st.image(result["annotated_image"], caption="Detections", width='
|
| 835 |
st.write(f"YOLO inference time: {result['yolo_inference_time_sec']*1000:.1f} ms")
|
| 836 |
st.write(f"Number of detections: {len(result['detections'])}")
|
| 837 |
if result["detections"]:
|
|
|
|
| 662 |
|
| 663 |
|
| 664 |
|
| 665 |
+
# ---- Replace your current detection block with this ----
|
| 666 |
+
uploaded_file = None
|
| 667 |
|
| 668 |
with st.form("detection_form"):
|
| 669 |
+
st.subheader("Object Detection β YOLOv8 + Optional ResNet Verification")
|
| 670 |
+
|
| 671 |
+
# Put uploader inside the form so uploading doesn't trigger detection
|
| 672 |
+
uploaded_file = st.file_uploader("Upload an image", type=["jpg", "jpeg", "png"])
|
| 673 |
+
|
| 674 |
conf_th = st.slider("Confidence threshold", 0.1, 0.9, 0.5, 0.05)
|
| 675 |
use_classifier = st.checkbox("Use ResNet50 classifier verification", value=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 676 |
|
| 677 |
+
# Submit button (the form will only submit when this is clicked)
|
| 678 |
+
submitted = st.form_submit_button("Run Detection")
|
| 679 |
|
| 680 |
+
# Only proceed when user clicked the button AND a file is present
|
| 681 |
+
if submitted:
|
| 682 |
+
if uploaded_file is None:
|
| 683 |
+
st.warning("Please upload an image before clicking Run Detection.")
|
| 684 |
+
else:
|
| 685 |
+
pil_img = read_image_file(uploaded_file)
|
| 686 |
+
|
| 687 |
+
# placeholders for in-place updates (prevents DOM insert/remove jitter)
|
| 688 |
+
left_col, right_col = st.columns(2)
|
| 689 |
+
left_ph = left_col.empty()
|
| 690 |
+
right_ph = right_col.empty()
|
| 691 |
+
table_ph = st.empty()
|
| 692 |
+
meta_ph = st.empty()
|
| 693 |
+
|
| 694 |
+
# show uploaded image immediately (fixed width)
|
| 695 |
+
left_ph.image(pil_img, caption="Uploaded Image", width=520)
|
| 696 |
+
|
| 697 |
+
# load yolo (cached) and optionally classifier (cached builder or loader)
|
| 698 |
+
with st.spinner("Loading YOLO model..."):
|
| 699 |
+
yolo_model = load_yolo_model()
|
| 700 |
+
|
| 701 |
+
classifier_model = None
|
| 702 |
+
if use_classifier:
|
| 703 |
+
with st.spinner("Loading ResNet50 classifier..."):
|
| 704 |
+
# prefer cached loader if available
|
| 705 |
+
try:
|
| 706 |
+
cls_models = load_classification_models()
|
| 707 |
+
classifier_model = cls_models.get("ResNet50")
|
| 708 |
+
except Exception:
|
| 709 |
+
# fallback: build & load weights (rare)
|
| 710 |
+
classifier_model = build_resnet50_model_v2()
|
| 711 |
+
weights_path = CLASSIFIER_MODEL_CONFIGS["ResNet50"]["path"]
|
| 712 |
+
if os.path.exists(weights_path):
|
| 713 |
+
try:
|
| 714 |
+
classifier_model.load_weights(weights_path)
|
| 715 |
+
except Exception as e:
|
| 716 |
+
st.warning(f"Could not load ResNet50 weights: {e}")
|
| 717 |
+
classifier_model = None
|
| 718 |
+
else:
|
| 719 |
+
st.warning("ResNet50 weights not found β classifier verification disabled.")
|
| 720 |
+
classifier_model = None
|
| 721 |
+
|
| 722 |
+
# run detection (only now)
|
| 723 |
+
with st.spinner("Running detection..."):
|
| 724 |
+
result = run_yolo_with_optional_classifier(
|
| 725 |
+
pil_img=pil_img,
|
| 726 |
+
yolo_model=yolo_model,
|
| 727 |
+
classifier_model=classifier_model,
|
| 728 |
+
conf_threshold=conf_th,
|
| 729 |
+
)
|
| 730 |
|
| 731 |
+
# update annotated image in-place (same fixed width)
|
| 732 |
+
right_ph.image(result["annotated_image"], caption="Detected Result", width=520)
|
| 733 |
+
|
| 734 |
+
meta_ph.write(f"YOLO inference time: {result['yolo_inference_time_sec']*1000:.1f} ms β Detections: {len(result['detections'])}")
|
| 735 |
+
|
| 736 |
+
if result["detections"]:
|
| 737 |
+
df_det = pd.DataFrame([
|
| 738 |
+
{
|
| 739 |
+
"YOLO label": det["label"],
|
| 740 |
+
"YOLO confidence level": det["conf_yolo"],
|
| 741 |
+
"CLS label": det.get("cls_label"),
|
| 742 |
+
"CLS confidence level": det.get("cls_conf"),
|
| 743 |
+
}
|
| 744 |
+
for det in result["detections"]
|
| 745 |
+
])
|
| 746 |
+
table_ph.dataframe(df_det)
|
| 747 |
else:
|
| 748 |
+
table_ph.info("No detections found.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 749 |
|
| 750 |
# ------------------------------------------------------------
|
| 751 |
# PAGE 4 β MODEL PERFORMANCE
|
|
|
|
| 847 |
conf_threshold=conf_th,
|
| 848 |
)
|
| 849 |
|
| 850 |
+
st.image(result["annotated_image"], caption="Detections", width='520')
|
| 851 |
st.write(f"YOLO inference time: {result['yolo_inference_time_sec']*1000:.1f} ms")
|
| 852 |
st.write(f"Number of detections: {len(result['detections'])}")
|
| 853 |
if result["detections"]:
|