* Don't allow editing of sub label until object lifecycle has ended

* Update sub labels in ended review segments

When manually editing a sub label for a tracked object from the UI, any review segments containing that tracked object did not have their sub_labels and objects values altered

* simplify

* Additional onvif debug logs in get_camera_status

* Ensure that best object is only set when the snapshot is actually updated.

* Don't hide downlaod button when there is no review item

---------

Co-authored-by: Nicolas Mowen <nickmowen213@gmail.com>
This commit is contained in:
Josh Hawkins
2025-06-23 18:40:21 -05:00
committed by GitHub
parent 8a9ebe9292
commit cc368dd20f
4 changed files with 114 additions and 40 deletions

View File

@@ -11,7 +11,7 @@ from typing import Any
import cv2
import numpy as np
from peewee import DoesNotExist
from peewee import SQL, DoesNotExist
from frigate.camera.state import CameraState
from frigate.comms.config_updater import ConfigSubscriber
@@ -29,9 +29,13 @@ from frigate.config import (
RecordConfig,
SnapshotsConfig,
)
from frigate.const import FAST_QUEUE_TIMEOUT, UPDATE_CAMERA_ACTIVITY
from frigate.const import (
FAST_QUEUE_TIMEOUT,
UPDATE_CAMERA_ACTIVITY,
UPSERT_REVIEW_SEGMENT,
)
from frigate.events.types import EventStateEnum, EventTypeEnum
from frigate.models import Event, Timeline
from frigate.models import Event, ReviewSegment, Timeline
from frigate.track.tracked_object import TrackedObject
from frigate.util.image import SharedMemoryFrameManager
@@ -152,7 +156,7 @@ class TrackedObjectProcessor(threading.Thread):
)
)
def snapshot(camera, obj: TrackedObject, frame_name: str):
def snapshot(camera: str, obj: TrackedObject) -> bool:
mqtt_config: CameraMqttConfig = self.config.cameras[camera].mqtt
if mqtt_config.enabled and self.should_mqtt_snapshot(camera, obj):
jpg_bytes = obj.get_img_bytes(
@@ -185,6 +189,10 @@ class TrackedObjectProcessor(threading.Thread):
retain=True,
)
return True
return False
def camera_activity(camera, activity):
last_activity = self.camera_activity.get(camera)
@@ -357,6 +365,60 @@ class TrackedObjectProcessor(threading.Thread):
data=Timeline.data.update({"sub_label": (sub_label, score)})
).where(Timeline.source_id == event_id).execute()
# only update ended review segments
# manually updating a sub_label from the UI is only possible for ended tracked objects
try:
review_segment = ReviewSegment.get(
(
SQL(
"json_extract(data, '$.detections') LIKE ?",
[f'%"{event_id}"%'],
)
)
& (ReviewSegment.end_time.is_null(False))
)
segment_data = review_segment.data
detection_ids = segment_data.get("detections", [])
# Rebuild objects list and sync sub_labels
objects_list = []
sub_labels = set()
events = Event.select(Event.id, Event.label, Event.sub_label).where(
Event.id.in_(detection_ids)
)
for det_event in events:
if det_event.sub_label:
sub_labels.add(det_event.sub_label)
objects_list.append(
f"{det_event.label}-verified"
) # eg, "bird-verified"
else:
objects_list.append(det_event.label) # eg, "bird"
segment_data["sub_labels"] = list(sub_labels)
segment_data["objects"] = objects_list
updated_data = {
ReviewSegment.id.name: review_segment.id,
ReviewSegment.camera.name: review_segment.camera,
ReviewSegment.start_time.name: review_segment.start_time,
ReviewSegment.end_time.name: review_segment.end_time,
ReviewSegment.severity.name: review_segment.severity,
ReviewSegment.thumb_path.name: review_segment.thumb_path,
ReviewSegment.data.name: segment_data,
}
self.requestor.send_data(UPSERT_REVIEW_SEGMENT, updated_data)
logger.debug(
f"Updated sub_label for event {event_id} in review segment {review_segment.id}"
)
except ReviewSegment.DoesNotExist:
logger.debug(
f"No review segment found with event ID {event_id} when updating sub_label"
)
return True
def set_recognized_license_plate(