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