mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-05 18:55:23 +03:00
Calculate possible layout
This commit is contained in:
parent
d3949eebfa
commit
9216a99b14
@ -8,6 +8,7 @@ import queue
|
|||||||
import signal
|
import signal
|
||||||
import subprocess as sp
|
import subprocess as sp
|
||||||
import threading
|
import threading
|
||||||
|
import traceback
|
||||||
from wsgiref.simple_server import make_server
|
from wsgiref.simple_server import make_server
|
||||||
|
|
||||||
import cv2
|
import cv2
|
||||||
@ -250,8 +251,8 @@ class BirdsEyeFrameManager:
|
|||||||
|
|
||||||
copy_yuv_to_position(
|
copy_yuv_to_position(
|
||||||
self.frame,
|
self.frame,
|
||||||
self.layout_offsets[position],
|
[position[1], position[0]],
|
||||||
self.layout_frame_shape,
|
[position[3], position[2]],
|
||||||
frame,
|
frame,
|
||||||
channel_dims,
|
channel_dims,
|
||||||
)
|
)
|
||||||
@ -267,6 +268,46 @@ class BirdsEyeFrameManager:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def update_frame(self):
|
def update_frame(self):
|
||||||
|
def calculate_layout(
|
||||||
|
canvas, cameras_to_add: list[str], coefficient
|
||||||
|
) -> tuple[any]:
|
||||||
|
camera_layout: list[list[any]] = []
|
||||||
|
camera_layout.append([])
|
||||||
|
x = 0
|
||||||
|
x_i = 0
|
||||||
|
y = 0
|
||||||
|
y_i = 0
|
||||||
|
max_height = 0
|
||||||
|
for camera in cameras_to_add:
|
||||||
|
detect_config = self.config.cameras[camera].detect
|
||||||
|
|
||||||
|
if self.config.cameras[camera].detect.width * coefficient <= canvas[0]:
|
||||||
|
# insert if camera can fit on current row
|
||||||
|
camera_layout[y_i].append(
|
||||||
|
(
|
||||||
|
camera,
|
||||||
|
(x, y, detect_config.width, detect_config.height),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
x += detect_config.width
|
||||||
|
max_height = max(max_height, detect_config.height)
|
||||||
|
else:
|
||||||
|
# move on to the next row and insert
|
||||||
|
y = max_height
|
||||||
|
y_i += 1
|
||||||
|
camera_layout.append([])
|
||||||
|
x = 0
|
||||||
|
x_i = 0
|
||||||
|
camera_layout[y_i].append(
|
||||||
|
(
|
||||||
|
camera,
|
||||||
|
(x, y, detect_config.width, detect_config.height),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
x += detect_config.width
|
||||||
|
|
||||||
|
return (camera_layout, y + max_height)
|
||||||
|
|
||||||
# determine how many cameras are tracking objects within the last 30 seconds
|
# determine how many cameras are tracking objects within the last 30 seconds
|
||||||
active_cameras = set(
|
active_cameras = set(
|
||||||
[
|
[
|
||||||
@ -337,63 +378,39 @@ class BirdsEyeFrameManager:
|
|||||||
|
|
||||||
# this also converts added_cameras from a set to a list since we need
|
# this also converts added_cameras from a set to a list since we need
|
||||||
# to pop elements in order
|
# to pop elements in order
|
||||||
added_cameras = sorted(
|
active_cameras_to_add = sorted(
|
||||||
added_cameras,
|
active_cameras,
|
||||||
# sort cameras by order and by name if the order is the same
|
# sort cameras by order and by name if the order is the same
|
||||||
key=lambda added_camera: (
|
key=lambda active_camera: (
|
||||||
self.config.cameras[added_camera].birdseye.order,
|
self.config.cameras[active_camera].birdseye.order,
|
||||||
added_camera,
|
active_camera,
|
||||||
),
|
),
|
||||||
# we're popping out elements from the end, so this needs to be reverse
|
# we're popping out elements from the end, so this needs to be reverse
|
||||||
# as we want the last element to be the first
|
# as we want the last element to be the first
|
||||||
reverse=True,
|
reverse=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
# update each position in the layout
|
canvas_width = self.frame_shape[1]
|
||||||
for position, camera in enumerate(self.camera_layout, start=0):
|
canvas_height = self.frame_shape[0]
|
||||||
# if this camera was removed, replace it or clear it
|
coefficient = 1
|
||||||
if camera in removed_cameras:
|
|
||||||
# if replacing this camera with a newly added one
|
layout_candidate, total_height = calculate_layout(
|
||||||
if len(added_cameras) > 0:
|
(canvas_width, canvas_height), active_cameras_to_add, coefficient
|
||||||
added_camera = added_cameras.pop()
|
)
|
||||||
self.camera_layout[position] = added_camera
|
|
||||||
self.copy_to_position(
|
if total_height > canvas_height:
|
||||||
position,
|
coefficient = canvas_height / total_height
|
||||||
added_camera,
|
layout_candidate = calculate_layout(
|
||||||
self.cameras[added_camera]["current_frame"],
|
(canvas_width, canvas_height), active_cameras_to_add, coefficient
|
||||||
)
|
)
|
||||||
self.cameras[added_camera]["layout_frame"] = self.cameras[
|
|
||||||
added_camera
|
self.camera_layout = layout_candidate
|
||||||
]["current_frame"]
|
|
||||||
# if removing this camera with no replacement
|
for row in self.camera_layout:
|
||||||
else:
|
for position in row:
|
||||||
self.camera_layout[position] = None
|
|
||||||
self.copy_to_position(position)
|
|
||||||
removed_cameras.remove(camera)
|
|
||||||
# if an empty spot and there are cameras to add
|
|
||||||
elif camera is None and len(added_cameras) > 0:
|
|
||||||
added_camera = added_cameras.pop()
|
|
||||||
self.camera_layout[position] = added_camera
|
|
||||||
self.copy_to_position(
|
self.copy_to_position(
|
||||||
position,
|
position[1], position[0], self.cameras[position[0]]["current_frame"]
|
||||||
added_camera,
|
|
||||||
self.cameras[added_camera]["current_frame"],
|
|
||||||
)
|
)
|
||||||
self.cameras[added_camera]["layout_frame"] = self.cameras[added_camera][
|
|
||||||
"current_frame"
|
|
||||||
]
|
|
||||||
# if not an empty spot and the camera has a newer frame, copy it
|
|
||||||
elif (
|
|
||||||
camera is not None
|
|
||||||
and self.cameras[camera]["current_frame"]
|
|
||||||
!= self.cameras[camera]["layout_frame"]
|
|
||||||
):
|
|
||||||
self.copy_to_position(
|
|
||||||
position, camera, self.cameras[camera]["current_frame"]
|
|
||||||
)
|
|
||||||
self.cameras[camera]["layout_frame"] = self.cameras[camera][
|
|
||||||
"current_frame"
|
|
||||||
]
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -523,19 +540,23 @@ def output_frames(config: FrigateConfig, video_output_queue):
|
|||||||
for ws in websocket_server.manager
|
for ws in websocket_server.manager
|
||||||
)
|
)
|
||||||
):
|
):
|
||||||
if birdseye_manager.update(
|
try:
|
||||||
camera,
|
if birdseye_manager.update(
|
||||||
len([o for o in current_tracked_objects if not o["stationary"]]),
|
camera,
|
||||||
len(motion_boxes),
|
len([o for o in current_tracked_objects if not o["stationary"]]),
|
||||||
frame_time,
|
len(motion_boxes),
|
||||||
frame,
|
frame_time,
|
||||||
):
|
frame,
|
||||||
frame_bytes = birdseye_manager.frame.tobytes()
|
):
|
||||||
|
frame_bytes = birdseye_manager.frame.tobytes()
|
||||||
|
|
||||||
if config.birdseye.restream:
|
if config.birdseye.restream:
|
||||||
birdseye_buffer[:] = frame_bytes
|
birdseye_buffer[:] = frame_bytes
|
||||||
|
|
||||||
converters["birdseye"].write(frame_bytes)
|
converters["birdseye"].write(frame_bytes)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Crash happened :: {e}")
|
||||||
|
logger.error(traceback.format_exc())
|
||||||
|
|
||||||
if camera in previous_frames:
|
if camera in previous_frames:
|
||||||
frame_manager.delete(f"{camera}{previous_frames[camera]}")
|
frame_manager.delete(f"{camera}{previous_frames[camera]}")
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user