Add tips and more info

This commit is contained in:
Nicolas Mowen 2025-10-23 12:08:07 -06:00
parent da47f23898
commit 5d532f5d79
4 changed files with 112 additions and 6 deletions

View File

@ -12,7 +12,18 @@ Object classification models are lightweight and run very fast on CPU. Inference
Training the model does briefly use a high amount of system resources for about 13 minutes per training run. On lower-power devices, training may take longer.
When running the `-tensorrt` image, Nvidia GPUs will automatically be used to accelerate training.
### Sub label vs Attribute
## Classes
Classes are the categories your model will learn to distinguish between. Each class represents a distinct visual category that the model will predict.
For object classification:
- Define classes that represent different types or attributes of the detected object
- Examples: For `person` objects, classes might be `delivery_person`, `resident`, `stranger`
- Include a `none` class for objects that don't fit any specific category
- Keep classes visually distinct to improve accuracy
### Classification Type
- **Sub label**:

View File

@ -12,6 +12,17 @@ State classification models are lightweight and run very fast on CPU. Inference
Training the model does briefly use a high amount of system resources for about 13 minutes per training run. On lower-power devices, training may take longer.
When running the `-tensorrt` image, Nvidia GPUs will automatically be used to accelerate training.
## Classes
Classes are the different states an area on your camera can be in. Each class represents a distinct visual state that the model will learn to recognize.
For state classification:
- Define classes that represent mutually exclusive states
- Examples: `open` and `closed` for a garage door, `on` and `off` for lights
- Use at least 2 classes (typically binary states work best)
- Keep class names clear and descriptive
## Example use cases
- **Door state**: Detect if a garage or front door is open vs closed.

View File

@ -71,7 +71,7 @@
"chooseExamples": "Choose Examples"
},
"step1": {
"description": "Create a new state or object classification model.",
"description": "Create a custom classification model. State models monitor fixed camera areas for changes (e.g., door open/closed). Object models add classifications to detected objects (e.g., known animals, delivery persons, etc.).",
"name": "Name",
"namePlaceholder": "Enter model name...",
"type": "Type",
@ -80,9 +80,14 @@
"objectLabel": "Object Label",
"objectLabelPlaceholder": "Select object type...",
"classificationType": "Classification Type",
"classificationTypeTip": "Learn about classification types",
"classificationTypeDesc": "Sub Labels add additional next to the object label (e.g., 'Person: UPS'). Attributes are searchable metadata stored separately in the object metadata.",
"classificationSubLabel": "Sub Label",
"classificationAttribute": "Attribute",
"classes": "Classes",
"classesTip": "Learn about classes",
"classesStateDesc": "Define the different states your camera area can be in. For example: 'open' and 'closed' for a garage door.",
"classesObjectDesc": "Define the different categories to classify detected objects into. For example: 'delivery_person', 'resident', 'stranger' for person classification.",
"classPlaceholder": "Enter class name...",
"errors": {
"nameRequired": "Model name is required",

View File

@ -2,6 +2,7 @@ import { Button } from "@/components/ui/button";
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
@ -22,10 +23,17 @@ import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { useTranslation } from "react-i18next";
import { useMemo } from "react";
import { LuX, LuPlus } from "react-icons/lu";
import { LuX, LuPlus, LuInfo, LuExternalLink } from "react-icons/lu";
import useSWR from "swr";
import { FrigateConfig } from "@/types/frigateConfig";
import { getTranslatedLabel } from "@/utils/i18n";
import { useDocDomain } from "@/hooks/use-doc-domain";
import { Link } from "react-router-dom";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
export type ModelType = "state" | "object";
export type ObjectClassificationType = "sub_label" | "attribute";
@ -53,6 +61,7 @@ export default function Step1NameAndDefine({
}: Step1NameAndDefineProps) {
const { t } = useTranslation(["views/classificationModel"]);
const { data: config } = useSWR<FrigateConfig>("config");
const { getLocaleDocUrl } = useDocDomain();
const objectLabels = useMemo(() => {
if (!config) return [];
@ -307,6 +316,38 @@ export default function Step1NameAndDefine({
<FormLabel className="text-primary-variant">
{t("wizard.step1.classificationType")}
</FormLabel>
<FormDescription className="mt-1 pt-0.5 text-xs text-muted-foreground">
<Popover>
<PopoverTrigger>
<div className="flex flex-row items-center gap-0.5 text-xs text-muted-foreground hover:text-primary">
<LuInfo className="size-3" />
<span className="cursor-pointer">
{t("wizard.step1.classificationTypeTip")}
</span>
</div>
</PopoverTrigger>
<PopoverContent>
<div className="flex flex-col gap-2">
<div className="text-sm">
{t("wizard.step1.classificationTypeDesc")}
</div>
<div className="mt-3 flex items-center text-primary">
<Link
to={getLocaleDocUrl(
"configuration/custom_classification/object_classification#classification-type",
)}
target="_blank"
rel="noopener noreferrer"
className="inline"
>
{t("readTheDocumentation", { ns: "common" })}
<LuExternalLink className="ml-2 inline-flex size-3" />
</Link>
</div>
</div>
</PopoverContent>
</Popover>
</FormDescription>
<FormControl>
<RadioGroup
onValueChange={field.onChange}
@ -352,9 +393,47 @@ export default function Step1NameAndDefine({
<div className="space-y-2">
<div className="flex items-center justify-between">
<FormLabel className="text-primary-variant">
{t("wizard.step1.classes")}
</FormLabel>
<div className="flex flex-col">
<FormLabel className="text-primary-variant">
{t("wizard.step1.classes")}
</FormLabel>
<FormDescription className="mt-1 pt-0.5 text-xs text-muted-foreground">
<Popover>
<PopoverTrigger>
<div className="flex flex-row items-center gap-0.5 text-xs text-muted-foreground hover:text-primary">
<LuInfo className="size-3" />
<span className="cursor-pointer">
{t("wizard.step1.classesTip")}
</span>
</div>
</PopoverTrigger>
<PopoverContent>
<div className="flex flex-col gap-2">
<div className="text-sm">
{watchedModelType === "state"
? t("wizard.step1.classesStateDesc")
: t("wizard.step1.classesObjectDesc")}
</div>
<div className="mt-3 flex items-center text-primary">
<Link
to={getLocaleDocUrl(
watchedModelType === "state"
? "configuration/custom_classification/state_classification"
: "configuration/custom_classification/object_classification",
)}
target="_blank"
rel="noopener noreferrer"
className="inline"
>
{t("readTheDocumentation", { ns: "common" })}
<LuExternalLink className="ml-2 inline-flex size-3" />
</Link>
</div>
</div>
</PopoverContent>
</Popover>
</FormDescription>
</div>
<Button
type="button"
variant="secondary"