mirror of
https://github.com/blakeblackshear/frigate.git
synced 2025-12-06 13:34:13 +03:00
Classification fixes (#20677)
Some checks are pending
CI / AMD64 Build (push) Waiting to run
CI / ARM Build (push) Waiting to run
CI / Jetson Jetpack 6 (push) Waiting to run
CI / AMD64 Extra Build (push) Blocked by required conditions
CI / ARM Extra Build (push) Blocked by required conditions
CI / Synaptics Build (push) Blocked by required conditions
CI / Assemble and push default build (push) Blocked by required conditions
Some checks are pending
CI / AMD64 Build (push) Waiting to run
CI / ARM Build (push) Waiting to run
CI / Jetson Jetpack 6 (push) Waiting to run
CI / AMD64 Extra Build (push) Blocked by required conditions
CI / ARM Extra Build (push) Blocked by required conditions
CI / Synaptics Build (push) Blocked by required conditions
CI / Assemble and push default build (push) Blocked by required conditions
* Don't run classification on stationary objects and set a maximum number of classifications * Fix layout of classification selection
This commit is contained in:
parent
094a0a6e05
commit
190925375b
@ -34,6 +34,8 @@ except ModuleNotFoundError:
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
MAX_OBJECT_CLASSIFICATIONS = 16
|
||||||
|
|
||||||
|
|
||||||
class CustomStateClassificationProcessor(RealTimeProcessorApi):
|
class CustomStateClassificationProcessor(RealTimeProcessorApi):
|
||||||
def __init__(
|
def __init__(
|
||||||
@ -396,6 +398,18 @@ class CustomObjectClassificationProcessor(RealTimeProcessorApi):
|
|||||||
if obj_data.get("end_time") is not None:
|
if obj_data.get("end_time") is not None:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if obj_data.get("stationary"):
|
||||||
|
return
|
||||||
|
|
||||||
|
object_id = obj_data["id"]
|
||||||
|
|
||||||
|
if (
|
||||||
|
object_id in self.classification_history
|
||||||
|
and len(self.classification_history[object_id])
|
||||||
|
>= MAX_OBJECT_CLASSIFICATIONS
|
||||||
|
):
|
||||||
|
return
|
||||||
|
|
||||||
now = datetime.datetime.now().timestamp()
|
now = datetime.datetime.now().timestamp()
|
||||||
x, y, x2, y2 = calculate_region(
|
x, y, x2, y2 = calculate_region(
|
||||||
frame.shape,
|
frame.shape,
|
||||||
@ -427,7 +441,7 @@ class CustomObjectClassificationProcessor(RealTimeProcessorApi):
|
|||||||
write_classification_attempt(
|
write_classification_attempt(
|
||||||
self.train_dir,
|
self.train_dir,
|
||||||
cv2.cvtColor(crop, cv2.COLOR_RGB2BGR),
|
cv2.cvtColor(crop, cv2.COLOR_RGB2BGR),
|
||||||
obj_data["id"],
|
object_id,
|
||||||
now,
|
now,
|
||||||
"unknown",
|
"unknown",
|
||||||
0.0,
|
0.0,
|
||||||
@ -448,7 +462,7 @@ class CustomObjectClassificationProcessor(RealTimeProcessorApi):
|
|||||||
write_classification_attempt(
|
write_classification_attempt(
|
||||||
self.train_dir,
|
self.train_dir,
|
||||||
cv2.cvtColor(crop, cv2.COLOR_RGB2BGR),
|
cv2.cvtColor(crop, cv2.COLOR_RGB2BGR),
|
||||||
obj_data["id"],
|
object_id,
|
||||||
now,
|
now,
|
||||||
self.labelmap[best_id],
|
self.labelmap[best_id],
|
||||||
score,
|
score,
|
||||||
@ -461,7 +475,7 @@ class CustomObjectClassificationProcessor(RealTimeProcessorApi):
|
|||||||
sub_label = self.labelmap[best_id]
|
sub_label = self.labelmap[best_id]
|
||||||
|
|
||||||
consensus_label, consensus_score = self.get_weighted_score(
|
consensus_label, consensus_score = self.get_weighted_score(
|
||||||
obj_data["id"], sub_label, score, now
|
object_id, sub_label, score, now
|
||||||
)
|
)
|
||||||
|
|
||||||
if consensus_label is not None:
|
if consensus_label is not None:
|
||||||
@ -470,7 +484,7 @@ class CustomObjectClassificationProcessor(RealTimeProcessorApi):
|
|||||||
== ObjectClassificationType.sub_label
|
== ObjectClassificationType.sub_label
|
||||||
):
|
):
|
||||||
self.sub_label_publisher.publish(
|
self.sub_label_publisher.publish(
|
||||||
(obj_data["id"], consensus_label, consensus_score),
|
(object_id, consensus_label, consensus_score),
|
||||||
EventMetadataTypeEnum.sub_label,
|
EventMetadataTypeEnum.sub_label,
|
||||||
)
|
)
|
||||||
elif (
|
elif (
|
||||||
@ -479,7 +493,7 @@ class CustomObjectClassificationProcessor(RealTimeProcessorApi):
|
|||||||
):
|
):
|
||||||
self.sub_label_publisher.publish(
|
self.sub_label_publisher.publish(
|
||||||
(
|
(
|
||||||
obj_data["id"],
|
object_id,
|
||||||
self.model_config.name,
|
self.model_config.name,
|
||||||
consensus_label,
|
consensus_label,
|
||||||
consensus_score,
|
consensus_score,
|
||||||
|
|||||||
@ -11,7 +11,6 @@ import {
|
|||||||
FrigateConfig,
|
FrigateConfig,
|
||||||
} from "@/types/frigateConfig";
|
} from "@/types/frigateConfig";
|
||||||
import { useEffect, useMemo, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
import { isMobile } from "react-device-detect";
|
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { FaFolderPlus } from "react-icons/fa";
|
import { FaFolderPlus } from "react-icons/fa";
|
||||||
import { MdModelTraining } from "react-icons/md";
|
import { MdModelTraining } from "react-icons/md";
|
||||||
@ -131,7 +130,7 @@ export default function ModelSelectionView({
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex size-full gap-2 p-2">
|
<div className="grid auto-rows-max grid-cols-2 gap-2 overflow-y-auto p-2 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-6 2xl:grid-cols-8 3xl:grid-cols-10">
|
||||||
{selectedClassificationConfigs.length === 0 ? (
|
{selectedClassificationConfigs.length === 0 ? (
|
||||||
<NoModelsView
|
<NoModelsView
|
||||||
onCreateModel={() => setNewModel(true)}
|
onCreateModel={() => setNewModel(true)}
|
||||||
@ -208,14 +207,13 @@ function ModelCard({ config, onClick }: ModelCardProps) {
|
|||||||
<div
|
<div
|
||||||
key={config.name}
|
key={config.name}
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative size-60 cursor-pointer overflow-hidden rounded-lg",
|
"relative aspect-square w-full cursor-pointer overflow-hidden rounded-lg",
|
||||||
"outline-transparent duration-500",
|
"outline-transparent duration-500",
|
||||||
isMobile && "w-full",
|
|
||||||
)}
|
)}
|
||||||
onClick={() => onClick()}
|
onClick={() => onClick()}
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
className={cn("size-full", isMobile && "w-full")}
|
className="size-full"
|
||||||
src={`${baseUrl}clips/${config.name}/dataset/${coverImage?.name}/${coverImage?.img}`}
|
src={`${baseUrl}clips/${config.name}/dataset/${coverImage?.name}/${coverImage?.img}`}
|
||||||
/>
|
/>
|
||||||
<ImageShadowOverlay />
|
<ImageShadowOverlay />
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user