Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| st.set_page_config(page_title="Object Volume Estimator", layout="wide") | |
| import cv2 | |
| import torch | |
| import numpy as np | |
| from PIL import Image | |
| import pandas as pd | |
| from ultralytics import YOLO | |
| from torchvision.transforms import Compose, Resize, ToTensor, Normalize | |
| # Load models | |
| def load_models(): | |
| yolo = YOLO("yolov8n.pt") | |
| midas = torch.hub.load("intel-isl/MiDaS", "DPT_Large") | |
| midas.eval() | |
| transform = Compose([ | |
| Resize(384), | |
| ToTensor(), | |
| Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5]) | |
| ]) | |
| return yolo, midas, transform | |
| yolo_model, midas_model, midas_transform = load_models() | |
| # --- Streamlit App --- | |
| st.title("Object Dimension & Volume Estimator") | |
| # πΈ Image Source Selection | |
| option = st.radio("Choose Image Source:", ("π€ Upload Image", "πΈ Use Camera")) | |
| # Mode Selection | |
| mode = st.selectbox("Select Image Type:", ["2D RGB Image", "RGB + Depth Image"]) | |
| image_pil = None | |
| if option == "π€ Upload Image": | |
| uploaded_file = st.file_uploader("Upload an image", type=["jpg", "jpeg", "png"]) | |
| if uploaded_file: | |
| image_pil = Image.open(uploaded_file).convert("RGB") | |
| elif option == "πΈ Use Camera": | |
| camera_input = st.camera_input("Take a picture") | |
| if camera_input: | |
| image_pil = Image.open(camera_input).convert("RGB") | |
| # Upload depth image if RGB + Depth selected | |
| depth_map = None | |
| if mode == "RGB + Depth Image" and image_pil is not None: | |
| depth_file = st.file_uploader("Upload corresponding Depth Map (grayscale image)", type=["png", "jpg", "jpeg", "tiff"]) | |
| if depth_file: | |
| depth_map = np.array(Image.open(depth_file).convert("L")) | |
| # Proceed if we have an image | |
| if image_pil is not None: | |
| # Convert to OpenCV format | |
| image_cv = np.array(image_pil) | |
| image_cv = cv2.cvtColor(image_cv, cv2.COLOR_RGB2BGR) | |
| img_h, img_w = image_cv.shape[:2] | |
| st.image(image_pil, caption="Input Image", use_container_width=True) | |
| # Store detected object data | |
| object_data = [] | |
| # π YOLO Object Detection | |
| results = yolo_model(image_cv) | |
| # π Depth Estimation | |
| if mode == "2D RGB Image": | |
| input_tensor = midas_transform(image_pil).unsqueeze(0) | |
| with torch.no_grad(): | |
| estimated_depth = midas_model(input_tensor).squeeze().cpu().numpy() | |
| depth_map_resized = cv2.resize(estimated_depth, (img_w, img_h)) | |
| else: | |
| if depth_map is not None: | |
| depth_map_resized = cv2.resize(depth_map, (img_w, img_h)) | |
| else: | |
| st.error("Please upload a corresponding depth map for 3D images.") | |
| st.stop() | |
| # π― Process each detection | |
| for r in results: | |
| for box in r.boxes: | |
| x1, y1, x2, y2 = map(int, box.xyxy[0]) | |
| width = x2 - x1 | |
| height = y2 - y1 | |
| region = depth_map_resized[y1:y2, x1:x2] | |
| if region.size == 0: | |
| continue | |
| depth = np.mean(region) | |
| volume = round(depth * width * height, 2) | |
| # Draw bounding box & label | |
| cv2.rectangle(image_cv, (x1, y1), (x2, y2), (0, 255, 0), 2) | |
| label = f"LΓBΓH: {depth:.2f}Γ{width}Γ{height} | V: {volume}" | |
| cv2.putText(image_cv, label, (x1, y1 - 10), | |
| cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 0), 2) | |
| # Store data for CSV | |
| object_data.append({ | |
| "Length": round(depth, 2), | |
| "Breadth": int(width), | |
| "Height": int(height), | |
| "Volume": volume | |
| }) | |
| # Show object details | |
| st.markdown(f"**π§ Object Detected:**") | |
| st.write(f"π Length Γ Breadth Γ Height: {depth:.2f} Γ {width} Γ {height}") | |
| st.write(f"π¦ Estimated Volume: {volume} (relative unitsΒ³)") | |
| # Show annotated image | |
| result_img = cv2.cvtColor(image_cv, cv2.COLOR_BGR2RGB) | |
| st.image(result_img, caption="Detected Dimensions", use_container_width=True) | |
| # Show table & CSV download if data exists | |
| if object_data: | |
| df = pd.DataFrame(object_data) | |
| st.markdown("### π Detected Objects Table") | |
| st.dataframe(df) | |
| csv = df.to_csv(index=False).encode('utf-8') | |
| st.download_button( | |
| label="π₯ Download Results as CSV", | |
| data=csv, | |
| file_name='object_dimensions_volume.csv', | |
| mime='text/csv', | |
| ) |