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 7ab3905e020cdd5faa01bc6f7e9d5f5fbd07dd7e..c8107378dada63bf4e092718fbe13b49905a3a2f 100644
--- a/README.md
+++ b/README.md
@@ -46,13 +46,9 @@ 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
-- Améliorer l'interface utilisateur avec le timer
 - Protéger l'interface OpenAPI et mettre en place une interface admin pour les news et potentiellement modération (avec authentification)
 - Permettre de définir les masques proprement et de manière à pouvoir généraliser à d'autre RU
 - Accorder la charte graphique si le service est intégré à d'autres appli (bordeau/blanc service de CS, charte graphique de VR)
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 64a1a8fcbd5950eaf1b41c43d368537466ae1655..853195a6872997706fa95c64a7d6d4b9ba37a8fb 100644
--- a/backend/db/crud.py
+++ b/backend/db/crud.py
@@ -505,7 +505,6 @@ def update_collaborative_record(user: schemas.User, db: Session):
     if last_record.date >= datetime.combine(date, time_slot.open_time) and not last_record.waiting_time:
         last_record.waiting_time = current_date - \
             pytz.timezone("Europe/Paris").localize(last_record.date)
-        print(last_record.waiting_time)
         db.add(last_record)
         db.commit()
         db.refresh(last_record)
@@ -514,6 +513,12 @@ def update_collaborative_record(user: schemas.User, db: Session):
     raise HTTPException(status_code=406, detail="Client already registered")
 
 
+def cancel_collaborative_record(user_id: int, db: Session):
+    db.query(models.CollaborativeRecords).filter(models.CollaborativeRecords.user_id == user_id).delete()
+    db.commit()
+    return
+
+
 def delete_collaborative_record(id: int, db: Session):
     if id == 0:
         db.query(models.CollaborativeRecords).delete()
diff --git a/backend/db/models.py b/backend/db/models.py
index 2f719cd94ba667400bb233ca1d3d73562ba99d04..1e6ad00d5a1b93a377d7a48501f89194ffa0f781 100644
--- a/backend/db/models.py
+++ b/backend/db/models.py
@@ -12,7 +12,7 @@ class CollaborativeRecords(Base):
     __tablename__ = "collection"
 
     id = Column(Integer, primary_key=True, index=True)
-    user_id = Column(Integer, ForeignKey("users.id"))
+    user_id = Column(Integer, ForeignKey("users.id", ondelete='SET NULL'))
     place = Column(String(30))
     date = Column(DateTime)
     waiting_time = Column(Interval)
diff --git a/backend/db/schemas.py b/backend/db/schemas.py
index 2042101f98e167167989f2ea0d52e7d918163951..757bfbd0dd438b3a0b7252fc301f97400a155621 100644
--- a/backend/db/schemas.py
+++ b/backend/db/schemas.py
@@ -33,7 +33,7 @@ class RecordRead(BaseModel):
 
 class CollaborativeRecords(BaseModel):
     """CollaborativeRecords schema"""
-    user_id: int = Field(..., title="Id of the user timed")
+    user_id: Optional[int] = Field(default=None, title="Id of the user timed")
     place: str = Field(..., title="Name of the RU corresponding the given record")
     date: datetime = Field(..., title="Date of the record")
     waiting_time: Optional[timedelta] = Field(default=None, title="Caculated waiting time for timed person")
diff --git a/backend/main.py b/backend/main.py
index 8a5b83204da713064c31881b4c61c5e3b3590164..82239f43f180564d4e73c65a4260c755e2aecf07 100644
--- a/backend/main.py
+++ b/backend/main.py
@@ -6,6 +6,7 @@ from fastapi.openapi.utils import get_openapi
 from sqlalchemy.orm import Session
 from dotenv import load_dotenv
 from threading import Thread
+from asyncio import run
 import os
 
 from db import database, models, crud
