Skip to content
Snippets Groups Projects
Commit 360c4dd2 authored by Antoine Gaudron-Desjardins's avatar Antoine Gaudron-Desjardins
Browse files

merge video-capture

parents 52e614e4 7805e359
No related branches found
No related tags found
1 merge request!37rtsp video capture setup
Pipeline #44182 passed
......@@ -12,3 +12,22 @@ CLIENT_SECRET=
API_ROOT=http://localhost:3001/api
WEB_ROOT=http://localhost:3000
AUTH_ROOT=https://auth.viarezo.fr
CAM_NUMBER=1
CAM_0_PLACE=local
CAM_0_IP=
CAM_0_USER=
CAM_0_PASSWORD=
CAM_0_STREAM=stream1
CAM_0_A_FACTOR=30
CAM_0_B_FACTOR=120
CAM_0_FRAMEGAP=150
CAM_0_POINTS_NB=7
CAM_0_POINT_0=70, 370
CAM_0_POINT_1=420, 720
CAM_0_POINT_2=1280, 720
CAM_0_POINT_3=1280, 250
CAM_0_POINT_4=930, 215
CAM_0_POINT_5=450, 550
CAM_0_POINT_6=130, 350
\ No newline at end of file
......@@ -20,7 +20,8 @@ def get_waiting_time(place: str, db: Session):
data = {"status": False, "waiting_time": None, "next_timetable": None}
first_timeslot = get_timeslot(place, weekday, True, db)
if first_timeslot and current_time < first_timeslot[0]:
data["next_timetable"] = "{:d}h{:02d}".format(first_timeslot[0].hour, first_timeslot[0].minute)
data["next_timetable"] = "{:d}h{:02d}".format(
first_timeslot[0].hour, first_timeslot[0].minute)
return data
elif first_timeslot and current_time <= first_timeslot[1]:
last_record = db.query(
......@@ -38,7 +39,8 @@ def get_waiting_time(place: str, db: Session):
return data
second_timeslot = get_timeslot(place, weekday, False, db)
if second_timeslot and current_time < second_timeslot[0]:
data["next_timetable"] = "{:d}h{:02d}".format(second_timeslot[0].hour, second_timeslot[0].minute)
data["next_timetable"] = "{:d}h{:02d}".format(
second_timeslot[0].hour, second_timeslot[0].minute)
return data
elif second_timeslot and current_time <= second_timeslot[1]:
last_record = db.query(
......@@ -57,7 +59,8 @@ def get_waiting_time(place: str, db: Session):
return data
def get_avg_graph_points(place: str, weekday: int, min_time: time, max_time: time, interval: timedelta, db: Session):
def get_avg_graph_points(place: str, weekday: int, min_time: time,
max_time: time, interval: timedelta, db: Session):
""" Get the average waiting time for each interval between two time steps """
def shift_time(t: time, delta: timedelta):
......@@ -107,14 +110,16 @@ def get_avg_graph(place: str, db: Session):
weekday, current_time = current_date.weekday(), current_date.time()
first_timeslot = get_timeslot(place, weekday, True, db)
if first_timeslot and current_time <= first_timeslot[1]:
return get_avg_graph_points(place, weekday, first_timeslot[0], first_timeslot[1], timedelta(minutes=5), db)
return get_avg_graph_points(
place, weekday, first_timeslot[0], first_timeslot[1], timedelta(minutes=5), db)
second_timeslot = get_timeslot(place, weekday, False, db)
if second_timeslot and current_time <= second_timeslot[1]:
return get_avg_graph_points(place, weekday, second_timeslot[0], second_timeslot[1], timedelta(minutes=5), db)
return []
def get_current_graph_points(place: str, current_date: date, min_time: time, max_time: time, interval: timedelta, db: Session):
def get_current_graph_points(place: str, current_date: date,
min_time: time, max_time: time, interval: timedelta, db: Session):
""" Get the waiting time for each interval between two time steps for the current timeslot """
def shift_time(t: time, delta: timedelta):
......@@ -162,7 +167,8 @@ def get_current_graph_points(place: str, current_date: date, min_time: time, max
def get_current_graph(place: str, db: Session):
""" Get the waiting_time_graph for the current timeslot"""
current_date = datetime.now(tz=pytz.timezone("Europe/Paris"))
weekday, day, current_time = current_date.weekday(), current_date.date(), current_date.time()
weekday, day, current_time = current_date.weekday(
), current_date.date(), current_date.time()
first_timeslot = get_timeslot(place, weekday, True, db)
if first_timeslot and current_time <= first_timeslot[0]:
return [], None, None
......@@ -187,7 +193,10 @@ def get_current_graph(place: str, db: Session):
def get_comments(place: str, page: int, db: Session):
""" Get the 20 last comments for the given place """
if page == 0:
comments = db.query(models.Comments).order_by(models.Comments.published_at.desc(), models.Comments.id.desc()).all()
comments = db.query(
models.Comments).order_by(
models.Comments.published_at.desc(),
models.Comments.id.desc()).all()
else:
comments = db.query(
models.Comments,
......@@ -227,7 +236,10 @@ def delete_comment(id: int, db: Session):
def get_news(place: str, db: Session):
""" Get the news for the given place """
news = db.query(models.News).filter(models.News.place == place).order_by(models.News.published_at.desc()).all()
news = db.query(
models.News).filter(
models.News.place == place).order_by(
models.News.published_at.desc()).all()
return news
......@@ -277,7 +289,8 @@ def get_timeslot(place: str, day: int, timeslot: bool, db: Session):
return opening_hours
def create_opening_hours(new_opening_hours: schemas.OpeningHoursBase, db: Session):
def create_opening_hours(
new_opening_hours: schemas.OpeningHoursBase, db: Session):
""" Add opening hours to the database """
db_opening_hours = models.OpeningHours(**new_opening_hours.dict())
db.add(db_opening_hours)
......@@ -291,7 +304,9 @@ def delete_opening_hours(id: int, db: Session):
if id == 0:
db.query(models.OpeningHours).delete()
else:
db.query(models.OpeningHours).filter(models.OpeningHours.id == id).delete()
db.query(
models.OpeningHours).filter(
models.OpeningHours.id == id).delete()
db.commit()
......@@ -300,7 +315,9 @@ def delete_opening_hours(id: int, db: Session):
def get_restaurants(db: Session):
current_date = datetime.now(tz=pytz.timezone("Europe/Paris"))
weekday, current_time = current_date.weekday(), current_date.time()
restaurant_names = [r.place for r in db.query(models.OpeningHours.place).distinct()]
restaurant_names = [
r.place for r in db.query(
models.OpeningHours.place).distinct()]
restaurants = []
for name in restaurant_names:
......@@ -338,7 +355,8 @@ def get_restaurants(db: Session):
).first()
if last_record:
waiting_time = last_record.waiting_time
restaurant["waiting_time"] = round(waiting_time.total_seconds() / 60)
restaurant["waiting_time"] = round(
waiting_time.total_seconds() / 60)
else:
restaurant["waiting_time"] = None
else:
......
......@@ -8,10 +8,12 @@ from pydantic import BaseModel, Field
class RecordBase(BaseModel):
"""Records base schema"""
place: str = Field(..., title="Name of the RU corresponding the given record")
place: str = Field(...,
title="Name of the RU corresponding the given record")
date: datetime = Field(..., title="Date of the record")
density: float = Field(..., title="Estimated density of people")
waiting_time: Optional[timedelta] = Field(title="Estimated waiting time for people coming at this date")
waiting_time: Optional[timedelta] = Field(
title="Estimated waiting time for people coming at this date")
class Record(RecordBase):
......@@ -57,9 +59,11 @@ class News(NewsBase):
class OpeningHoursBase(BaseModel):
"""Database opening_hours base schema"""
place: str = Field(..., title="Name of the RU corresponding the given record")
place: str = Field(...,
title="Name of the RU corresponding the given record")
day: int = Field(..., title="Day of the week")
timeslot: bool = Field(..., title="Service slot (True for midday, False for evening)")
timeslot: bool = Field(...,
title="Service slot (True for midday, False for evening)")
open_time: time = Field(..., title="Opening time")
close_time: time = Field(..., title="Closing time")
......
......@@ -7,9 +7,11 @@ from fastapi import Depends
from sqlalchemy.orm import Session
from db import schemas
from typing import List
from threading import Thread
from db import database, models
from routers import *
from video_capture import handle_cameras
app = FastAPI(docs_url="/api/docs", openapi_url="/api/openapi.json")
......@@ -30,9 +32,11 @@ app.add_middleware(
@app.on_event("startup")
def on_startup():
async def on_startup():
# Database creation
models.Base.metadata.create_all(bind=database.engine)
t = Thread(target=handle_cameras)
t.start()
# Integration of routers
......@@ -44,7 +48,8 @@ app.include_router(authentication.router)
@app.get('/api/records', response_model=List[schemas.Record])
async def get_records(place: str, db: Session = Depends(get_db)):
return db.query(models.Records).filter(models.Records.place == place).order_by(models.Records.date.desc()).all()
return db.query(models.Records).filter(models.Records.place ==
place).order_by(models.Records.date.desc()).all()
@app.post('/api/records', response_model=schemas.Record)
......@@ -64,39 +69,3 @@ async def del_records(id: int, db: Session = Depends(get_db)):
db.query(models.Records).filter(models.Records.id == id).delete()
db.commit()
return
"""
import cv2
import numpy as np
import keras
from utils.preprocessing import fix_singular_shape, norm_by_imagenet
model = keras.models.load_model('model')
# contours of the zone of a picture that should be analyzed by the model
contours = {
'eiffel': [[70, 370], [420, 720], [1280, 720], [1280, 250], [930, 215], [450, 550], [130, 350]]
}
masks = {}
for key, polygon in contours.items():
mask = np.zeros((1280, 720, 3), dtype=np.unit8)
cv2.fillPoly(mask, [polygon], (255, 255, 255))
masks[key] = mask
@app.get("/estimate/{id}")
async def estimate_(id: str) -> float:
# img = fetch(...)
img = np.zeros((1280, 720, 3))
resized_img = cv2.cvtColor(cv2.resize(img, (1280, 720)), cv2.COLOR_BGR2RGB).astype(np.float32)
masked_img = cv2.bitwise_and(resized_img, mask[id])
treated_img = fix_singular_shape(masked_img, 16)
input_image = np.expand_dims(np.squeeze(norm_by_imagenet([treated_img])), axis=0)
pred_map = np.squeeze(model.predict(input_image))
count_prediction = np.sum(pred_map)
return count_prediction
"""
......@@ -24,12 +24,14 @@ async def stats(place: str, db: Session = Depends(get_db)):
return crud.get_current_graph(place, db)
@router.get('/{place}/opening_hours', response_model=List[schemas.OpeningHours])
@router.get('/{place}/opening_hours',
response_model=List[schemas.OpeningHours])
async def get_opening_hours(place: str, db: Session = Depends(get_db)):
return crud.get_opening_hours(place, db)
@router.get('/{place}/opening_hours/{day}/{timeslot}', response_model=List[schemas.OpeningHours])
@router.get('/{place}/opening_hours/{day}/{timeslot}',
response_model=List[schemas.OpeningHours])
async def get_timeslot(place: str, day: int, timeslot: bool, db: Session = Depends(get_db)):
return crud.get_timeslot(place, day, timeslot, db)
......
import cv2
from datetime import datetime, timedelta
import numpy as np
import keras
from utils.preprocessing import fix_singular_shape, norm_by_imagenet
from db import models
from db.database import SessionLocal
db = SessionLocal()
model = keras.models.load_model('assets')
cap = cv2.VideoCapture("rtsp://viarezocam:superponey@10.148.38.9/stream1")
count = 0
frame_gap = 450
while(cap.isOpened()):
ret, frame = cap.read()
if ret and count % frame_gap == 0:
current_time = datetime.now()
treated_img = fix_singular_shape(frame, 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)
waiting_time = timedelta(seconds=120 + count_prediction * 30)
record = {"place": "local",
"date": current_time,
"density": count_prediction,
"waiting_time": waiting_time}
db_record = models.Records(**record)
db.add(db_record)
db.commit()
db.refresh(db_record)
count += 1
cap.release()
cv2.destroyAllWindows()
import cv2
from datetime import datetime, timedelta
import numpy as np
import keras
from utils.preprocessing import fix_singular_shape, norm_by_imagenet
from db import models
from dotenv import load_dotenv
import os
from db.database import SessionLocal
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)
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)
print(count_prediction)
waiting_time = timedelta(
seconds=camera['b_factor'] +
int(count_prediction) *
camera['a_factor'])
db_record = models.Records(
place=camera['place'],
date=current_time,
density=int(count_prediction),
waiting_time=waiting_time)
db.add(db_record)
db.commit()
db.refresh(db_record)
camera['count'] += 1
else:
camera["cap"] = cv2.VideoCapture(
f"rtsp://{camera['user']}:{camera['password']}@{camera['IP']}/{camera['stream']}")
print("tentative de reconnexion")
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment