Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -21,62 +21,94 @@ def check_ffmpeg():
|
|
21 |
if shutil.which("ffmpeg") is None:
|
22 |
raise EnvironmentError("ffmpeg is not installed or not found in the system PATH. Please install ffmpeg to proceed.")
|
23 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
def process_video(video_path, output_option):
|
25 |
# Check if ffmpeg is installed
|
26 |
check_ffmpeg()
|
27 |
|
28 |
-
#
|
29 |
-
|
30 |
-
|
31 |
-
#
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
mp4_files.append(mp4_file)
|
51 |
-
|
52 |
-
# Check again for the converted .mp4 video files specifically for the processed video
|
53 |
-
matched_mp4_files = [file for file in mp4_files if video_name in file]
|
54 |
-
|
55 |
-
if not matched_mp4_files:
|
56 |
-
raise Exception(f"No .mp4 video files found in directory {output_dir} after conversion for {video_name}.")
|
57 |
-
|
58 |
-
# Initialize object count dictionary based on colors
|
59 |
-
color_counts = {color: 0 for color in ClassToColorMapping.values()}
|
60 |
-
|
61 |
-
# Calculate object count based on results and map to colors
|
62 |
for result in results:
|
63 |
-
if
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
|
|
69 |
|
70 |
-
|
71 |
-
|
|
|
|
|
|
|
|
|
72 |
|
73 |
-
#
|
|
|
|
|
|
|
74 |
if output_option == "Count":
|
75 |
-
return
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
80 |
|
81 |
# Define Gradio inputs
|
82 |
video_input = gr.Video()
|
@@ -92,12 +124,12 @@ video_interface = gr.Interface(
|
|
92 |
inputs=[video_input, output_option_input],
|
93 |
outputs=[gr.JSON(label="Color Counts"), "video"], # Ensure two outputs are defined, using JSON for color counts
|
94 |
title="YOLO Video Tracking Application with Color Counting",
|
95 |
-
description="A simple application to track objects in a video using YOLO model and count objects by color. Upload your own video, or click one of the examples to load them.",
|
96 |
article="""<div>
|
97 |
-
<p style="text-align: center">Upload a video file and select the type of output you want: object color
|
98 |
</div>""",
|
99 |
examples=examples,
|
100 |
-
cache_examples=
|
101 |
)
|
102 |
|
103 |
# Deploy the interface with share enabled
|
|
|
21 |
if shutil.which("ffmpeg") is None:
|
22 |
raise EnvironmentError("ffmpeg is not installed or not found in the system PATH. Please install ffmpeg to proceed.")
|
23 |
|
24 |
+
def convert_to_mp4(file):
|
25 |
+
"""Convert a .avi video file to .mp4 format."""
|
26 |
+
mp4_file = f"{file[:-4]}.mp4"
|
27 |
+
os.system(f"ffmpeg -y -i \"{file}\" -vcodec libx264 \"{mp4_file}\"")
|
28 |
+
os.remove(file) # Remove the original .avi file after conversion
|
29 |
+
return mp4_file
|
30 |
+
|
31 |
def process_video(video_path, output_option):
|
32 |
# Check if ffmpeg is installed
|
33 |
check_ffmpeg()
|
34 |
|
35 |
+
# Determine if the video needs to be saved
|
36 |
+
save_video = output_option in ["Video", "Both"]
|
37 |
+
|
38 |
+
# Run the YOLO model on the video, specifying the tracker configuration and save option
|
39 |
+
results = model.track(
|
40 |
+
video_path,
|
41 |
+
save=save_video,
|
42 |
+
tracker="bytetrack.yaml",
|
43 |
+
half=False,
|
44 |
+
vid_stride=1,
|
45 |
+
iou=0.75,
|
46 |
+
conf=0.25
|
47 |
+
)
|
48 |
+
|
49 |
+
# Initialize a dictionary to store unique IDs for each color
|
50 |
+
chip_ids = {color: set() for color in ClassToColorMapping.values()}
|
51 |
+
|
52 |
+
# Check if results are None or if there are no results
|
53 |
+
if results is None or len(results) == 0:
|
54 |
+
raise Exception("No detections were found in the video.")
|
55 |
+
|
56 |
+
# Track the unique IDs for each color
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
57 |
for result in results:
|
58 |
+
# Check if result.boxes exists and has valid id and cls attributes
|
59 |
+
if result.boxes is None or result.boxes.id is None or result.boxes.cls is None:
|
60 |
+
continue # Skip if no boxes or if ids or classes are None
|
61 |
+
|
62 |
+
# Check if the id and cls tensors are not empty
|
63 |
+
if result.boxes.id.numel() == 0 or result.boxes.cls.numel() == 0:
|
64 |
+
continue # Skip if ids or classes are empty tensors
|
65 |
|
66 |
+
for cls, id_ in zip(result.boxes.cls, result.boxes.id):
|
67 |
+
if cls is None or id_ is None:
|
68 |
+
continue # Skip if class or id is None
|
69 |
+
color = ClassToColorMapping.get(int(cls.item()), None) # Map class label to color
|
70 |
+
if color:
|
71 |
+
chip_ids[color].add(int(id_.item())) # Add the unique ID to the set
|
72 |
|
73 |
+
# Convert sets to counts of unique IDs
|
74 |
+
chip_counts_by_color = {color: len(ids) for color, ids in chip_ids.items()}
|
75 |
+
|
76 |
+
# If the user only wants the count, return it immediately
|
77 |
if output_option == "Count":
|
78 |
+
return chip_counts_by_color, None
|
79 |
+
|
80 |
+
# Process video saving if required
|
81 |
+
if save_video:
|
82 |
+
video_name = os.path.splitext(os.path.basename(video_path))[0]
|
83 |
+
|
84 |
+
# Find the latest directory created in 'runs/detect/'
|
85 |
+
output_dir = max(glob.glob('./runs/detect/*'), key=os.path.getmtime)
|
86 |
+
|
87 |
+
# Find the saved video file in the latest directory with the specific video name
|
88 |
+
video_files = glob.glob(os.path.join(output_dir, f'{video_name}*.avi'))
|
89 |
+
|
90 |
+
if not video_files:
|
91 |
+
raise Exception(f"No .avi video files found in directory {output_dir} for {video_name}")
|
92 |
+
|
93 |
+
# Convert each .avi video to .mp4
|
94 |
+
mp4_files = []
|
95 |
+
for file in video_files:
|
96 |
+
mp4_file = convert_to_mp4(file)
|
97 |
+
mp4_files.append(mp4_file)
|
98 |
+
|
99 |
+
matched_mp4_files = [file for file in mp4_files if video_name in file]
|
100 |
+
|
101 |
+
if not matched_mp4_files:
|
102 |
+
raise Exception(f"No .mp4 video files found in directory {output_dir} after conversion for {video_name}.")
|
103 |
+
|
104 |
+
# Return video path and chip counts if both are requested
|
105 |
+
if output_option == "Both":
|
106 |
+
return chip_counts_by_color, matched_mp4_files[0]
|
107 |
+
else:
|
108 |
+
return None, matched_mp4_files[0]
|
109 |
+
else:
|
110 |
+
# Return only chip counts if no video is needed
|
111 |
+
return chip_counts_by_color, None
|
112 |
|
113 |
# Define Gradio inputs
|
114 |
video_input = gr.Video()
|
|
|
124 |
inputs=[video_input, output_option_input],
|
125 |
outputs=[gr.JSON(label="Color Counts"), "video"], # Ensure two outputs are defined, using JSON for color counts
|
126 |
title="YOLO Video Tracking Application with Color Counting",
|
127 |
+
description="A simple application to track objects in a video using YOLO model and count unique objects by color. Upload your own video, or click one of the examples to load them.",
|
128 |
article="""<div>
|
129 |
+
<p style="text-align: center">Upload a video file and select the type of output you want: unique object counts by color, processed video, or both. Then, hit submit to process the video.</p>
|
130 |
</div>""",
|
131 |
examples=examples,
|
132 |
+
cache_examples=True # Disable caching to speed up launch
|
133 |
)
|
134 |
|
135 |
# Deploy the interface with share enabled
|