Spaces:
Runtime error
Runtime error
deeleting video
Browse files- .gitignore +1 -1
- app.py +131 -16
- inference.py +8 -7
- metrics.py +4 -0
- output.mp4 +0 -0
- pre-requeriments.txt +0 -1
- static/danger_symbol.jpeg +0 -0
- static/danger_symbol1.png +0 -0
.gitignore
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
# Added
|
2 |
tmp/
|
3 |
-
|
4 |
# Byte-compiled / optimized / DLL files
|
5 |
__pycache__/
|
6 |
*.py[cod]
|
|
|
1 |
# Added
|
2 |
tmp/
|
3 |
+
*.mp4
|
4 |
# Byte-compiled / optimized / DLL files
|
5 |
__pycache__/
|
6 |
*.py[cod]
|
app.py
CHANGED
@@ -33,15 +33,107 @@ import pathlib
|
|
33 |
import multiprocessing as mp
|
34 |
from time import time
|
35 |
|
36 |
-
|
37 |
-
REPO_ID='SharkSpace/videos_examples'
|
38 |
-
snapshot_download(repo_id=REPO_ID, token=os.environ.get('SHARK_MODEL'),repo_type='dataset',local_dir='videos_example')
|
39 |
|
40 |
theme = gr.themes.Soft(
|
41 |
primary_hue="sky",
|
42 |
neutral_hue="slate",
|
43 |
)
|
44 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
def process_video(input_video, out_fps = 'auto', skip_frames = 7):
|
46 |
cap = cv2.VideoCapture(input_video)
|
47 |
|
@@ -62,42 +154,65 @@ def process_video(input_video, out_fps = 'auto', skip_frames = 7):
|
|
62 |
cnt = 0
|
63 |
|
64 |
while iterating:
|
|
|
|
|
65 |
if (cnt % skip_frames) == 0:
|
|
|
66 |
# flip frame vertically
|
67 |
display_frame, result = inference_frame_serial(frame)
|
68 |
-
|
69 |
#print(result)
|
70 |
top_pred = process_results_for_plot(predictions = result.numpy(),
|
71 |
classes = classes,
|
72 |
class_sizes = class_sizes_lower)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
pred_dashbord = prediction_dashboard(top_pred = top_pred)
|
74 |
#print('sending frame')
|
75 |
-
print(cnt)
|
76 |
-
|
|
|
|
|
|
|
|
|
77 |
cnt += 1
|
78 |
iterating, frame = cap.read()
|
79 |
|
80 |
video.release()
|
81 |
-
yield None,
|
82 |
|
83 |
with gr.Blocks(theme=theme) as demo:
|
84 |
-
with gr.Row():
|
85 |
input_video = gr.Video(label="Input")
|
|
|
|
|
86 |
output_video = gr.Video(label="Output Video")
|
87 |
-
|
88 |
-
|
89 |
-
original_frames = gr.Image(label="Original Frame")
|
90 |
-
dashboard = gr.Image(label="Dashboard")
|
91 |
-
processed_frames = gr.Image(label="Shark Engine")
|
92 |
-
|
93 |
with gr.Row():
|
94 |
paths = sorted(pathlib.Path('videos_example/').rglob('*.mp4'))
|
95 |
samples=[[path.as_posix()] for path in paths if 'raw_videos' in str(path)]
|
96 |
examples = gr.Examples(samples, inputs=input_video)
|
97 |
process_video_btn = gr.Button("Process Video")
|
98 |
|
99 |
-
process_video_btn.click(process_video, input_video, [processed_frames, original_frames, output_video, dashboard])
|
100 |
-
|
101 |
demo.queue()
|
102 |
if os.getenv('SYSTEM') == 'spaces':
|
103 |
demo.launch(width='40%',auth=(os.environ.get('SHARK_USERNAME'), os.environ.get('SHARK_PASSWORD')))
|
|
|
33 |
import multiprocessing as mp
|
34 |
from time import time
|
35 |
|
36 |
+
if not os.path.exists('videos_example'):
|
37 |
+
REPO_ID='SharkSpace/videos_examples'
|
38 |
+
snapshot_download(repo_id=REPO_ID, token=os.environ.get('SHARK_MODEL'),repo_type='dataset',local_dir='videos_example')
|
39 |
|
40 |
theme = gr.themes.Soft(
|
41 |
primary_hue="sky",
|
42 |
neutral_hue="slate",
|
43 |
)
|
44 |
|
45 |
+
|
46 |
+
|
47 |
+
def add_border(frame, color = (255, 0, 0), thickness = 2):
|
48 |
+
# Add a red border to the image
|
49 |
+
relative = max(frame.shape[0],frame.shape[1])
|
50 |
+
top = int(relative*0.025)
|
51 |
+
bottom = int(relative*0.025)
|
52 |
+
left = int(relative*0.025)
|
53 |
+
right = int(relative*0.025)
|
54 |
+
# Add the border to the image
|
55 |
+
bordered_image = cv2.copyMakeBorder(frame, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color)
|
56 |
+
|
57 |
+
return bordered_image
|
58 |
+
|
59 |
+
def overlay_text_on_image(image, text_list, font=cv2.FONT_HERSHEY_SIMPLEX, font_size=0.5, font_thickness=1, margin=10, color=(255, 255, 255)):
|
60 |
+
relative = min(image.shape[0],image.shape[1])
|
61 |
+
y0, dy = margin, int(relative*0.1) # start y position and line gap
|
62 |
+
for i, line in enumerate(text_list):
|
63 |
+
y = y0 + i * dy
|
64 |
+
text_width, _ = cv2.getTextSize(line, font, font_size, font_thickness)[0]
|
65 |
+
cv2.putText(image, line, (image.shape[1] - text_width - margin, y), font, font_size, color, font_thickness, lineType=cv2.LINE_AA)
|
66 |
+
return image
|
67 |
+
|
68 |
+
def overlay_logo(frame,logo, position=(10, 10)):
|
69 |
+
"""
|
70 |
+
Overlay a transparent logo (with alpha channel) on a frame.
|
71 |
+
|
72 |
+
Parameters:
|
73 |
+
- frame: The main image/frame to overlay the logo on.
|
74 |
+
- logo_path: Path to the logo image.
|
75 |
+
- position: (x, y) tuple indicating where the logo starts (top left corner).
|
76 |
+
"""
|
77 |
+
# Load the logo and its alpha channel
|
78 |
+
alpha_channel = np.ones(logo.shape[:2], dtype=logo.dtype)
|
79 |
+
print(logo.min(),logo.max())
|
80 |
+
logo = np.dstack((logo, alpha_channel))
|
81 |
+
|
82 |
+
indexes = logo[:,:,1]>150
|
83 |
+
logo[indexes,3] = 0
|
84 |
+
l_channels = cv2.split(logo)
|
85 |
+
if len(l_channels) != 4:
|
86 |
+
raise ValueError("Logo doesn't have an alpha channel!")
|
87 |
+
l_b, l_g, l_r, l_alpha = l_channels
|
88 |
+
cv2.imwrite('l_alpha.png',l_alpha*255)
|
89 |
+
# Extract regions of interest (ROI) from both images
|
90 |
+
roi = frame[position[1]:position[1]+logo.shape[0], position[0]:position[0]+logo.shape[1]]
|
91 |
+
|
92 |
+
# Blend the logo using the alpha channel
|
93 |
+
for channel in range(0, 3):
|
94 |
+
roi[:, :, channel] = (l_alpha ) * l_channels[channel] + (1.0 - l_alpha ) * roi[:, :, channel]
|
95 |
+
|
96 |
+
return frame
|
97 |
+
|
98 |
+
|
99 |
+
def add_danger_symbol_from_image(frame, top_pred):
|
100 |
+
relative = max(frame.shape[0],frame.shape[1])
|
101 |
+
if top_pred['shark_sighted'] and top_pred['dangerous_dist']:
|
102 |
+
# Add the danger symbol
|
103 |
+
danger_symbol = cv2.imread('static/danger_symbol.jpeg')
|
104 |
+
danger_symbol = cv2.resize(danger_symbol, (int(relative*0.1), int(relative*0.1)), interpolation = cv2.INTER_AREA)[:,:,::-1]
|
105 |
+
frame = overlay_logo(frame,danger_symbol, position=(int(relative*0.05), int(relative*0.05)))
|
106 |
+
return frame
|
107 |
+
|
108 |
+
def draw_cockpit(frame, top_pred,cnt):
|
109 |
+
# Bullet points:
|
110 |
+
high_danger_color = (255,0,0)
|
111 |
+
low_danger_color = yellowgreen = (154,205,50)
|
112 |
+
shark_sighted = 'Shark Detected: ' + str(top_pred['shark_sighted'])
|
113 |
+
human_sighted = 'Number of Humans: ' + str(top_pred['human_n'])
|
114 |
+
shark_size_estimate = 'Biggest shark size: ' + str(top_pred['biggest_shark_size'])
|
115 |
+
shark_weight_estimate = 'Biggest shark weight: ' + str(top_pred['biggest_shark_weight'])
|
116 |
+
danger_level = 'Danger Level: '
|
117 |
+
danger_level += 'High' if top_pred['dangerous_dist'] else 'Low'
|
118 |
+
danger_color = 'orangered' if top_pred['dangerous_dist'] else 'yellowgreen'
|
119 |
+
# Create a list of strings to plot
|
120 |
+
strings = [shark_sighted, human_sighted, shark_size_estimate, shark_weight_estimate, danger_level]
|
121 |
+
relative = max(frame.shape[0],frame.shape[1])
|
122 |
+
if top_pred['shark_sighted'] and top_pred['dangerous_dist'] and cnt%2 == 0:
|
123 |
+
frame = add_border(frame, color=high_danger_color, thickness=int(relative*0.025))
|
124 |
+
frame = add_danger_symbol_from_image(frame, top_pred)
|
125 |
+
elif top_pred['shark_sighted'] and not top_pred['dangerous_dist'] and cnt%2 == 0:
|
126 |
+
frame = add_border(frame, color=low_danger_color, thickness=int(relative*0.025))
|
127 |
+
frame = add_danger_symbol_from_image(frame, top_pred)
|
128 |
+
else:
|
129 |
+
|
130 |
+
frame = add_border(frame, color=(0,0,0), thickness=int(relative*0.025))
|
131 |
+
|
132 |
+
overlay_text_on_image(frame, strings, font=cv2.FONT_HERSHEY_SIMPLEX, font_size=relative*0.0007, font_thickness=1, margin=int(relative*0.05), color=(255, 255, 255))
|
133 |
+
return frame
|
134 |
+
|
135 |
+
|
136 |
+
|
137 |
def process_video(input_video, out_fps = 'auto', skip_frames = 7):
|
138 |
cap = cv2.VideoCapture(input_video)
|
139 |
|
|
|
154 |
cnt = 0
|
155 |
|
156 |
while iterating:
|
157 |
+
print('overall count ', cnt)
|
158 |
+
|
159 |
if (cnt % skip_frames) == 0:
|
160 |
+
print('starting Frame: ', cnt)
|
161 |
# flip frame vertically
|
162 |
display_frame, result = inference_frame_serial(frame)
|
163 |
+
|
164 |
#print(result)
|
165 |
top_pred = process_results_for_plot(predictions = result.numpy(),
|
166 |
classes = classes,
|
167 |
class_sizes = class_sizes_lower)
|
168 |
+
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
169 |
+
prediction_frame = cv2.cvtColor(display_frame, cv2.COLOR_BGR2RGB)
|
170 |
+
|
171 |
+
|
172 |
+
#
|
173 |
+
#video.write(cv2.cvtColor(frame, cv2.COLOR_RGB2BGR))
|
174 |
+
|
175 |
+
if cnt*skip_frames %2==0 and top_pred['shark_sighted']:
|
176 |
+
prediction_frame = cv2.resize(prediction_frame, (int(width), int(height)))
|
177 |
+
frame =prediction_frame
|
178 |
+
|
179 |
+
if top_pred['shark_sighted']:
|
180 |
+
frame = draw_cockpit(frame, top_pred,cnt*skip_frames)
|
181 |
+
|
182 |
+
frame = cv2.resize(frame, (int(width), int(height)))
|
183 |
+
video.write(cv2.cvtColor(frame, cv2.COLOR_RGB2BGR))
|
184 |
+
|
185 |
+
|
186 |
pred_dashbord = prediction_dashboard(top_pred = top_pred)
|
187 |
#print('sending frame')
|
188 |
+
print('finalizing frame:',cnt)
|
189 |
+
print(pred_dashbord.shape)
|
190 |
+
print(frame.shape)
|
191 |
+
print(prediction_frame.shape)
|
192 |
+
yield frame , None
|
193 |
+
|
194 |
cnt += 1
|
195 |
iterating, frame = cap.read()
|
196 |
|
197 |
video.release()
|
198 |
+
yield None, output_path
|
199 |
|
200 |
with gr.Blocks(theme=theme) as demo:
|
201 |
+
with gr.Row().style(equal_height=True,height='25%'):
|
202 |
input_video = gr.Video(label="Input")
|
203 |
+
original_frames = gr.Image(label="Processed Frame").style( height=650)
|
204 |
+
#processed_frames = gr.Image(label="Shark Engine")
|
205 |
output_video = gr.Video(label="Output Video")
|
206 |
+
#dashboard = gr.Image(label="Events")
|
207 |
+
|
|
|
|
|
|
|
|
|
208 |
with gr.Row():
|
209 |
paths = sorted(pathlib.Path('videos_example/').rglob('*.mp4'))
|
210 |
samples=[[path.as_posix()] for path in paths if 'raw_videos' in str(path)]
|
211 |
examples = gr.Examples(samples, inputs=input_video)
|
212 |
process_video_btn = gr.Button("Process Video")
|
213 |
|
214 |
+
#process_video_btn.click(process_video, input_video, [processed_frames, original_frames, output_video, dashboard])
|
215 |
+
process_video_btn.click(process_video, input_video, [ original_frames, output_video])
|
216 |
demo.queue()
|
217 |
if os.getenv('SYSTEM') == 'spaces':
|
218 |
demo.launch(width='40%',auth=(os.environ.get('SHARK_USERNAME'), os.environ.get('SHARK_PASSWORD')))
|
inference.py
CHANGED
@@ -53,11 +53,11 @@ classes = ['Beach',
|
|
53 |
'Dolphin',
|
54 |
'Miscellaneous',
|
55 |
'Unidentifiable shark',
|
56 |
-
'
|
57 |
'Dusty shark',
|
58 |
'Blue shark',
|
59 |
'Great white shark',
|
60 |
-
'
|
61 |
'Nurse shark',
|
62 |
'Silky shark',
|
63 |
'Leopard shark',
|
@@ -106,11 +106,11 @@ class_sizes = {'Beach': None,
|
|
106 |
'Dolphin': {'feet':[6.6, 13.1], 'meter': [2, 4], 'kg': [150, 650], 'pounds': [330, 1430]},
|
107 |
'Miscellaneous': None,
|
108 |
'Unidentifiable shark': {'feet': [2, 15], 'meter': [0.6, 4.5], 'kg': [50, 1000], 'pounds': [110, 2200]},
|
109 |
-
'
|
110 |
'Dusty shark': {'feet': [9, 14], 'meter': [3, 4.25], 'kg': [160, 180], 'pounds': [350, 400]},
|
111 |
'Blue shark': {'feet': [7.9, 12.5], 'meter': [2.4, 3], 'kg': [60, 120], 'pounds': [130, 260]},
|
112 |
'Great white shark': {'feet': [13.1, 20], 'meter': [4, 6], 'kg': [680, 1800], 'pounds': [1500, 4000]},
|
113 |
-
'
|
114 |
'Nurse shark': {'feet': [7.9, 9.8], 'meter': [2.4, 3], 'kg': [90, 115], 'pounds': [200, 250]},
|
115 |
'Silky shark': {'feet': [6.6, 8.2], 'meter': [2, 2.5], 'kg': [300, 380], 'pounds': [660, 840]},
|
116 |
'Leopard shark': {'feet': [3.9, 4.9], 'meter': [1.2, 1.5], 'kg': [11, 20], 'pounds': [22, 44]},
|
@@ -132,10 +132,11 @@ classes_is_shark_id = [i for i, x in enumerate(classes_is_shark) if x == 1]
|
|
132 |
classes_is_human_id = [i for i, x in enumerate(classes_is_human) if x == 1]
|
133 |
classes_is_unknown_id = [i for i, x in enumerate(classes_is_unknown) if x == 1]
|
134 |
|
135 |
-
REPO_ID = "SharkSpace/maskformer_model"
|
136 |
-
FILENAME = "mask2former"
|
137 |
|
138 |
-
|
|
|
|
|
|
|
139 |
|
140 |
# Choose to use a config and initialize the detector
|
141 |
config_file ='model/mask2former_swin-t-p4-w7-224_8xb2-lsj-50e_coco-panoptic/mask2former_swin-t-p4-w7-224_8xb2-lsj-50e_coco-panoptic.py'
|
|
|
53 |
'Dolphin',
|
54 |
'Miscellaneous',
|
55 |
'Unidentifiable shark',
|
56 |
+
'C Shark',
|
57 |
'Dusty shark',
|
58 |
'Blue shark',
|
59 |
'Great white shark',
|
60 |
+
'Shark',
|
61 |
'Nurse shark',
|
62 |
'Silky shark',
|
63 |
'Leopard shark',
|
|
|
106 |
'Dolphin': {'feet':[6.6, 13.1], 'meter': [2, 4], 'kg': [150, 650], 'pounds': [330, 1430]},
|
107 |
'Miscellaneous': None,
|
108 |
'Unidentifiable shark': {'feet': [2, 15], 'meter': [0.6, 4.5], 'kg': [50, 1000], 'pounds': [110, 2200]},
|
109 |
+
'C Shark': {'feet': [4, 10], 'meter': [1.25, 3], 'kg': [50, 1000], 'pounds': [110, 2200]}, # Prob incorrect
|
110 |
'Dusty shark': {'feet': [9, 14], 'meter': [3, 4.25], 'kg': [160, 180], 'pounds': [350, 400]},
|
111 |
'Blue shark': {'feet': [7.9, 12.5], 'meter': [2.4, 3], 'kg': [60, 120], 'pounds': [130, 260]},
|
112 |
'Great white shark': {'feet': [13.1, 20], 'meter': [4, 6], 'kg': [680, 1800], 'pounds': [1500, 4000]},
|
113 |
+
'Shark': {'feet': [7.2, 10.8], 'meter': [2.2, 3.3], 'kg': [130, 300], 'pounds': [290, 660]},
|
114 |
'Nurse shark': {'feet': [7.9, 9.8], 'meter': [2.4, 3], 'kg': [90, 115], 'pounds': [200, 250]},
|
115 |
'Silky shark': {'feet': [6.6, 8.2], 'meter': [2, 2.5], 'kg': [300, 380], 'pounds': [660, 840]},
|
116 |
'Leopard shark': {'feet': [3.9, 4.9], 'meter': [1.2, 1.5], 'kg': [11, 20], 'pounds': [22, 44]},
|
|
|
132 |
classes_is_human_id = [i for i, x in enumerate(classes_is_human) if x == 1]
|
133 |
classes_is_unknown_id = [i for i, x in enumerate(classes_is_unknown) if x == 1]
|
134 |
|
|
|
|
|
135 |
|
136 |
+
if not os.path.exists('model'):
|
137 |
+
REPO_ID = "SharkSpace/maskformer_model"
|
138 |
+
FILENAME = "mask2former"
|
139 |
+
snapshot_download(repo_id=REPO_ID, token= os.environ.get('SHARK_MODEL'),local_dir='model/')
|
140 |
|
141 |
# Choose to use a config and initialize the detector
|
142 |
config_file ='model/mask2former_swin-t-p4-w7-224_8xb2-lsj-50e_coco-panoptic/mask2former_swin-t-p4-w7-224_8xb2-lsj-50e_coco-panoptic.py'
|
metrics.py
CHANGED
@@ -49,6 +49,7 @@ def add_class_sizes(top_pred = {}, class_sizes = None):
|
|
49 |
tmp_class_sizes = class_sizes[tmp_pred.lower()]
|
50 |
if tmp_class_sizes == None:
|
51 |
size_list.append(None)
|
|
|
52 |
else:
|
53 |
size_list.append(tmp_class_sizes['feet'])
|
54 |
|
@@ -74,6 +75,7 @@ def add_class_weights(top_pred = {}, class_weights = None):
|
|
74 |
tmp_class_weights = class_weights[tmp_pred.lower()]
|
75 |
if tmp_class_weights == None:
|
76 |
weight_list.append(None)
|
|
|
77 |
else:
|
78 |
weight_list.append(tmp_class_weights['pounds'])
|
79 |
|
@@ -117,6 +119,8 @@ def get_min_distance_shark_person(top_pred, class_sizes = None, dangerous_distan
|
|
117 |
'dangerous_dist': min_dist < dangerous_distance}
|
118 |
|
119 |
def _calculate_dist_estimate(bbox1, bbox2, labels, class_sizes = None, measurement = 'feet'):
|
|
|
|
|
120 |
class_feet_size_mean = np.array([class_sizes[labels[0]][measurement][0],
|
121 |
class_sizes[labels[1]][measurement][0]]).mean()
|
122 |
box_pixel_size_mean = np.array([np.linalg.norm(bbox1[[0, 1]] - bbox1[[2, 3]]),
|
|
|
49 |
tmp_class_sizes = class_sizes[tmp_pred.lower()]
|
50 |
if tmp_class_sizes == None:
|
51 |
size_list.append(None)
|
52 |
+
continue
|
53 |
else:
|
54 |
size_list.append(tmp_class_sizes['feet'])
|
55 |
|
|
|
75 |
tmp_class_weights = class_weights[tmp_pred.lower()]
|
76 |
if tmp_class_weights == None:
|
77 |
weight_list.append(None)
|
78 |
+
continue
|
79 |
else:
|
80 |
weight_list.append(tmp_class_weights['pounds'])
|
81 |
|
|
|
119 |
'dangerous_dist': min_dist < dangerous_distance}
|
120 |
|
121 |
def _calculate_dist_estimate(bbox1, bbox2, labels, class_sizes = None, measurement = 'feet'):
|
122 |
+
if class_sizes[labels[0]] == None or class_sizes[labels[1]] == None:
|
123 |
+
return 9999
|
124 |
class_feet_size_mean = np.array([class_sizes[labels[0]][measurement][0],
|
125 |
class_sizes[labels[1]][measurement][0]]).mean()
|
126 |
box_pixel_size_mean = np.array([np.linalg.norm(bbox1[[0, 1]] - bbox1[[2, 3]]),
|
output.mp4
DELETED
Binary file (262 kB)
|
|
pre-requeriments.txt
CHANGED
@@ -1,5 +1,4 @@
|
|
1 |
|
2 |
-
|
3 |
numpy==1.22.4
|
4 |
opencv-python-headless==4.5.5.64
|
5 |
openmim==0.1.5
|
|
|
1 |
|
|
|
2 |
numpy==1.22.4
|
3 |
opencv-python-headless==4.5.5.64
|
4 |
openmim==0.1.5
|
static/danger_symbol.jpeg
ADDED
static/danger_symbol1.png
ADDED