diff --git a/docs/docs/configuration/custom_classification/object_classification.md b/docs/docs/configuration/custom_classification/object_classification.md index 9465716b7..983fce852 100644 --- a/docs/docs/configuration/custom_classification/object_classification.md +++ b/docs/docs/configuration/custom_classification/object_classification.md @@ -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 1–3 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**: diff --git a/docs/docs/configuration/custom_classification/state_classification.md b/docs/docs/configuration/custom_classification/state_classification.md index afc79eff8..c22661f26 100644 --- a/docs/docs/configuration/custom_classification/state_classification.md +++ b/docs/docs/configuration/custom_classification/state_classification.md @@ -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 1–3 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. diff --git a/web/public/locales/en/views/classificationModel.json b/web/public/locales/en/views/classificationModel.json index 2f14df78d..e5b0044e8 100644 --- a/web/public/locales/en/views/classificationModel.json +++ b/web/public/locales/en/views/classificationModel.json @@ -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", diff --git a/web/src/components/classification/wizard/Step1NameAndDefine.tsx b/web/src/components/classification/wizard/Step1NameAndDefine.tsx index 59e388c52..5ddfe1388 100644 --- a/web/src/components/classification/wizard/Step1NameAndDefine.tsx +++ b/web/src/components/classification/wizard/Step1NameAndDefine.tsx @@ -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("config"); + const { getLocaleDocUrl } = useDocDomain(); const objectLabels = useMemo(() => { if (!config) return []; @@ -307,6 +316,38 @@ export default function Step1NameAndDefine({ {t("wizard.step1.classificationType")} + + + +
+ + + {t("wizard.step1.classificationTypeTip")} + +
+
+ +
+
+ {t("wizard.step1.classificationTypeDesc")} +
+
+ + {t("readTheDocumentation", { ns: "common" })} + + +
+
+
+
+
- - {t("wizard.step1.classes")} - +
+ + {t("wizard.step1.classes")} + + + + +
+ + + {t("wizard.step1.classesTip")} + +
+
+ +
+
+ {watchedModelType === "state" + ? t("wizard.step1.classesStateDesc") + : t("wizard.step1.classesObjectDesc")} +
+
+ + {t("readTheDocumentation", { ns: "common" })} + + +
+
+
+
+
+