Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
parkpow
GitHub Repository: parkpow/deep-license-plate-recognition
Path: blob/master/video-editor/benchmark_video_blur.py
641 views
1
import argparse
2
import datetime
3
import math
4
import os
5
import subprocess
6
import time
7
from collections import OrderedDict
8
from concurrent.futures import ThreadPoolExecutor
9
from functools import partial
10
from timeit import default_timer
11
12
import cv2
13
import requests
14
15
16
def parse_arguments():
17
parser = argparse.ArgumentParser(description="Benchmark Video Blur")
18
parser.add_argument(
19
"--video-editor-url",
20
default="http://localhost:8081/process-video",
21
help="URL endpoint to process video files with Blur",
22
required=False,
23
)
24
parser.add_argument(
25
"--sample",
26
help="One or more samples separated by a comma, for example: 60,50,30",
27
required=False,
28
)
29
parser.add_argument(
30
"--video",
31
help="File path of video file to be processed with Blur, for example: assets/cars.mp4",
32
required=False,
33
)
34
parser.add_argument(
35
"--blur-output",
36
default="output/cars_blur.mp4",
37
help="Video file path where blur saves the already processed file",
38
required=False,
39
)
40
parser.add_argument(
41
"--benchmark-results",
42
default="benchmark_results.txt",
43
help="File to store benchmarking results",
44
required=False,
45
)
46
return parser.parse_args()
47
48
49
def get_duration(args):
50
video = cv2.VideoCapture(args.video)
51
fps = video.get(cv2.CAP_PROP_FPS)
52
frame_count = video.get(cv2.CAP_PROP_FRAME_COUNT)
53
seconds = frame_count // fps
54
video_time = datetime.timedelta(seconds=seconds)
55
return str(video_time)
56
57
58
def write_results(args, results):
59
file_path = args.benchmark_results
60
61
# Check if the file exists
62
file_exists = os.path.exists(file_path)
63
64
# Open the file in append mode if it exists, or create it if it doesn't
65
mode = "a" if file_exists else "w"
66
67
# Get video duration utilizing OpenCV
68
length = get_duration(args)
69
70
with open(file_path, mode) as file:
71
if not file_exists:
72
file.write(
73
"| {:<18} | {:<6} | {:<11} | {:>19} |\n".format(
74
"Video Duration (m)", "Sample", "Output Size", "Processing Time (s)"
75
)
76
)
77
file.write(
78
"| ------------------ | ------ | ----------- | ------------------- |\n"
79
)
80
81
# Append or write the results
82
for result in results:
83
file.write(
84
"| {:>18} | {:>6} | {:>11} | {:>19.1f} |\n".format(
85
length, result["rate"], result["size"], result["duration"]
86
)
87
)
88
89
90
def print_table(file_path):
91
with open(file_path) as file:
92
for line in file:
93
print(line, end="")
94
95
96
def video_blur_api(fp, video_editor_url, exit_on_error=True):
97
fp.seek(0)
98
response = requests.post(
99
video_editor_url, data=dict(action="blur"), files=dict(upload=fp)
100
)
101
if response is None:
102
return {}
103
if response.status_code < 200 or response.status_code > 300:
104
print(response.text)
105
if exit_on_error:
106
exit(1)
107
return response.json(object_pairs_hook=OrderedDict)
108
109
110
def call_duration(path, video_editor_url):
111
now = default_timer()
112
with open(path, "rb") as fp:
113
video_blur_api(fp, video_editor_url=video_editor_url)
114
return default_timer() - now
115
116
117
def convert_size(size_bytes):
118
if size_bytes == 0:
119
return "0B"
120
sign = ""
121
if size_bytes < 0:
122
size_bytes *= -1
123
sign = "-"
124
size_name = ("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB")
125
i = int(math.floor(math.log(size_bytes, 1024)))
126
p = math.pow(1024, i)
127
s = round(size_bytes / p, 2)
128
return f"{sign}{s} {size_name[i]}"
129
130
131
def benchmark(args, executor, sample_rate):
132
stats = list(
133
executor.map(
134
partial(call_duration, video_editor_url=args.video_editor_url), [args.video]
135
)
136
)
137
file_size = os.path.getsize(args.blur_output)
138
yield dict(rate=sample_rate, size=convert_size(file_size), duration=max(stats))
139
140
141
def check_api_access(api_url, max_wait_time=60, poll_interval=2):
142
"""
143
Waits for the API endpoint to become accessible within a specified time.
144
145
Args:
146
api_url (str): The URL of the API endpoint to check.
147
max_wait_time (int): Maximum time to wait in seconds.
148
poll_interval (int): Interval for checking the API availability.
149
150
Returns:
151
bool: True if the API is accessible within the specified time, False otherwise.
152
"""
153
start_time = time.time()
154
while time.time() - start_time < max_wait_time:
155
try:
156
# Try to make an HTTP request to the API endpoint
157
response = requests.options(api_url)
158
if response.status_code == 200:
159
# The API is accessible, return True
160
return True
161
except requests.exceptions.RequestException:
162
pass # Handle any exceptions if the request fails
163
164
# Wait for the next poll_interval seconds before checking again
165
time.sleep(poll_interval)
166
167
# If we reach here, it means the API didn't become accessible within max_wait_time
168
return False
169
170
171
def main(args):
172
rate_string = args.sample
173
number_strings = rate_string.split(",")
174
sample_rates = [int(x) for x in number_strings]
175
176
with ThreadPoolExecutor(max_workers=1) as executor:
177
for sample_rate in sample_rates:
178
# Read the existing env.txt file and remove any existing SAMPLE entry
179
lines = []
180
with open("env.txt") as env_file:
181
for line in env_file:
182
if not line.startswith("SAMPLE="):
183
lines.append(line)
184
185
with open("env.txt", "w") as env_file:
186
for line in lines:
187
env_file.write(line)
188
189
# Add the new SAMPLE_RATE entry
190
env_file.write(f"SAMPLE={sample_rate}\n")
191
192
# Process the video with the modified environment
193
cmd = "docker compose up --build"
194
subprocess.Popen(cmd, shell=True)
195
196
if check_api_access(args.video_editor_url):
197
print("API is accessible, you can proceed with the benchmark.")
198
else:
199
print(
200
"API not accessible within the specified time. Take appropriate action."
201
)
202
203
# Start Benchmark
204
results = list(benchmark(args, executor, sample_rate))
205
206
cmd = "docker compose down"
207
subprocess.call(cmd, shell=True)
208
209
# Write benchmark results to file to save progress.
210
write_results(args, results)
211
212
print_table(args.benchmark_results)
213
214
215
if __name__ == "__main__":
216
args = parse_arguments()
217
218
if not args.sample:
219
raise Exception("sample is required")
220
elif not args.video:
221
raise Exception("video is required")
222
else:
223
main(args)
224
225