Skip to content
Snippets Groups Projects
Commit cfe0c824 authored by Aymeric Chaumont's avatar Aymeric Chaumont
Browse files

moving camera vars in .env and making the code better

parent 17b7a43a
Branches
No related tags found
1 merge request!37rtsp video capture setup
Pipeline #44173 passed with warnings
......@@ -7,3 +7,22 @@ DB_HOST=localhost
DB_PORT=3306
WEB_ROOT=http://localhost:3000
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
......@@ -18,7 +18,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(
......@@ -36,7 +37,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(
......@@ -55,7 +57,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):
......@@ -105,14 +108,17 @@ 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 get_avg_graph_points(
place, weekday, second_timeslot[0], second_timeslot[1], timedelta(minutes=5), db)
return None
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):
......@@ -160,17 +166,20 @@ 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 []
elif first_timeslot and current_time <= first_timeslot[1]:
return get_current_graph_points(place, day, first_timeslot[0], current_time, timedelta(minutes=5), db)
return get_current_graph_points(
place, day, first_timeslot[0], current_time, timedelta(minutes=5), db)
second_timeslot = get_timeslot(place, weekday, False, db)
if second_timeslot and current_time <= second_timeslot[0]:
return []
elif second_timeslot and current_time <= second_timeslot[1]:
return get_current_graph_points(place, day, second_timeslot[0], current_time, timedelta(minutes=5), db)
return get_current_graph_points(
place, day, second_timeslot[0], current_time, timedelta(minutes=5), db)
return []
......@@ -179,7 +188,10 @@ def get_current_graph(place: str, db: Session):
def get_comments(place: str, page: int, db: Session):
""" Get the 10 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).filter(
......@@ -197,7 +209,10 @@ def get_comments(place: str, page: int, db: Session):
def create_comment(place: str, new_comments: schemas.CommentBase, db: Session):
""" Add a new comment to the database """
date = datetime.now(tz=pytz.timezone("Europe/Paris"))
db_comment = models.Comments(**new_comments.dict(), published_at=date, place=place)
db_comment = models.Comments(
**new_comments.dict(),
published_at=date,
place=place)
db.add(db_comment)
db.commit()
db.refresh(db_comment)
......@@ -217,7 +232,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
......@@ -267,7 +285,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)
......@@ -281,7 +300,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()
......@@ -290,7 +311,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:
......@@ -328,7 +351,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):
......@@ -30,7 +32,8 @@ class CommentBase(BaseModel):
class Comment(CommentBase):
"""Database comments base schema"""
id: int
published_at: datetime = Field(..., title="Publication date of the comment")
published_at: datetime = Field(...,
title="Publication date of the comment")
place: str = Field(..., title="Name of the RU corresponding the comment")
class Config:
......@@ -56,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")
......
from venv import create
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from dotenv import load_dotenv
......@@ -7,9 +8,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 stats, comments, news
from video_capture import handle_cameras
app = FastAPI(docs_url="/api/docs", openapi_url="/api/openapi.json")
......@@ -30,9 +33,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
......@@ -43,7 +48,8 @@ app.include_router(news.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)
......@@ -63,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
"""
......@@ -9,12 +9,14 @@ from db.database import get_db
router = APIRouter(prefix="/api", tags=["opening_hours"])
@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)
......
......@@ -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')
frame_gap = 450
cameras = [{
"place": "local",
"IP": "10.148.38.9",
"user": "viarezocam",
"password": "superponey",
"stream": "stream1",
"framegap": 900, # 60 * camera frequency
"count": 0, # mandatory
"cap": None
}]
for camera in cameras:
camera.cap = cv2.VideoCapture(f"rtsp://{camera.user}:{camera.password}@{camera.ip}/{camera.stream}")
while True:
for camera in cameras:
if camera.cap.isOpened():
ret, frame = camera.cap.read()
if ret and camera.count % camera.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": camera.place,
"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)
camera.count += 1
else:
camera.cap.release()
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