Charalambos Georgiades commited on
Commit
8c6ff1d
1 Parent(s): cefaf53

Added app.py

Browse files
Files changed (2) hide show
  1. app.py +214 -0
  2. cfg/vessels_tyv4.cfg +281 -0
app.py ADDED
@@ -0,0 +1,214 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Imports
2
+ import cv2
3
+ from detector import Detector
4
+ from pathlib import Path
5
+ import gradio as gr
6
+ import os
7
+ import numpy as np
8
+ import csv
9
+ import matplotlib.pyplot as plt
10
+ import pandas as pd
11
+
12
+ # Choose weights, names and config file
13
+ chosen_weights = "cfg/vessels_tyv4.weights"
14
+ chosen_config_file = "cfg/vessels_tyv4.cfg"
15
+ chosen_names = "cfg/vessel.names"
16
+
17
+ with open(chosen_names, "r") as f:
18
+ classes = [line.strip() for line in f.readlines()]
19
+ labels = np.array(classes, dtype=str)
20
+
21
+ # Function for analyzing images
22
+ def analyze_image(selected_image, chosen_conf_thresh, chosen_nms_thresh):
23
+
24
+ # Delete existing output files
25
+ if os.path.exists("Classes.csv"):
26
+ os.remove("Classes.csv")
27
+
28
+ if selected_image is None:
29
+ raise RuntimeError("No image found!")
30
+
31
+ print("Starting image scan")
32
+
33
+ # Initialize the detector
34
+ detector = Detector(weights = str(chosen_weights), config_file = str(chosen_config_file), classes_file = chosen_names, conf_thresh = chosen_conf_thresh, nms_thresh = chosen_nms_thresh)
35
+
36
+ # Detect the image
37
+ img_det, classes_id, scores, boxes = detector.detect(selected_image)
38
+
39
+ class_names = []
40
+
41
+ for _class in classes_id:
42
+ class_names.append(labels[_class])
43
+
44
+ tags = []
45
+
46
+ for i in range(len(class_names)):
47
+ tags.append([str(class_names[i]), str(boxes[i][0]), str(boxes[i][1]), str(boxes[i][2]), str(boxes[i][3]), str(scores[i])])
48
+
49
+ print("Image scan finished succefully.")
50
+
51
+ # Save tags in a csv file
52
+ with open("Classes.csv", "w") as f:
53
+ write = csv.writer(f)
54
+ write.writerow(["Class", "X", "Y", "Width", "Height", "Score"])
55
+ write.writerows(tags)
56
+ f.close()
57
+
58
+ return img_det, "Classes.csv", tags[:10]
59
+
60
+ # Function for analyzing video
61
+ def analyze_video(selected_video, chosen_conf_thresh, chosen_nms_thresh, start_sec, duration):
62
+
63
+ # Delete existing output files
64
+ if os.path.exists("demo_film.mp4"):
65
+ os.remove("demo_film.mp4")
66
+ if os.path.exists("output.mp4"):
67
+ os.remove("output.mp4")
68
+ if os.path.exists("Classes.csv"):
69
+ os.remove("Classes.csv")
70
+
71
+ if selected_video is None:
72
+ raise RuntimeError("No video found!")
73
+
74
+ print("Starting video scan")
75
+
76
+ # Capture the video input
77
+ video = cv2.VideoCapture(selected_video)
78
+ ret, frame = video.read()
79
+ if not ret: # Checking
80
+ raise RuntimeError("Cannot read video stream!")
81
+
82
+ # Calculate start and end frame
83
+ total_frames = round(video.get(cv2.CAP_PROP_FRAME_COUNT))
84
+ fps = video.get(cv2.CAP_PROP_FPS)
85
+ start_frame = round(start_sec * fps)
86
+ end_frame = round(start_frame + (duration * fps))
87
+
88
+ # Initialize the detector
89
+ detector = Detector(weights = str(chosen_weights), config_file = str(chosen_config_file), classes_file = chosen_names, conf_thresh = chosen_conf_thresh, nms_thresh = chosen_nms_thresh)
90
+
91
+ frame_id = 0
92
+ vid_out = []
93
+ save_file_name = "demo_film.mp4"
94
+
95
+ tags = []
96
+ unique_objects = []
97
+
98
+ if start_frame > total_frames:
99
+ raise RuntimeError("Start second is out of bounds!")
100
+
101
+ while True:
102
+ # Read the image
103
+ ret, frame = video.read()
104
+
105
+ if not ret: # Error or end of stream heck
106
+ break
107
+ if frame is None: continue
108
+
109
+ if start_frame <= frame_id <= end_frame:
110
+ class_names = []
111
+ # Detect the image
112
+ img_det, classes_id, scores, boxes = detector.detect(frame)
113
+
114
+ for _class in classes_id:
115
+ class_names.append(labels[_class])
116
+
117
+ if unique_objects.count(labels[_class]) == 0:
118
+ unique_objects.append(labels[_class])
119
+
120
+ for i in range(len(class_names)):
121
+ tags.append([str(class_names[i]), str(boxes[i][0]), str(boxes[i][1]), str(boxes[i][2]), str(boxes[i][3]), str(scores[i]), str(frame_id)])
122
+
123
+ # video writer
124
+ if frame_id == start_frame:
125
+ Height, Width = img_det.shape[:2]
126
+ fps = video.get(cv2.CAP_PROP_FPS) if 15 < video.get(cv2.CAP_PROP_FPS) <= 30 else 15
127
+ vid_out = cv2.VideoWriter(save_file_name, cv2.VideoWriter_fourcc(*"MP4V"), fps, (Width, Height))
128
+ vid_out.write(img_det)
129
+
130
+ if frame_id > end_frame:
131
+ break
132
+
133
+ frame_id += 1
134
+
135
+ # Release videos
136
+ video.release()
137
+ vid_out.release()
138
+
139
+ with open("Classes.csv", "w") as f:
140
+ write = csv.writer(f)
141
+ write.writerow(["Class", "X", "Y", "Width", "Height", "Score","Frame"])
142
+ write.writerows(tags)
143
+ f.close()
144
+
145
+ plt.switch_backend("agg")
146
+
147
+ if end_frame > total_frames:
148
+ end_frame = total_frames
149
+
150
+ fig = plt.figure()
151
+
152
+ df = pd.DataFrame(tags, columns = ["Class", "X", "Y", "Width", "Height", "Score", "Frame"])
153
+
154
+ for unique_object in unique_objects:
155
+ object_array = df[df["Class"].str.fullmatch(unique_object)==True]
156
+ obj_per_frame = []
157
+
158
+ for i in range(start_frame, end_frame + 1):
159
+ temp_array = []
160
+ temp_array = object_array[object_array["Frame"].astype("str").str.fullmatch(str(i))==True]
161
+ rows = temp_array.shape[0]
162
+ obj_per_frame.append(rows)
163
+
164
+ plt.plot(list(range(start_frame, end_frame+1)), obj_per_frame, label = unique_object)
165
+
166
+ plt.title("Objects per frame")
167
+ plt.ylabel("Objects")
168
+ plt.xlabel("Frame")
169
+ plt.legend()
170
+
171
+ print("Video scan finished succefully.")
172
+
173
+ # Changes video fourcc to h264 so that it can be displayed in the browser
174
+ os.system("ffmpeg -i demo_film.mp4 -vcodec libx264 -f mp4 output.mp4")
175
+
176
+ return "output.mp4", fig, "Classes.csv", tags[:10]
177
+
178
+
179
+ # Dradio interfaces take mandatory parameters an input function, the input type(s) and output type(s)
180
+ # Demo is hosted on http://localhost:7860/
181
+
182
+ # Examples
183
+ image_examples = [
184
+ ["examples/horses.png", 0.20, 0.40],
185
+ ["examples/basketball.png", 0.25, 0.40],
186
+ ]
187
+ video_examples =[["examples/scene_from_series.mp4", 0.25, 0.40, 0, 10]]
188
+
189
+ # Image interface
190
+ image_interface = gr.Interface(fn = analyze_image,
191
+ inputs = [gr.Image(label = "Image"),
192
+ gr.Slider(0, 1, value = 0.25, label = "Confidence Threshold"),
193
+ gr.Slider(0, 1, value = 0.40, label = "Non Maxima Supression threshold")],
194
+ outputs = [gr.Image(label="Image"), gr.File(label="All classes"), gr.Dataframe(label="Ten first classes", headers=["Class", "X", "Y", "Width", "Height", "Score"])],
195
+ allow_flagging = False,
196
+ cache_examples = False,
197
+ examples = image_examples)
198
+
199
+ # Video interface
200
+ video_interface = gr.Interface(fn = analyze_video,
201
+ inputs = [gr.Video(label = "Video"),
202
+ gr.Slider(0, 1, value = 0.25, label = "Confidence Threshold"),
203
+ gr.Slider(0, 1, value = 0.40, label = "Non Maxima Supression threshold"),
204
+ gr.Slider(0, 60, value = 0, label = "Start Second", step = 1),
205
+ gr.Slider(1, 10, value = 4, label = "Duration", step = 1)],
206
+ outputs = [gr.Video(label="Video"), gr.Plot(label="Objects per frame"), gr.File(label="All classes"), gr.Dataframe(label=" Ten first classes", headers=["Class", "X", "Y", "Width", "Height", "Score", "Frame"])],
207
+ allow_flagging = False,
208
+ cache_examples = False,
209
+ examples = video_examples)
210
+
211
+ gr.TabbedInterface(
212
+ [video_interface, image_interface],
213
+ ["Scan Videos", "Scan Images"]
214
+ ).launch()
cfg/vessels_tyv4.cfg ADDED
@@ -0,0 +1,281 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [net]
2
+ # Testing
3
+ #batch=1
4
+ #subdivisions=1
5
+ # Training
6
+ batch=64
7
+ subdivisions=8
8
+ width=416
9
+ height=416
10
+ channels=3
11
+ momentum=0.9
12
+ decay=0.0005
13
+ angle=0
14
+ saturation = 1.5
15
+ exposure = 1.5
16
+ hue=.1
17
+
18
+ learning_rate=0.00261
19
+ burn_in=1000
20
+ max_batches = 80200
21
+ policy=steps
22
+ steps=400000,450000
23
+ scales=.1,.1
24
+
25
+ [convolutional]
26
+ batch_normalize=1
27
+ filters=32
28
+ size=3
29
+ stride=2
30
+ pad=1
31
+ activation=leaky
32
+
33
+ [convolutional]
34
+ batch_normalize=1
35
+ filters=64
36
+ size=3
37
+ stride=2
38
+ pad=1
39
+ activation=leaky
40
+
41
+ [convolutional]
42
+ batch_normalize=1
43
+ filters=64
44
+ size=3
45
+ stride=1
46
+ pad=1
47
+ activation=leaky
48
+
49
+ [route]
50
+ layers=-1
51
+ groups=2
52
+ group_id=1
53
+
54
+ [convolutional]
55
+ batch_normalize=1
56
+ filters=32
57
+ size=3
58
+ stride=1
59
+ pad=1
60
+ activation=leaky
61
+
62
+ [convolutional]
63
+ batch_normalize=1
64
+ filters=32
65
+ size=3
66
+ stride=1
67
+ pad=1
68
+ activation=leaky
69
+
70
+ [route]
71
+ layers = -1,-2
72
+
73
+ [convolutional]
74
+ batch_normalize=1
75
+ filters=64
76
+ size=1
77
+ stride=1
78
+ pad=1
79
+ activation=leaky
80
+
81
+ [route]
82
+ layers = -6,-1
83
+
84
+ [maxpool]
85
+ size=2
86
+ stride=2
87
+
88
+ [convolutional]
89
+ batch_normalize=1
90
+ filters=128
91
+ size=3
92
+ stride=1
93
+ pad=1
94
+ activation=leaky
95
+
96
+ [route]
97
+ layers=-1
98
+ groups=2
99
+ group_id=1
100
+
101
+ [convolutional]
102
+ batch_normalize=1
103
+ filters=64
104
+ size=3
105
+ stride=1
106
+ pad=1
107
+ activation=leaky
108
+
109
+ [convolutional]
110
+ batch_normalize=1
111
+ filters=64
112
+ size=3
113
+ stride=1
114
+ pad=1
115
+ activation=leaky
116
+
117
+ [route]
118
+ layers = -1,-2
119
+
120
+ [convolutional]
121
+ batch_normalize=1
122
+ filters=128
123
+ size=1
124
+ stride=1
125
+ pad=1
126
+ activation=leaky
127
+
128
+ [route]
129
+ layers = -6,-1
130
+
131
+ [maxpool]
132
+ size=2
133
+ stride=2
134
+
135
+ [convolutional]
136
+ batch_normalize=1
137
+ filters=256
138
+ size=3
139
+ stride=1
140
+ pad=1
141
+ activation=leaky
142
+
143
+ [route]
144
+ layers=-1
145
+ groups=2
146
+ group_id=1
147
+
148
+ [convolutional]
149
+ batch_normalize=1
150
+ filters=128
151
+ size=3
152
+ stride=1
153
+ pad=1
154
+ activation=leaky
155
+
156
+ [convolutional]
157
+ batch_normalize=1
158
+ filters=128
159
+ size=3
160
+ stride=1
161
+ pad=1
162
+ activation=leaky
163
+
164
+ [route]
165
+ layers = -1,-2
166
+
167
+ [convolutional]
168
+ batch_normalize=1
169
+ filters=256
170
+ size=1
171
+ stride=1
172
+ pad=1
173
+ activation=leaky
174
+
175
+ [route]
176
+ layers = -6,-1
177
+
178
+ [maxpool]
179
+ size=2
180
+ stride=2
181
+
182
+ [convolutional]
183
+ batch_normalize=1
184
+ filters=512
185
+ size=3
186
+ stride=1
187
+ pad=1
188
+ activation=leaky
189
+
190
+ ##################################
191
+
192
+ [convolutional]
193
+ batch_normalize=1
194
+ filters=256
195
+ size=1
196
+ stride=1
197
+ pad=1
198
+ activation=leaky
199
+
200
+ [convolutional]
201
+ batch_normalize=1
202
+ filters=512
203
+ size=3
204
+ stride=1
205
+ pad=1
206
+ activation=leaky
207
+
208
+ [convolutional]
209
+ size=1
210
+ stride=1
211
+ pad=1
212
+ filters=24
213
+ activation=linear
214
+
215
+
216
+
217
+ [yolo]
218
+ mask = 3,4,5
219
+ anchors = 9, 15, 22, 18, 14, 39, 34, 41, 45, 86, 145,161 #416
220
+ classes=3
221
+ num=6
222
+ jitter=.3
223
+ scale_x_y = 1.05
224
+ cls_normalizer=1.0
225
+ iou_normalizer=0.07
226
+ iou_loss=ciou
227
+ ignore_thresh = .7
228
+ truth_thresh = 1
229
+ random=1
230
+ resize=1.5
231
+ nms_kind=greedynms
232
+ beta_nms=0.6
233
+
234
+ [route]
235
+ layers = -4
236
+
237
+ [convolutional]
238
+ batch_normalize=1
239
+ filters=128
240
+ size=1
241
+ stride=1
242
+ pad=1
243
+ activation=leaky
244
+
245
+ [upsample]
246
+ stride=2
247
+
248
+ [route]
249
+ layers = -1, 23
250
+
251
+ [convolutional]
252
+ batch_normalize=1
253
+ filters=256
254
+ size=3
255
+ stride=1
256
+ pad=1
257
+ activation=leaky
258
+
259
+ [convolutional]
260
+ size=1
261
+ stride=1
262
+ pad=1
263
+ filters=24
264
+ activation=linear
265
+
266
+ [yolo]
267
+ mask = 0,1,2
268
+ anchors = 9, 15, 22, 18, 14, 39, 34, 41, 45, 86, 145,161 #416
269
+ classes=3
270
+ num=6
271
+ jitter=.3
272
+ scale_x_y = 1.05
273
+ cls_normalizer=1.0
274
+ iou_normalizer=0.07
275
+ iou_loss=ciou
276
+ ignore_thresh = .7
277
+ truth_thresh = 1
278
+ random=1
279
+ resize=1.5
280
+ nms_kind=greedynms
281
+ beta_nms=0.6