Spaces:
Sleeping
Sleeping
add video progress bar and save annotated video button
Browse files- .gitignore +1 -0
- app.py +49 -27
- requirements.txt +2 -1
.gitignore
CHANGED
@@ -126,6 +126,7 @@ models/*
|
|
126 |
|
127 |
# All cached movie files
|
128 |
*.mp4
|
|
|
129 |
|
130 |
# All cached model files
|
131 |
*.pt
|
|
|
126 |
|
127 |
# All cached movie files
|
128 |
*.mp4
|
129 |
+
*.MOV
|
130 |
|
131 |
# All cached model files
|
132 |
*.pt
|
app.py
CHANGED
@@ -2,6 +2,8 @@ from ultralytics import YOLO
|
|
2 |
import time
|
3 |
import os
|
4 |
import logging
|
|
|
|
|
5 |
|
6 |
import av
|
7 |
import cv2
|
@@ -138,7 +140,7 @@ def analyze_frame(frame: np.ndarray):
|
|
138 |
|
139 |
if show_labels in ["Object Detection", "Both"]:
|
140 |
# Run YOLOv8 object detection on the frame
|
141 |
-
object_results = object_model(frame)
|
142 |
|
143 |
for i, box in enumerate(object_results[0].boxes):
|
144 |
class_id = int(box.cls)
|
@@ -151,7 +153,7 @@ def analyze_frame(frame: np.ndarray):
|
|
151 |
|
152 |
if show_labels in ["Pose Estimation", "Both"]:
|
153 |
# Run YOLOv8 pose estimation on the frame
|
154 |
-
pose_results = pose_model(frame)
|
155 |
|
156 |
for i, box in enumerate(pose_results[0].boxes):
|
157 |
class_id = int(box.cls)
|
@@ -381,7 +383,7 @@ st.markdown(
|
|
381 |
|
382 |
|
383 |
def analysis_init():
|
384 |
-
global yt_error, analysis_time, show_labels, labels_placeholder, input_subheader, input_placeholder, output_placeholder
|
385 |
|
386 |
yt_error.empty() # Placeholder for analysis time
|
387 |
|
@@ -397,7 +399,11 @@ def analysis_init():
|
|
397 |
("Object Detection", "Pose Estimation", "Both"),
|
398 |
index=2 # Set default to "Both" (index 2)
|
399 |
)
|
|
|
|
|
|
|
400 |
labels_placeholder = st.empty() # Placeholder for labels
|
|
|
401 |
|
402 |
|
403 |
# Function to publish frames and results to the Streamlit UI
|
@@ -460,8 +466,25 @@ if uploaded_file is not None or image_url:
|
|
460 |
# Function to process video files
|
461 |
# This function reads frames from a video file, analyzes each frame for face detection and sentiment analysis,
|
462 |
# and updates the Streamlit UI with the current input frame, analyzed frame, and detected labels.
|
|
|
463 |
def process_video(video_path):
|
464 |
cap = cv2.VideoCapture(video_path) # Open the video file
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
465 |
while cap.isOpened():
|
466 |
ret, frame = cap.read() # Read a frame from the video
|
467 |
if not ret:
|
@@ -472,35 +495,34 @@ def process_video(video_path):
|
|
472 |
|
473 |
# Analyze the frame for face detection and sentiment analysis
|
474 |
analyze_frame(rgb_frame)
|
475 |
-
|
476 |
|
477 |
-
|
|
|
478 |
|
|
|
479 |
|
480 |
-
#
|
|
|
|
|
|
|
|
|
481 |
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
488 |
|
489 |
-
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
490 |
-
try:
|
491 |
-
info_dict = ydl.extract_info(youtube_url, download=False)
|
492 |
-
if 'url' in info_dict:
|
493 |
-
return info_dict['url']
|
494 |
-
elif 'entries' in info_dict:
|
495 |
-
return info_dict['entries'][0]['url']
|
496 |
-
else:
|
497 |
-
yt_error.error(
|
498 |
-
"Unable to extract video URL. The video might be unavailable or restricted.")
|
499 |
-
return None
|
500 |
-
except yt_dlp.utils.DownloadError as e:
|
501 |
-
yt_error.error(
|
502 |
-
f"Error: Unable to process the YouTube URL. {str(e)}")
|
503 |
-
return None
|
504 |
|
505 |
# Function to get video URL using Cobalt API
|
506 |
|
|
|
2 |
import time
|
3 |
import os
|
4 |
import logging
|
5 |
+
import tempfile
|
6 |
+
|
7 |
|
8 |
import av
|
9 |
import cv2
|
|
|
140 |
|
141 |
if show_labels in ["Object Detection", "Both"]:
|
142 |
# Run YOLOv8 object detection on the frame
|
143 |
+
object_results = object_model(frame, conf=0.5)
|
144 |
|
145 |
for i, box in enumerate(object_results[0].boxes):
|
146 |
class_id = int(box.cls)
|
|
|
153 |
|
154 |
if show_labels in ["Pose Estimation", "Both"]:
|
155 |
# Run YOLOv8 pose estimation on the frame
|
156 |
+
pose_results = pose_model(frame, conf=0.5)
|
157 |
|
158 |
for i, box in enumerate(pose_results[0].boxes):
|
159 |
class_id = int(box.cls)
|
|
|
383 |
|
384 |
|
385 |
def analysis_init():
|
386 |
+
global progress_bar, status_text, download_button, yt_error, analysis_time, show_labels, labels_placeholder, input_subheader, input_placeholder, output_placeholder
|
387 |
|
388 |
yt_error.empty() # Placeholder for analysis time
|
389 |
|
|
|
399 |
("Object Detection", "Pose Estimation", "Both"),
|
400 |
index=2 # Set default to "Both" (index 2)
|
401 |
)
|
402 |
+
# Create a progress bar
|
403 |
+
progress_bar = st.empty()
|
404 |
+
status_text = st.empty()
|
405 |
labels_placeholder = st.empty() # Placeholder for labels
|
406 |
+
download_button = st.empty() # Placeholder for download button
|
407 |
|
408 |
|
409 |
# Function to publish frames and results to the Streamlit UI
|
|
|
466 |
# Function to process video files
|
467 |
# This function reads frames from a video file, analyzes each frame for face detection and sentiment analysis,
|
468 |
# and updates the Streamlit UI with the current input frame, analyzed frame, and detected labels.
|
469 |
+
# Function to process video files
|
470 |
def process_video(video_path):
|
471 |
cap = cv2.VideoCapture(video_path) # Open the video file
|
472 |
+
|
473 |
+
# Create a temporary file for the annotated video
|
474 |
+
with tempfile.NamedTemporaryFile(delete=False, suffix='.mp4') as temp_video:
|
475 |
+
temp_video_path = temp_video.name
|
476 |
+
|
477 |
+
# save_annotated_video(video_path, temp_video_path)
|
478 |
+
|
479 |
+
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
|
480 |
+
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
|
481 |
+
fps = int(cap.get(cv2.CAP_PROP_FPS))
|
482 |
+
total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
|
483 |
+
|
484 |
+
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
|
485 |
+
out = cv2.VideoWriter(temp_video_path, fourcc, fps, (width, height))
|
486 |
+
|
487 |
+
frame_count = 0
|
488 |
while cap.isOpened():
|
489 |
ret, frame = cap.read() # Read a frame from the video
|
490 |
if not ret:
|
|
|
495 |
|
496 |
# Analyze the frame for face detection and sentiment analysis
|
497 |
analyze_frame(rgb_frame)
|
498 |
+
analyzed_frame = img_container["analyzed"]
|
499 |
|
500 |
+
if analyzed_frame is not None:
|
501 |
+
out.write(cv2.cvtColor(analyzed_frame, cv2.COLOR_RGB2BGR))
|
502 |
|
503 |
+
publish_frame() # Publish the results
|
504 |
|
505 |
+
# Update progress
|
506 |
+
frame_count += 1
|
507 |
+
progress = min(100, int(frame_count / total_frames * 100))
|
508 |
+
progress_bar.progress(progress)
|
509 |
+
status_text.text(f"Processing video: {progress}% complete")
|
510 |
|
511 |
+
cap.release() # Release the video capture object
|
512 |
+
out.release()
|
513 |
+
|
514 |
+
# Add download button for annotated video
|
515 |
+
with open(temp_video_path, "rb") as file:
|
516 |
+
download_button.download_button(
|
517 |
+
label="Download Annotated Video",
|
518 |
+
data=file,
|
519 |
+
file_name="annotated_video.mp4",
|
520 |
+
mime="video/mp4"
|
521 |
+
)
|
522 |
+
|
523 |
+
# Clean up the temporary file
|
524 |
+
os.unlink(temp_video_path)
|
525 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
526 |
|
527 |
# Function to get video URL using Cobalt API
|
528 |
|
requirements.txt
CHANGED
@@ -6,4 +6,5 @@ setuptools
|
|
6 |
streamlit_webrtc
|
7 |
twilio
|
8 |
ultralytics
|
9 |
-
watchdog
|
|
|
|
6 |
streamlit_webrtc
|
7 |
twilio
|
8 |
ultralytics
|
9 |
+
watchdog
|
10 |
+
tempfile
|