|
1 | 1 | """ |
2 | | -Main flask application |
3 | | -
|
4 | | -# Reference for start/stop trick: |
5 | | - https://stackoverflow.com/questions/49821707/starting-and-stopping-a-method-using-flask-routes-python |
6 | 2 |
|
7 | 3 | # TODO: Load ML model with redis and keep it for sometime. |
8 | 4 | 1- detector/yolov3/detector.py |=> yolov3 weightfile -> redis cache |
9 | 5 | 2- deepsort/deep/feature_extractor |=> model_path -> redis cache |
10 | 6 | 3- Use tmpfs (Insert RAM as a virtual disk and store model state): https://pypi.org/project/memory-tempfile/ |
11 | 7 |
|
12 | | -# TODO: Automatic turn off or switch between the cameras in ML model part. |
13 | | -# TODO: send rtsp url to the ML model part and run the model for that camera. |
14 | 8 | """ |
15 | 9 | from os.path import join |
16 | 10 | from os import getenv, environ |
|
19 | 13 | from threading import Thread |
20 | 14 |
|
21 | 15 | from redis import Redis |
22 | | -from flask import Response, Flask, jsonify |
| 16 | +from flask import Response, Flask, jsonify, request, abort |
23 | 17 |
|
24 | 18 | from rtsp_threaded_tracker import RealTimeTracking |
25 | 19 | from server_cfg import model, deep_sort_dict |
26 | 20 | from config.config import DevelopmentConfig |
27 | 21 | from utils.parser import get_config |
28 | 22 |
|
29 | | -redis_cache = Redis('111.222.333.444') |
| 23 | +redis_cache = Redis('127.0.0.1') |
30 | 24 | app = Flask(__name__) |
31 | | -environ['tracking'] = 'off' |
| 25 | +environ['in_progress'] = 'off' |
32 | 26 |
|
33 | 27 |
|
34 | 28 | def parse_args(): |
@@ -59,39 +53,101 @@ def parse_args(): |
59 | 53 |
|
60 | 54 |
|
61 | 55 | def gen(): |
| 56 | + """ |
| 57 | +
|
| 58 | + Returns: video frames from redis cache |
| 59 | +
|
| 60 | + """ |
62 | 61 | while True: |
63 | 62 | frame = redis_cache.get('frame') |
64 | 63 | if frame is not None: |
65 | 64 | yield b'--frame\r\n'b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n' |
66 | 65 |
|
| 66 | + |
67 | 67 | def pedestrian_tracking(cfg, args): |
| 68 | + """ |
| 69 | + starts the pedestrian detection on rtsp link |
| 70 | + Args: |
| 71 | + cfg: |
| 72 | + args: |
| 73 | +
|
| 74 | + Returns: |
| 75 | +
|
| 76 | + """ |
68 | 77 | tracker = RealTimeTracking(cfg, args) |
69 | 78 | tracker.run() |
70 | 79 |
|
| 80 | + |
71 | 81 | def trigger_process(cfg, args): |
72 | | - t = Thread(target=pedestrian_tracking, args=(cfg, args)) |
73 | | - t.start() |
74 | | - return jsonify({"msg": "Pedestrian detection started successfully"}) |
| 82 | + """ |
| 83 | + triggers pedestrian_tracking process on rtsp link using a thread |
| 84 | + Args: |
| 85 | + cfg: |
| 86 | + args: |
| 87 | +
|
| 88 | + Returns: |
| 89 | + """ |
| 90 | + try: |
| 91 | + t = Thread(target=pedestrian_tracking, args=(cfg, args)) |
| 92 | + t.start() |
| 93 | + return jsonify({"message": "Pedestrian detection started successfully"}) |
| 94 | + except Exception: |
| 95 | + return jsonify({'message': "Unexpected exception occured in process"}) |
| 96 | + |
| 97 | + |
| 98 | +@app.errorhandler(400) |
| 99 | +def bad_argument(error): |
| 100 | + return jsonify({'message': error.description['message']}) |
| 101 | + |
75 | 102 |
|
76 | 103 | # Routes |
77 | | -@app.route('/') |
78 | | -def video_feed(): |
| 104 | +@app.route('/stream', methods=['GET']) |
| 105 | +def stream(): |
| 106 | + """ |
| 107 | + Provides video frames on http link |
| 108 | + Returns: |
| 109 | +
|
| 110 | + """ |
79 | 111 | return Response(gen(), |
80 | 112 | mimetype='multipart/x-mixed-replace; boundary=frame') |
81 | 113 |
|
82 | | -@app.route("/start", methods=['GET']) |
83 | | -def start_tracking(): |
84 | | - if environ['tracking'] != 'on': |
85 | | - global cfg, args |
86 | | - environ['tracking'] = 'on' |
87 | | - return Response(trigger_process(cfg, args), mimetype="text/html") |
88 | | - else: |
89 | | - return jsonify({"msg": " Pedestrian detection is already in progress."}) |
90 | | - |
91 | | -@app.route("/stop", methods=['GET']) |
92 | | -def stop_tracking(): |
93 | | - environ['tracking'] = 'off' |
94 | | - return jsonify({"msg": "Pedestrian detection terminated!"}) |
| 114 | + |
| 115 | +@app.route("/run", methods=['GET']) |
| 116 | +def process_manager(): |
| 117 | + """ |
| 118 | + request parameters: |
| 119 | + run (bool): 1 -> start the pedestrian tracking |
| 120 | + 0 -> stop it |
| 121 | + camera_stream: str -> rtsp link to security camera |
| 122 | +
|
| 123 | + :return: |
| 124 | + """ |
| 125 | + # data = request.args |
| 126 | + data = request.args |
| 127 | + status = data['run'] |
| 128 | + status = int(status) if status.isnumeric() else abort(400, {'message': f"bad argument for run {data['run']}"}) |
| 129 | + if status == 1: |
| 130 | + # if pedestrian tracking is not running, start it off! |
| 131 | + try: |
| 132 | + if environ.get('in_progress', 'off') == 'off': |
| 133 | + global cfg, args |
| 134 | + vdo = data.get('camera_stream') |
| 135 | + if vdo is not None: |
| 136 | + args.input = int(vdo) |
| 137 | + environ['in_progress'] = 'on' |
| 138 | + return trigger_process(cfg, args) |
| 139 | + elif environ.get('in_progress') == 'on': |
| 140 | + # if pedestrian tracking is running, don't start another one (we are short of gpu resources) |
| 141 | + return jsonify({"message": " Pedestrian detection is already in progress."}) |
| 142 | + except Exception: |
| 143 | + environ['in_progress'] = 'off' |
| 144 | + return abort(503) |
| 145 | + elif status == 0: |
| 146 | + if environ.get('in_progress', 'off') == 'off': |
| 147 | + return jsonify({"message": "pedestrian detection is already terminated!"}) |
| 148 | + else: |
| 149 | + environ['in_progress'] = 'off' |
| 150 | + return jsonify({"message": "Pedestrian detection terminated!"}) |
95 | 151 |
|
96 | 152 |
|
97 | 153 | if __name__ == '__main__': |
|
0 commit comments