add average speed

This commit is contained in:
Josh Hawkins 2024-12-20 12:56:02 -06:00
parent 03db156c20
commit d3ce58cbf4
6 changed files with 52 additions and 13 deletions

View File

@ -153,7 +153,7 @@ ui:
unit_system: metric
```
The maximum speed during the object's lifetime is saved in Frigate's database and can be seen in the UI in the Tracked Object Details pane in Explore. Current estimated speed can also be seen on the debug view as the third value in the object label. Current estimated speed, max estimated speed, and velocity angle (the angle of the direction the object is moving relative to the frame) of tracked objects is also sent through the `events` MQTT topic. See the [MQTT docs](../integrations/mqtt.md#frigateevents).
The average and maximum speed during the object's lifetime is saved in Frigate's database and can be seen in the UI in the Tracked Object Details pane in Explore. Current estimated speed can also be seen on the debug view as the third value in the object label. Current estimated speed, average estimated speed, max estimated speed, and velocity angle (the angle of the direction the object is moving relative to the frame) of tracked objects is also sent through the `events` MQTT topic. See the [MQTT docs](../integrations/mqtt.md#frigateevents).
#### Best practices and caveats

View File

@ -322,6 +322,7 @@ def events_explore(limit: int = 10):
"top_score",
"description",
"sub_label_score",
"average_estimated_speed",
"max_estimated_speed",
]
},
@ -595,6 +596,7 @@ def events_search(request: Request, params: EventsSearchQueryParams = Depends())
"top_score",
"description",
"sub_label_score",
"average_estimated_speed",
"max_estimated_speed",
]
}

View File

@ -25,6 +25,8 @@ def should_update_db(prev_event: Event, current_event: Event) -> bool:
or prev_event["entered_zones"] != current_event["entered_zones"]
or prev_event["thumbnail"] != current_event["thumbnail"]
or prev_event["end_time"] != current_event["end_time"]
or prev_event["average_estimated_speed"]
!= current_event["average_estimated_speed"]
or prev_event["max_estimated_speed"] != current_event["max_estimated_speed"]
):
return True
@ -210,6 +212,7 @@ class EventProcessor(threading.Thread):
"score": score,
"top_score": event_data["top_score"],
"attributes": attributes,
"average_estimated_speed": event_data["average_estimated_speed"],
"max_estimated_speed": event_data["max_estimated_speed"],
"type": "object",
"max_severity": event_data.get("max_severity"),

View File

@ -62,7 +62,9 @@ class TrackedObject:
self.frame = None
self.active = True
self.pending_loitering = False
self.estimated_speed = 0
self.speed_history = []
self.current_estimated_speed = 0
self.average_estimated_speed = 0
self.max_estimated_speed = 0
self.velocity_angle = 0
self.previous = self.to_dict()
@ -197,16 +199,22 @@ class TrackedObject:
)
if self.ui_config.unit_system == "metric":
# Convert m/s to km/h
self.estimated_speed = speed_magnitude * 3.6
self.current_estimated_speed = speed_magnitude * 3.6
elif self.ui_config.unit_system == "imperial":
# Convert ft/s to mph
self.estimated_speed = speed_magnitude * 0.681818
self.current_estimated_speed = speed_magnitude * 0.681818
logger.debug(
f"Camera: {self.camera_config.name}, zone: {name}, tracked object ID: {self.obj_data['id']}, pixel velocity: {str(tuple(np.round(self.obj_data['estimate_velocity']).flatten().astype(int)))} estimated speed: {self.estimated_speed:.1f}"
f"Camera: {self.camera_config.name}, zone: {name}, tracked object ID: {self.obj_data['id']}, pixel velocity: {str(tuple(np.round(self.obj_data['estimate_velocity']).flatten().astype(int)))} estimated speed: {self.current_estimated_speed:.1f}"
)
if self.estimated_speed > self.max_estimated_speed:
self.max_estimated_speed = self.estimated_speed
self.speed_history.append(self.current_estimated_speed)
self.average_estimated_speed = sum(self.speed_history) / len(
self.speed_history
)
if self.current_estimated_speed > self.max_estimated_speed:
self.max_estimated_speed = self.current_estimated_speed
# update loitering status
self.pending_loitering = in_loitering_zone
@ -289,7 +297,8 @@ class TrackedObject:
"current_attributes": self.obj_data["attributes"],
"pending_loitering": self.pending_loitering,
"max_severity": self.max_severity,
"estimated_speed": self.estimated_speed,
"current_estimated_speed": self.current_estimated_speed,
"average_estimated_speed": self.average_estimated_speed,
"max_estimated_speed": self.max_estimated_speed,
"velocity_angle": self.velocity_angle,
}

View File

@ -316,6 +316,18 @@ function ObjectDetailsTab({
}
}, [search]);
const averageEstimatedSpeed = useMemo(() => {
if (!search || !search.data?.average_estimated_speed) {
return undefined;
}
if (search.data?.average_estimated_speed != 0) {
return search.data?.average_estimated_speed.toFixed(1);
} else {
return undefined;
}
}, [search]);
const maxEstimatedSpeed = useMemo(() => {
if (!search || !search.data?.max_estimated_speed) {
return undefined;
@ -439,12 +451,24 @@ function ObjectDetailsTab({
{score}%{subLabelScore && ` (${subLabelScore}%)`}
</div>
</div>
{maxEstimatedSpeed && (
{(averageEstimatedSpeed || maxEstimatedSpeed) && (
<div className="flex flex-col gap-1.5">
<div className="text-sm text-primary/40">Max Estimated Speed</div>
<div className="text-sm">
<div className="text-sm text-primary/40">Estimated Speeds</div>
<div className="flex flex-col space-y-0.5 text-sm">
{averageEstimatedSpeed && (
<div>
{averageEstimatedSpeed}{" "}
{config?.ui.unit_system == "imperial" ? "mph" : "kph"}{" "}
<span className="text-primary/40">(average)</span>
</div>
)}
{maxEstimatedSpeed && (
<div>
{maxEstimatedSpeed}{" "}
{config?.ui.unit_system == "imperial" ? "mph" : "kph"}
{config?.ui.unit_system == "imperial" ? "mph" : "kph"}{" "}
<span className="text-primary/40">(maximum)</span>
</div>
)}
</div>
</div>
)}

View File

@ -55,6 +55,7 @@ export type SearchResult = {
ratio: number;
type: "object" | "audio" | "manual";
description?: string;
average_estimated_speed: number;
max_estimated_speed: number;
};
};