diff --git a/.gitignore b/.gitignore
index de88a2b3adcdd604db49c8ff544b4427e4f935e9..a17152a7e7ce9d3f563aa4472d25aa817a7d29ef 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/README.md b/README.md
index 6be0232a3f8b924143ae4d7b56a5d0aef8aae9c7..c8107378dada63bf4e092718fbe13b49905a3a2f 100644
--- a/README.md
+++ b/README.md
@@ -46,9 +46,6 @@ Navigate to [http://localhost:3000](http://localhost:3000)
 
 # TODO
 ## Coté algo
-- Faire tournez le script de comptage que pendant les créneaux d'ouvertures du RU associé
-- Mettre en place le script pour compter les caisses ouvertes
-- Mettre en place le couplage des caméras (implique de pouvoir définir les masques proprement) dans le script de comptage de personnes
 - Accéder à d'autre infos telle que l'API des cours sur demande à la DISI pour intégrer ça aux prédictions (ex: cours en promo complète juste implique plus d'attente)
 
 ## Coté dev
diff --git a/backend/cameras.py.template b/backend/cameras.py.template
new file mode 100644
index 0000000000000000000000000000000000000000..5d197e572134b2e9d63518bcbcd5a227ee42bde0
--- /dev/null
+++ b/backend/cameras.py.template
@@ -0,0 +1,43 @@
+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]
+                            ]
+                        ],
+                    "caisses":
+                        [
+                            {
+                                "x1": 380,
+                                "x2": 435,
+                                "y1": 740,
+                                "y2": 780
+                            },
+                            {
+                                "x1": 300,
+                                "x2": 350,
+                                "y1": 830,
+                                "y2": 880
+                            }
+                        ]
+                }
+            ]
+    }
+]
diff --git a/backend/db/crud.py b/backend/db/crud.py
index df872ffc41042fd3a602dcdb7dcd8fccb57b2130..a856d45a090291fc14ce11865323dec349e15d31 100644
--- a/backend/db/crud.py
+++ b/backend/db/crud.py
@@ -231,7 +231,7 @@ def get_news(place: str, db: Session):
     next_timetable = None
     for time_slot in opening_hours:
         if current_date.time() < time_slot.open_time:
-            next_timetable=time_slot.open_time
+            next_timetable = time_slot.open_time
             break
     if not next_timetable:
         closure = db.query(
diff --git a/backend/main.py b/backend/main.py
index d6c986ac7a837ba1f558c9d386bfb257ded706f8..ba7a7273e7fbcd7de70ec586c1bd11c248187224 100644
--- a/backend/main.py
+++ b/backend/main.py
@@ -2,6 +2,7 @@ from fastapi import FastAPI
 from fastapi.middleware.cors import CORSMiddleware
 from dotenv import load_dotenv
 from threading import Thread
+from asyncio import run
 import os
 
 from db import database, models
@@ -30,7 +31,7 @@ app.add_middleware(
 async def on_startup():
     # Database creation
     models.Base.metadata.create_all(bind=database.engine)
-    t = Thread(target=handle_cameras)
+    t = Thread(target=run, args=(handle_cameras(),))
     t.start()
 
 
diff --git a/backend/video_capture.py b/backend/video_capture.py
index 9806146f1aad3258b8e71d350cf91b4c6093d04f..08cf8533470937c824551fdf2c7e28441e7858e8 100644
--- a/backend/video_capture.py
+++ b/backend/video_capture.py
@@ -3,75 +3,76 @@ 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)
+
+        current_date = datetime.now()
+        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
+                open_checkouts = 0
+                cams_working = True
+
+                for camera in restaurant["cameras"]:
+                    cap = cv2.VideoCapture(f'rtsp://{camera["user"]}:{camera["password"]}@{camera["IP"]}/{camera["stream"]}')
+                    if cams_working and 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, verbose=0))
+                        count_prediction += np.sum(pred_map)
+                        for caisse in camera["caisses"]:
+                            if np.sum(pred_map[caisse["x1"] // 2:caisse["x2"] // 2, caisse["y1"] // 2:caisse["y2"] // 2]) > 0.5:
+                                open_checkouts += 1
+                    else:
+                        cams_working = False
+                    cap.release()
+
+                if cams_working and open_checkouts:
                     waiting_time = timedelta(
-                        seconds=camera['b_factor'] +
-                        int(count_prediction) *
-                        camera['a_factor'])
+                        seconds=restaurant['b_factor'] +
+                        int(count_prediction *
+                            restaurant['a_factor'] / open_checkouts))
                     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"}))
+        time.sleep(max(0, 60 - (datetime.now() - current_date).total_seconds()))