@@ -35,7 +36,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/routers/records.py b/backend/routers/records.py
index f6f603ac15e7bf7a8b87f5f4ee881f27edafc86f..04e4444b446a51a7b491fbd803a5b91c8385e819 100644
--- a/backend/routers/records.py
+++ b/backend/routers/records.py
@@ -54,6 +54,16 @@ async def end_new_record(response: Response, connect_id: str = Cookie(...), db:
     return db_record
 
 
+@router.post("/collection/cancel", response_model=None, tags=["data collection"])
+async def cancel_new_record(response: Response, connect_id: str = Cookie(...), db: Session = Depends(get_db)):
+    user = crud.get_user(connect_id, db)
+    db_record = crud.cancel_collaborative_record(user.id, db)
+    if not user.username:
+        crud.delete_user(user.cookie, db)
+        response.delete_cookie(key="connect_id")
+    return db_record
+
+
 @router.delete('/collection', response_model=None, tags=["data collection"])
 async def delete_record(id: int, db: Session = Depends(get_db)):
     return crud.delete_collaborative_record(id, db)
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()))
diff --git a/frontend/src/styles/restaurant.css b/frontend/src/styles/restaurant.css
index 639835729cd42edf8daed25f00d902c2948d236b..45fe9e89524ecd4a49310a82210501e428f180bb 100644
--- a/frontend/src/styles/restaurant.css
+++ b/frontend/src/styles/restaurant.css
@@ -12,43 +12,19 @@
     overflow: hidden;
 }
 
-#restaurant-start-button {
-    width: fit-content;
-    border: none;
-    border-radius: 5px;
-    padding: 0.1rem;
-    padding-left: 0.3rem;
-    padding-right: 0.3rem;
-    margin-top: 2rem;
-}
-
-.restaurant-button-disabled {
-    background-color: rgb(66, 75, 83);
-    color: #b9b9b9;
-}
-
-.restaurant-button-active {
+.restaurant-button {
     background-color: rgb(33, 37, 41);
     color: white;
-}
-
-.restaurant-button-active:hover {
-    box-shadow: 0px 0px 5px white;
-}
-
-#restaurant-end-button {
-    width: fit-content;
-    background-color: #83000d;
-    color: white;
+    width: 7rem;
     border: none;
     border-radius: 5px;
-    padding: 0.1rem;
+    padding: 0.2rem;
     padding-left: 0.3rem;
     padding-right: 0.3rem;
     margin-top: 2rem;
 }
 
-#restaurant-end-button:hover {
+.restaurant-button:hover {
     box-shadow: 0px 0px 5px rgb(33, 37, 41);
 }
 
