Spaces:
Sleeping
Sleeping
Merge branch 'test'
Browse files- src/app.py +51 -60
- src/utils.py +0 -21
src/app.py
CHANGED
@@ -1,77 +1,68 @@
|
|
1 |
-
from
|
2 |
-
from flask import Flask
|
3 |
-
import threading
|
4 |
-
from utils import start_html_stream
|
5 |
import cv2
|
6 |
-
import
|
7 |
-
import queue
|
8 |
import time
|
9 |
-
import os
|
10 |
|
11 |
app = Flask(__name__)
|
12 |
-
PORT = 7860
|
13 |
-
|
14 |
-
frame_queue = queue.Queue(maxsize=1)
|
15 |
-
|
16 |
-
@app.route("/status", methods=["GET"])
|
17 |
-
def status():
|
18 |
-
return {"Server": "Running"}, 200
|
19 |
-
|
20 |
-
@app.route('/')
|
21 |
-
def html_stream():
|
22 |
-
return start_html_stream(frame_queue)
|
23 |
|
24 |
-
|
25 |
-
|
|
|
26 |
|
27 |
-
def
|
28 |
-
|
29 |
|
30 |
-
cap = cv2.VideoCapture(
|
31 |
framerate = cap.get(cv2.CAP_PROP_FPS)
|
32 |
-
|
33 |
|
34 |
-
|
35 |
-
|
|
|
|
|
36 |
|
|
|
37 |
next_frame_time = time.time()
|
|
|
38 |
while True:
|
39 |
-
frame =
|
40 |
-
if frame is None:
|
41 |
-
stream.stop()
|
42 |
-
stream = CamGear(source=video_file).start()
|
43 |
-
continue
|
44 |
-
frame = cv2.resize(frame, (1280, 720))
|
45 |
-
if not frame_queue.empty():
|
46 |
-
try:
|
47 |
-
frame_queue.get_nowait()
|
48 |
-
except queue.Empty:
|
49 |
-
pass
|
50 |
-
frame_queue.put(frame)
|
51 |
-
del frame
|
52 |
-
gc.collect()
|
53 |
|
54 |
-
|
55 |
-
|
56 |
-
|
|
|
|
|
57 |
|
58 |
-
|
59 |
-
|
60 |
-
|
|
|
|
|
|
|
61 |
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
75 |
|
76 |
-
if __name__ ==
|
77 |
-
|
|
|
|
|
|
1 |
+
from flask import Flask, Response, stream_with_context
|
|
|
|
|
|
|
2 |
import cv2
|
3 |
+
import threading
|
|
|
4 |
import time
|
|
|
5 |
|
6 |
app = Flask(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
|
8 |
+
latest_frame = None
|
9 |
+
lock = threading.Lock()
|
10 |
+
measured_fps = 0
|
11 |
|
12 |
+
def video_reader():
|
13 |
+
global latest_frame, lock, measured_fps
|
14 |
|
15 |
+
cap = cv2.VideoCapture('videos/classroom.mp4')
|
16 |
framerate = cap.get(cv2.CAP_PROP_FPS)
|
17 |
+
frame_duration = 1 / framerate
|
18 |
|
19 |
+
# variables to measure FPS
|
20 |
+
frame_count = 0
|
21 |
+
last_time = time.time()
|
22 |
+
rolling_duration = 0.5
|
23 |
|
24 |
+
# variables to control framerate
|
25 |
next_frame_time = time.time()
|
26 |
+
|
27 |
while True:
|
28 |
+
ret, frame = cap.read()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
|
30 |
+
if ret:
|
31 |
+
with lock:
|
32 |
+
cv2.putText(frame, f"{measured_fps: .0f}", (frame.shape[1] - 70, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2, cv2.LINE_AA)
|
33 |
+
latest_frame = frame
|
34 |
+
frame_count += 1
|
35 |
|
36 |
+
# measure FPS
|
37 |
+
now = time.time()
|
38 |
+
if now - last_time >= rolling_duration:
|
39 |
+
measured_fps = frame_count / (now - last_time)
|
40 |
+
frame_count = 0
|
41 |
+
last_time = now
|
42 |
|
43 |
+
# control framerate
|
44 |
+
next_frame_time += frame_duration
|
45 |
+
sleep_time = next_frame_time - time.time()
|
46 |
+
if sleep_time > 0:
|
47 |
+
time.sleep(sleep_time)
|
48 |
+
else:
|
49 |
+
next_frame_time = time.time()
|
50 |
|
51 |
+
def generate():
|
52 |
+
while True:
|
53 |
+
with lock:
|
54 |
+
encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), 50]
|
55 |
+
ret, jpeg = cv2.imencode('.jpg', latest_frame, encode_param)
|
56 |
+
frame_bytes = jpeg.tobytes() if ret else None
|
57 |
+
print(f"frame filesize: {len(frame_bytes) / (1024 * 1024):.4f} MB")
|
58 |
+
if frame_bytes is not None:
|
59 |
+
yield (b'--frame\r\n'b'Content-Type: image/jpeg\r\n\r\n' + frame_bytes + b'\r\n')
|
60 |
+
|
61 |
+
@app.route('/')
|
62 |
+
def video_feed():
|
63 |
+
return Response(stream_with_context(generate()), mimetype='multipart/x-mixed-replace; boundary=frame')
|
64 |
|
65 |
+
if __name__ == '__main__':
|
66 |
+
t = threading.Thread(target=video_reader, daemon=True)
|
67 |
+
t.start()
|
68 |
+
app.run(host='0.0.0.0', port=5000, threaded=True)
|
src/utils.py
DELETED
@@ -1,21 +0,0 @@
|
|
1 |
-
import cv2
|
2 |
-
from flask import Response
|
3 |
-
import gc
|
4 |
-
import time
|
5 |
-
|
6 |
-
def start_html_stream(frame_queue):
|
7 |
-
def generate():
|
8 |
-
while True:
|
9 |
-
frame = frame_queue.get()
|
10 |
-
if frame is None:
|
11 |
-
time.sleep(0.001)
|
12 |
-
continue
|
13 |
-
encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), 40]
|
14 |
-
(flag, encoded_image) = cv2.imencode(".jpg", frame, encode_param)
|
15 |
-
del frame
|
16 |
-
gc.collect()
|
17 |
-
if not flag:
|
18 |
-
continue
|
19 |
-
yield(b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + bytearray(encoded_image) + b'\r\n')
|
20 |
-
|
21 |
-
return Response(generate(), mimetype="multipart/x-mixed-replace; boundary=frame")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|