mirror of
https://github.com/blakeblackshear/frigate.git
synced 2024-11-26 19:06:11 +01:00
add labelmap customization to the config (fixes #507)
This commit is contained in:
parent
a3853af47a
commit
92aa16c556
@ -110,10 +110,17 @@ detectors:
|
|||||||
|
|
||||||
### `model`
|
### `model`
|
||||||
|
|
||||||
|
If using a custom model, the width and height will need to be specified.
|
||||||
|
|
||||||
|
The labelmap can be customized to your needs. A common reason to do this is to combine multiple object types that are easily confused when you don't need to be as granular such as car/truck. By default, truck is renamed to car because they are often confused. You cannot add new object types, but you can change the names of existing objects in the model.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
model:
|
model:
|
||||||
# Required: height of the trained model
|
# Required: height of the trained model
|
||||||
height: 320
|
height: 320
|
||||||
# Required: width of the trained model
|
# Required: width of the trained model
|
||||||
width: 320
|
width: 320
|
||||||
|
# Optional: labelmap overrides
|
||||||
|
labelmap:
|
||||||
|
7: car
|
||||||
```
|
```
|
||||||
|
@ -4,13 +4,13 @@ title: Default available objects
|
|||||||
sidebar_label: Available objects
|
sidebar_label: Available objects
|
||||||
---
|
---
|
||||||
|
|
||||||
import labels from '../../../labelmap.txt';
|
import labels from "../../../labelmap.txt";
|
||||||
|
|
||||||
By default, Frigate includes the following object models from the Google Coral test data.
|
By default, Frigate includes the following object models from the Google Coral test data.
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
{labels.split('\n').map((label) => (
|
{labels.split("\n").map((label) => (
|
||||||
<li>{label.replace(/^\d+\s+/, '')}</li>
|
<li>{label.replace(/^\d+\s+/, "")}</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@ -23,14 +23,3 @@ Models for both CPU and EdgeTPU (Coral) are bundled in the image. You can use yo
|
|||||||
- Labels: `/labelmap.txt`
|
- Labels: `/labelmap.txt`
|
||||||
|
|
||||||
You also need to update the model width/height in the config if they differ from the defaults.
|
You also need to update the model width/height in the config if they differ from the defaults.
|
||||||
|
|
||||||
### Customizing the Labelmap
|
|
||||||
|
|
||||||
The labelmap can be customized to your needs. A common reason to do this is to combine multiple object types that are easily confused when you don't need to be as granular such as car/truck. You must retain the same number of labels, but you can change the names. To change:
|
|
||||||
|
|
||||||
- Download the [COCO labelmap](https://dl.google.com/coral/canned_models/coco_labels.txt)
|
|
||||||
- Modify the label names as desired. For example, change `7 truck` to `7 car`
|
|
||||||
- Mount the new file at `/labelmap.txt` in the container with an additional volume
|
|
||||||
```
|
|
||||||
-v ./config/labelmap.txt:/labelmap.txt
|
|
||||||
```
|
|
||||||
|
@ -259,6 +259,7 @@ class FrigateApp:
|
|||||||
name,
|
name,
|
||||||
config,
|
config,
|
||||||
model_shape,
|
model_shape,
|
||||||
|
self.config.model.merged_labelmap,
|
||||||
self.detection_queue,
|
self.detection_queue,
|
||||||
self.detection_out_events[name],
|
self.detection_out_events[name],
|
||||||
self.detected_frames_queue,
|
self.detected_frames_queue,
|
||||||
|
@ -13,6 +13,7 @@ from pydantic.fields import PrivateAttr
|
|||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
from frigate.const import BASE_DIR, RECORD_DIR, CACHE_DIR
|
from frigate.const import BASE_DIR, RECORD_DIR, CACHE_DIR
|
||||||
|
from frigate.edgetpu import load_labels
|
||||||
from frigate.util import create_mask, deep_merge
|
from frigate.util import create_mask, deep_merge
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -615,6 +616,22 @@ class DatabaseConfig(BaseModel):
|
|||||||
class ModelConfig(BaseModel):
|
class ModelConfig(BaseModel):
|
||||||
width: int = Field(default=320, title="Object detection model input width.")
|
width: int = Field(default=320, title="Object detection model input width.")
|
||||||
height: int = Field(default=320, title="Object detection model input height.")
|
height: int = Field(default=320, title="Object detection model input height.")
|
||||||
|
labelmap: Dict[int, str] = Field(
|
||||||
|
default_factory=dict, title="Labelmap customization."
|
||||||
|
)
|
||||||
|
_merged_labelmap: Optional[Dict[int, str]] = PrivateAttr()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def merged_labelmap(self) -> Dict[int, str]:
|
||||||
|
return self._merged_labelmap
|
||||||
|
|
||||||
|
def __init__(self, **config):
|
||||||
|
super().__init__(**config)
|
||||||
|
|
||||||
|
self._merged_labelmap = {
|
||||||
|
**load_labels("/labelmap.txt"),
|
||||||
|
**config.get("labelmap", {}),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class LogLevelEnum(str, Enum):
|
class LogLevelEnum(str, Enum):
|
||||||
|
@ -231,7 +231,7 @@ class EdgeTPUProcess:
|
|||||||
|
|
||||||
class RemoteObjectDetector:
|
class RemoteObjectDetector:
|
||||||
def __init__(self, name, labels, detection_queue, event, model_shape):
|
def __init__(self, name, labels, detection_queue, event, model_shape):
|
||||||
self.labels = load_labels(labels)
|
self.labels = labels
|
||||||
self.name = name
|
self.name = name
|
||||||
self.fps = EventsPerSecond()
|
self.fps = EventsPerSecond()
|
||||||
self.detection_queue = detection_queue
|
self.detection_queue = detection_queue
|
||||||
|
@ -503,6 +503,86 @@ class TestConfig(unittest.TestCase):
|
|||||||
runtime_config = frigate_config.runtime_config
|
runtime_config = frigate_config.runtime_config
|
||||||
assert round(runtime_config.cameras["back"].motion.contour_area) == 99
|
assert round(runtime_config.cameras["back"].motion.contour_area) == 99
|
||||||
|
|
||||||
|
def test_merge_labelmap(self):
|
||||||
|
|
||||||
|
config = {
|
||||||
|
"mqtt": {"host": "mqtt"},
|
||||||
|
"model": {"labelmap": {7: "truck"}},
|
||||||
|
"cameras": {
|
||||||
|
"back": {
|
||||||
|
"ffmpeg": {
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"path": "rtsp://10.0.0.1:554/video",
|
||||||
|
"roles": ["detect"],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"height": 1080,
|
||||||
|
"width": 1920,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
frigate_config = FrigateConfig(**config)
|
||||||
|
assert config == frigate_config.dict(exclude_unset=True)
|
||||||
|
|
||||||
|
runtime_config = frigate_config.runtime_config
|
||||||
|
assert runtime_config.model.merged_labelmap[7] == "truck"
|
||||||
|
|
||||||
|
def test_default_labelmap_empty(self):
|
||||||
|
|
||||||
|
config = {
|
||||||
|
"mqtt": {"host": "mqtt"},
|
||||||
|
"cameras": {
|
||||||
|
"back": {
|
||||||
|
"ffmpeg": {
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"path": "rtsp://10.0.0.1:554/video",
|
||||||
|
"roles": ["detect"],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"height": 1080,
|
||||||
|
"width": 1920,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
frigate_config = FrigateConfig(**config)
|
||||||
|
assert config == frigate_config.dict(exclude_unset=True)
|
||||||
|
|
||||||
|
runtime_config = frigate_config.runtime_config
|
||||||
|
assert runtime_config.model.merged_labelmap[0] == "person"
|
||||||
|
|
||||||
|
def test_default_labelmap(self):
|
||||||
|
|
||||||
|
config = {
|
||||||
|
"mqtt": {"host": "mqtt"},
|
||||||
|
"model": {"width": 320, "height": 320},
|
||||||
|
"cameras": {
|
||||||
|
"back": {
|
||||||
|
"ffmpeg": {
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"path": "rtsp://10.0.0.1:554/video",
|
||||||
|
"roles": ["detect"],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"height": 1080,
|
||||||
|
"width": 1920,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
frigate_config = FrigateConfig(**config)
|
||||||
|
assert config == frigate_config.dict(exclude_unset=True)
|
||||||
|
|
||||||
|
runtime_config = frigate_config.runtime_config
|
||||||
|
assert runtime_config.model.merged_labelmap[0] == "person"
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main(verbosity=2)
|
unittest.main(verbosity=2)
|
||||||
|
@ -318,6 +318,7 @@ def track_camera(
|
|||||||
name,
|
name,
|
||||||
config: CameraConfig,
|
config: CameraConfig,
|
||||||
model_shape,
|
model_shape,
|
||||||
|
labelmap,
|
||||||
detection_queue,
|
detection_queue,
|
||||||
result_connection,
|
result_connection,
|
||||||
detected_objects_queue,
|
detected_objects_queue,
|
||||||
@ -344,7 +345,7 @@ def track_camera(
|
|||||||
|
|
||||||
motion_detector = MotionDetector(frame_shape, config.motion)
|
motion_detector = MotionDetector(frame_shape, config.motion)
|
||||||
object_detector = RemoteObjectDetector(
|
object_detector = RemoteObjectDetector(
|
||||||
name, "/labelmap.txt", detection_queue, result_connection, model_shape
|
name, labelmap, detection_queue, result_connection, model_shape
|
||||||
)
|
)
|
||||||
|
|
||||||
object_tracker = ObjectTracker(config.detect)
|
object_tracker = ObjectTracker(config.detect)
|
||||||
|
Loading…
Reference in New Issue
Block a user