diff --git a/frontend/src/views/Restaurant.js b/frontend/src/views/Restaurant.js
index f4113205874ed501e30af255efe95cdf3a7a884a..fa5701876ad200f5998d841408938c5bfabc996a 100644
--- a/frontend/src/views/Restaurant.js
+++ b/frontend/src/views/Restaurant.js
@@ -12,7 +12,7 @@ import "../styles/restaurant.css";
 
 export default function RestaurantPage({ selection, lastMessage }) {
   // const [started, setStarted] = useState(false);
-  // const [disabled, setDisabled] = useState(false);
+  // const [timed, setTimed] = useState(false);
 
   // const Start = () => {
   //   instance
@@ -21,7 +21,7 @@ export default function RestaurantPage({ selection, lastMessage }) {
   //       setStarted(true);
   //     })
   //     .catch((e) => {
-  //       setDisabled(true);
+  //       setTimed(true);
   //       alert(
   //         "Il semblerait que tu aies déjà renseigné un temps d'attente sur ce créneau. Merci de ta participation, n'hésite pas à te chronométrer de nouveau la prochaine fois !",
   //       );
@@ -34,10 +34,10 @@ export default function RestaurantPage({ selection, lastMessage }) {
   //     .post("collection/stop")
   //     .then(() => {
   //       setStarted(false);
-  //       setDisabled(true);
+  //       setTimed(true);
   //     })
   //     .catch((e) => {
-  //       setDisabled(true);
+  //       setTimed(true);
   //       alert(
   //         "Il semblerait que tu aies déjà renseigné un temps d'attente sur ce créneau. Merci de ta participation, n'hésite pas à te chronométrer de nouveau la prochaine fois !",
   //       );
@@ -45,6 +45,20 @@ export default function RestaurantPage({ selection, lastMessage }) {
   //     });
   // };
 
+  // const Cancel = () => {
+  //   instance
+  //     .post("collection/cancel")
+  //     .then(() => {
+  //       setStarted(false);
+  //       setTimed(false);
+  //     })
+  //     .catch((e) => {
+  //       setStarted(false);
+  //       setTimed(false);
+  //       console.log(e);
+  //     });
+  // };
+
   return (
     <>
       {selection && (
@@ -52,18 +66,26 @@ export default function RestaurantPage({ selection, lastMessage }) {
           <Comments place={selection.name} lastMessage={lastMessage} infos />
           <div className="restaurant-container" id="restaurant-main-page">
             <WaitingTime place={selection.name} lastMessage={lastMessage} />
-            <Graph place={selection.name} type="current" lastMessage={lastMessage} />
-            {/* <button
-              id={`restaurant-${started ? "end" : "start"}-button`}
-              onClick={started ? End : Start}
-              className={disabled ? "restaurant-button-disabled" : "restaurant-button-active"}
-              disabled={disabled}
-            >
-              {started ? "Fini !!" : "Départ !!"}
-            </button> */}
+            <Graph place={selection.name} lastMessage={lastMessage} />
+            {/* <div style={{ fontSize: "1.2rem", paddingLeft: "10%", paddingRight: "10%" }}>
+              {timed
+                ? "Merci de ta participation, n'hésite pas à te chronométrer de nouveau la prochaine fois !"
+                : "Aide nous à récupérer des données en te chronométrant dans la queue du self !"}
+            </div>
+            {!timed && (
+              <>
+                <button onClick={started ? End : Start} className="restaurant-button">
+                  {started ? "Fini !" : "Démarrer !"}
+                </button>
+                {started && (
+                  <button onClick={Cancel} className="restaurant-button">
+                    Annuler
+                  </button>
+                )}
+              </>
+            )} */}
           </div>
           <Comments place={selection.name} lastMessage={lastMessage} />
-          {/*<Graph place={selection.name} type="avg" />*/}
         </div>
       )}
     </>
diff --git a/photo_camera/1er_etage_milieu.jpg b/photo_camera/1er_etage_milieu.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..df32ba4b2d5d01b9c87b482cb41dceae006c36da
Binary files /dev/null and b/photo_camera/1er_etage_milieu.jpg differ
diff --git a/photo_camera/1er_etage_milieu_2.jpg b/photo_camera/1er_etage_milieu_2.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..68613e1e5ae106df19af90c63fc98f05dba30c1a
Binary files /dev/null and b/photo_camera/1er_etage_milieu_2.jpg differ
diff --git a/photo_camera/1er_etage_milieu_retourne.jpg b/photo_camera/1er_etage_milieu_retourne.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..4d93f4c1c17cb1d2de91bda94bd8ebecf286aa02
Binary files /dev/null and b/photo_camera/1er_etage_milieu_retourne.jpg differ
diff --git a/photo_camera/2eme_etage_angle.jpg b/photo_camera/2eme_etage_angle.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..bc7e04e4d12c009e0229d24004bd2c44cd4a027b
Binary files /dev/null and b/photo_camera/2eme_etage_angle.jpg differ
diff --git a/photo_camera/2eme_etage_milieu.jpg b/photo_camera/2eme_etage_milieu.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..2963d2f25080038a2e92fd8cbc302edd542a7b30
Binary files /dev/null and b/photo_camera/2eme_etage_milieu.jpg differ
diff --git a/photo_camera/2eme_etage_milieu_2.jpg b/photo_camera/2eme_etage_milieu_2.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..397477651cd0d370e737a5ed47012d28257fcf17
Binary files /dev/null and b/photo_camera/2eme_etage_milieu_2.jpg differ