| import streamlit as st |
| from ultralytics import YOLO |
| from ultralytics.nn.tasks import SegmentationModel |
| import torch |
| import cv2 |
| import numpy as np |
| import tempfile |
| import os |
|
|
| |
| torch.serialization.add_safe_globals([SegmentationModel]) |
|
|
| |
| model = YOLO("yolov8n-seg.pt").to("cpu") |
|
|
| st.title("π₯ Object Segmentation on Uploaded Video") |
|
|
| uploaded_video = st.file_uploader("Upload a video", type=["mp4", "avi", "mov"]) |
|
|
| if uploaded_video: |
| |
| tfile = tempfile.NamedTemporaryFile(delete=False) |
| tfile.write(uploaded_video.read()) |
| video_path = tfile.name |
|
|
| st.video(video_path) |
| st.markdown("### β³ Processing video... Please wait.") |
|
|
| cap = cv2.VideoCapture(video_path) |
| width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) |
| height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) |
| fps = int(cap.get(cv2.CAP_PROP_FPS)) |
|
|
| output_path = os.path.join(tempfile.gettempdir(), "output_segmentation.mp4") |
| fourcc = cv2.VideoWriter_fourcc(*'mp4v') |
| out = cv2.VideoWriter(output_path, fourcc, fps, (width, height)) |
|
|
| frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) |
| progress_bar = st.progress(0) |
|
|
| |
| np.random.seed(42) |
| colors = {i: tuple(np.random.randint(0, 256, 3).tolist()) for i in range(80)} |
|
|
| frame_index = 0 |
| while cap.isOpened(): |
| ret, frame = cap.read() |
| if not ret: |
| break |
|
|
| try: |
| results = model.predict(frame, conf=0.3, iou=0.5) |
| except Exception as e: |
| st.error(f"Prediction failed on frame {frame_index}: {e}") |
| break |
|
|
| if results[0].masks is not None: |
| masks = results[0].masks.data.cpu().numpy() |
| class_ids = results[0].boxes.cls.cpu().numpy().astype(int) |
| boxes = results[0].boxes.xyxy.cpu().numpy() |
| names = results[0].names |
|
|
| for mask, class_id, box in zip(masks, class_ids, boxes): |
| label = names[class_id] |
| color = colors.get(class_id, (0, 255, 0)) |
|
|
| |
| resized_mask = cv2.resize(mask, (frame.shape[1], frame.shape[0])) |
| mask_bool = resized_mask > 0.5 |
|
|
| |
| colored_mask = np.zeros_like(frame, dtype=np.uint8) |
| colored_mask[mask_bool] = color |
| frame = cv2.addWeighted(frame, 1.0, colored_mask, 0.5, 0) |
|
|
| |
| x1, y1, x2, y2 = box.astype(int) |
| font = cv2.FONT_HERSHEY_SIMPLEX |
| font_scale = 0.6 |
| thickness = 1 |
| label_text = label |
|
|
| (text_width, text_height), _ = cv2.getTextSize(label_text, font, font_scale, thickness) |
| text_x = x1 |
| text_y = y1 - 10 if y1 - 10 > 10 else y1 + text_height + 10 |
|
|
| |
| cv2.rectangle(frame, (text_x - 2, text_y - text_height - 4), |
| (text_x + text_width + 2, text_y + 4), (0, 0, 0), -1) |
| cv2.putText(frame, label_text, (text_x, text_y), |
| font, font_scale, (255, 255, 255), thickness=1, lineType=cv2.LINE_AA) |
|
|
| out.write(frame) |
| frame_index += 1 |
| progress_bar.progress(min(frame_index / frame_count, 1.0)) |
|
|
| cap.release() |
| out.release() |
| progress_bar.empty() |
|
|
| st.success("β
Video processing completed!") |
|
|
| with open(output_path, "rb") as f: |
| st.download_button("π₯ Download Segmented Video", f, file_name="segmented_output.mp4", mime="video/mp4") |
|
|