mirror of
https://github.com/blakeblackshear/frigate.git
synced 2025-07-30 13:48:07 +02:00
Attributes for object masks (#18003)
* Add ability to select attributes for object masks This feature already works correctly on the backend. This just adds the ability to select attributes through the UI. * Add clarity to LPR docs about timestamps * fix sub label score and add info popover
This commit is contained in:
parent
f98795abfd
commit
9fa2b002ba
@ -358,3 +358,11 @@ LPR's performance impact depends on your hardware. Ensure you have at least 4GB
|
||||
The YOLOv9 license plate detector model will run (and the metric will appear) if you've enabled LPR but haven't defined `license_plate` as an object to track, either at the global or camera level.
|
||||
|
||||
If you are detecting `car` on cameras where you don't want to run LPR, make sure you disable LPR it at the camera level. And if you do want to run LPR on those cameras, make sure you define `license_plate` as an object to track.
|
||||
|
||||
### It looks like Frigate picked up my camera's timestamp as the license plate. How can I prevent this?
|
||||
|
||||
This could happen if cars travel close to your camera's timestamp. You could either move the timestamp through your camera's firmware, or apply a mask to it in Frigate.
|
||||
|
||||
If you are using a model that natively detects `license_plate`, add an _object mask_ of type `license_plate` and a _motion mask_ over your timestamp.
|
||||
|
||||
If you are using dedicated LPR camera mode, only a _motion mask_ over your timestamp is required.
|
||||
|
@ -5,7 +5,8 @@
|
||||
},
|
||||
"details": {
|
||||
"person": "Person",
|
||||
"confidence": "Confidence",
|
||||
"subLabelScore": "Sub Label Score",
|
||||
"scoreInfo": "The sub label score is the weighted score for all of the recognized face confidences, so this may differ from the score shown on the snapshot.",
|
||||
"face": "Face Details",
|
||||
"faceDesc": "Details for the face and associated object",
|
||||
"timestamp": "Timestamp"
|
||||
|
@ -37,7 +37,6 @@ import axios from "axios";
|
||||
import { toast } from "sonner";
|
||||
import { Toaster } from "../ui/sonner";
|
||||
import ActivityIndicator from "../indicators/activity-indicator";
|
||||
import { getAttributeLabels } from "@/utils/iconUtil";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
type ObjectMaskEditPaneProps = {
|
||||
@ -401,14 +400,6 @@ export function ZoneObjectSelector({ camera }: ZoneObjectSelectorProps) {
|
||||
const { t } = useTranslation(["views/settings"]);
|
||||
const { data: config } = useSWR<FrigateConfig>("config");
|
||||
|
||||
const attributeLabels = useMemo(() => {
|
||||
if (!config) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return getAttributeLabels(config);
|
||||
}, [config]);
|
||||
|
||||
const cameraConfig = useMemo(() => {
|
||||
if (config && camera) {
|
||||
return config.cameras[camera];
|
||||
@ -424,20 +415,16 @@ export function ZoneObjectSelector({ camera }: ZoneObjectSelectorProps) {
|
||||
|
||||
Object.values(config.cameras).forEach((camera) => {
|
||||
camera.objects.track.forEach((label) => {
|
||||
if (!attributeLabels.includes(label)) {
|
||||
labels.add(label);
|
||||
}
|
||||
labels.add(label);
|
||||
});
|
||||
});
|
||||
|
||||
cameraConfig.objects.track.forEach((label) => {
|
||||
if (!attributeLabels.includes(label)) {
|
||||
labels.add(label);
|
||||
}
|
||||
labels.add(label);
|
||||
});
|
||||
|
||||
return [...labels].sort();
|
||||
}, [config, cameraConfig, attributeLabels]);
|
||||
}, [config, cameraConfig]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -21,6 +21,11 @@ import {
|
||||
DropdownMenuTrigger,
|
||||
DropdownMenuSeparator,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@/components/ui/popover";
|
||||
import { Toaster } from "@/components/ui/sonner";
|
||||
import {
|
||||
Tooltip,
|
||||
@ -42,6 +47,7 @@ import { isDesktop, isMobile } from "react-device-detect";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
LuImagePlus,
|
||||
LuInfo,
|
||||
LuPencil,
|
||||
LuRefreshCw,
|
||||
LuScanFace,
|
||||
@ -647,10 +653,23 @@ function TrainingGrid({
|
||||
{selectedEvent?.data.sub_label_score && (
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<div className="text-sm text-primary/40">
|
||||
{t("details.confidence")}
|
||||
<div className="flex flex-row items-center gap-1">
|
||||
{t("details.subLabelScore")}
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<div className="cursor-pointer p-0">
|
||||
<LuInfo className="size-4" />
|
||||
<span className="sr-only">Info</span>
|
||||
</div>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-80">
|
||||
{t("details.scoreInfo")}
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-sm smart-capitalize">
|
||||
{Math.round(selectedEvent?.data?.sub_label_score || 0) * 100}%
|
||||
{Math.round((selectedEvent?.data?.sub_label_score || 0) * 100)}%
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
Loading…
Reference in New Issue
Block a user