From 5479c5dd8581b021fb230e37855e0ffd98e2d397 Mon Sep 17 00:00:00 2001 From: Aymeric Chaumont <aymeric.chaumont@student-cs.fr> Date: Wed, 20 Jul 2022 11:01:46 +0200 Subject: [PATCH] cleanify cameras inventory, allow for multiple cams per restaurant, cleanify rtsp capture, fix websockets in video-capture --- .gitignore | 3 +- backend/cameras.py.template | 28 +++++++++ backend/video_capture.py | 112 ++++++++++++++++++------------------ 3 files changed, 86 insertions(+), 57 deletions(-) create mode 100644 backend/cameras.py.template diff --git a/.gitignore b/.gitignore index de88a2b..a17152a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ node_modules/ build/ env/ .env -__pycache__ \ No newline at end of file +__pycache__ +cameras.py \ No newline at end of file diff --git a/backend/cameras.py.template b/backend/cameras.py.template new file mode 100644 index 0000000..c44cdae --- /dev/null +++ b/backend/cameras.py.template @@ -0,0 +1,28 @@ +restaurants = [ + { + "restaurant": "local", + "a_factor": 30, + "b_factor": 120, + "cameras": + [ + { + "IP": "", + "user": "", + "password": "", + "stream": "stream1", + "mask_points": + [ + [ + [70, 370], + [420, 720], + [1280, 720], + [1280, 250], + [930, 215], + [450, 550], + [130, 350] + ] + ] + } + ] + } +] diff --git a/backend/video_capture.py b/backend/video_capture.py index 9806146..c83c95d 100644 --- a/backend/video_capture.py +++ b/backend/video_capture.py @@ -3,75 +3,75 @@ from datetime import datetime, timedelta import numpy as np import keras from utils.preprocessing import fix_singular_shape, norm_by_imagenet -from dotenv import load_dotenv import json -import os +import time +from cameras import restaurants from db import models from db.database import SessionLocal from routers.websocket import manager + - -def handle_cameras(): +async def handle_cameras(): model = keras.models.load_model('assets', compile=False) db = SessionLocal() - load_dotenv() - camera_number = int(os.getenv('CAM_NUMBER')) - cameras = [] - for i in range(camera_number): - camera = {} - camera["place"] = os.getenv(f'CAM_{i}_PLACE') - camera["IP"] = os.getenv(f'CAM_{i}_IP') - camera["user"] = os.getenv(f'CAM_{i}_USER') - camera["password"] = os.getenv(f'CAM_{i}_PASSWORD') - camera["stream"] = os.getenv(f'CAM_{i}_STREAM') - camera["a_factor"] = int(os.getenv(f'CAM_{i}_A_FACTOR')) - camera["b_factor"] = int(os.getenv(f'CAM_{i}_B_FACTOR')) - camera["framegap"] = int(os.getenv(f'CAM_{i}_FRAMEGAP')) - camera["count"] = 0 - camera["cap"] = cv2.VideoCapture( - f'rtsp://{camera["user"]}:{camera["password"]}@{camera["IP"]}/{camera["stream"]}') - mask_length = int(os.getenv(f'CAM_{i}_POINTS_NB')) - mask_points = [] - for j in range(mask_length): - point = os.getenv(f'CAM_{i}_POINT_{j}') - mask_points.append(list(map(int, point.split(',')))) - mask = np.zeros((720, 1280, 3), dtype=np.float32) - cv2.fillPoly(mask, [np.array(mask_points)], (255, 255, 255)) - camera["mask"] = mask - cameras.append(camera) + for restaurant in restaurants: + for camera in restaurant["cameras"]: + mask = np.zeros((720, 1280, 3), dtype=np.float32) + cv2.fillPoly(mask, np.array(camera["mask_points"]), (255, 255, 255)) + camera["mask"] = mask while True: - for camera in cameras: - if camera['cap'].isOpened(): - ret, frame = camera['cap'].read() - if ret and camera['count'] % camera['framegap'] == 0: - current_time = datetime.now() - masked_img = cv2.bitwise_and( - frame.astype(np.float32), camera["mask"]) - treated_img = fix_singular_shape(masked_img, 16) - input_image = np.expand_dims( - np.squeeze( - norm_by_imagenet( - np.array( - [treated_img]))), - axis=0) - pred_map = np.squeeze(model.predict(input_image)) - count_prediction = np.sum(pred_map) + + start_timestamp = time.time() + current_date = datetime.fromtimestamp(start_timestamp) + print(current_date) + weekday, current_time = current_date.weekday(), current_date.time() + + for restaurant in restaurants: + + is_open = db.query( + models.OpeningHours).filter( + models.OpeningHours.place == restaurant["restaurant"], + models.OpeningHours.day == weekday, + models.OpeningHours.open_time <= current_time, + models.OpeningHours.close_time >= current_time).first() is not None + + if is_open: + count_prediction = 0 + cams_working = True + + for camera in restaurant["cameras"]: + cap = cv2.VideoCapture(f'rtsp://{camera["user"]}:{camera["password"]}@{camera["IP"]}/{camera["stream"]}') + if cap.isOpened(): + _, frame = cap.read() + masked_img = cv2.bitwise_and( + frame.astype(np.float32), camera["mask"]) + treated_img = fix_singular_shape(masked_img, 16) + input_image = np.expand_dims( + np.squeeze( + norm_by_imagenet( + np.array( + [treated_img]))), + axis=0) + pred_map = np.squeeze(model.predict(input_image)) + count_prediction += np.sum(pred_map) + else: + cams_working = False + cap.release() + + if cams_working: waiting_time = timedelta( - seconds=camera['b_factor'] + - int(count_prediction) * - camera['a_factor']) + seconds=restaurant['b_factor'] + + int(count_prediction * + restaurant['a_factor'])) db_record = models.Records( - place=camera['place'], - date=current_time, + place=restaurant['restaurant'], + date=current_date, density=int(count_prediction), waiting_time=waiting_time) db.add(db_record) db.commit() - manager.broadcast(json.dumps({"type": "data"})) - camera['count'] += 1 - else: - camera["cap"] = cv2.VideoCapture( - f"rtsp://{camera['user']}:{camera['password']}@{camera['IP']}/{camera['stream']}") - print("tentative de reconnexion") + await manager.broadcast(json.dumps({"type": "data"})) + print("owarida") + time.sleep(60 - time.time() + start_timestamp) -- GitLab