Skip to content

Commit

Permalink
refactor and reduce false positives
Browse files Browse the repository at this point in the history
  • Loading branch information
blakeblackshear committed Sep 17, 2020
1 parent ea4ecae commit acb75fa
Show file tree
Hide file tree
Showing 10 changed files with 541 additions and 232 deletions.
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ RUN apt -qq update && apt -qq install --no-install-recommends -y \
PyYAML \
matplotlib \
pyarrow \
click \
&& echo "deb https://packages.cloud.google.com/apt coral-edgetpu-stable main" > /etc/apt/sources.list.d/coral-edgetpu.list \
&& wget -q -O - https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - \
&& apt -qq update \
Expand All @@ -46,7 +47,7 @@ RUN apt -qq update && apt -qq install --no-install-recommends -y \

# get model and labels
RUN wget -q https://github.com/google-coral/edgetpu/raw/master/test_data/ssd_mobilenet_v2_coco_quant_postprocess_edgetpu.tflite -O /edgetpu_model.tflite --trust-server-names
RUN wget -q https://dl.google.com/coral/canned_models/coco_labels.txt -O /labelmap.txt --trust-server-names
COPY labelmap.txt /labelmap.txt
RUN wget -q https://github.com/google-coral/edgetpu/raw/master/test_data/ssd_mobilenet_v2_coco_quant_postprocess.tflite -O /cpu_model.tflite


Expand Down
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -342,5 +342,17 @@ cameras:
width: 1920
```
- Additional logging is available in the docker container - You can view the logs by running `docker logs -t frigate`
- Object configuration - Tracked objects types, sizes and thresholds can be defined globally and/or on a per camera basis. The global and camera object configuration is *merged*. For example, if you defined tracking person, car, and truck globally but modified your backyard camera to only track person, the global config would merge making the effective list for the backyard camera still contain person, car and truck. If you want precise object tracking per camera, best practice to put a minimal list of objects at the global level and expand objects on a per camera basis. Object threshold and area configuration will be used first from the camera object config (if defined) and then from the global config. See the [example config](config/config.example.yml) for more information.
- Object configuration - Tracked objects types, sizes and thresholds can be defined globally and/or on a per camera basis. The global and camera object configuration is *merged*. For example, if you defined tracking person, car, and truck globally but modified your backyard camera to only track person, the global config would merge making the effective list for the backyard camera still contain person, car and truck. If you want precise object tracking per camera, best practice to put a minimal list of objects at the global level and expand objects on a per camera basis. Object threshold and area configuration will be used first from the camera object config (if defined) and then from the global config. See the [example config](config/config.example.yml) for more information.

## Troubleshooting

### "ffmpeg didnt return a frame. something is wrong"
Turn on logging for the camera by overriding the global_args and setting the log level to `info`:
```yaml
ffmpeg:
global_args:
- -hide_banner
- -loglevel
- panic
```
13 changes: 8 additions & 5 deletions config/config.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,10 @@ mqtt:
# unless overridden at the camera levels.
# Keys must be valid labels. By default, the model uses coco (https://dl.google.com/coral/canned_models/coco_labels.txt).
# All labels from the model are reported over MQTT. These values are used to filter out false positives.
# min_area (optional): minimum width*height of the bounding box for the detected person
# max_area (optional): maximum width*height of the bounding box for the detected person
# threshold (optional): The minimum decimal percentage (50% hit = 0.5) for the confidence from tensorflow
# min_area (optional): minimum width*height of the bounding box for the detected object
# max_area (optional): maximum width*height of the bounding box for the detected object
# min_score (optional): minimum score for the object
# threshold (optional): The minimum decimal percentage for tracked object's computed score to considered a true positive
####################
objects:
track:
Expand All @@ -66,7 +67,8 @@ objects:
person:
min_area: 5000
max_area: 100000
threshold: 0.8
min_score: 0.5
threshold: 0.85

zones:
#################
Expand Down Expand Up @@ -184,4 +186,5 @@ cameras:
person:
min_area: 5000
max_area: 100000
threshold: 0.8
min_score: 0.5
threshold: 0.85
25 changes: 21 additions & 4 deletions detect_objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def run(self):
process = mp.Process(target=track_camera, args=(name, self.config[name], GLOBAL_OBJECT_CONFIG, camera_process['frame_queue'],
camera_process['frame_shape'], self.tflite_process.detection_queue, self.tracked_objects_queue,
camera_process['process_fps'], camera_process['detection_fps'],
camera_process['read_start'], camera_process['detection_frame']))
camera_process['read_start'], camera_process['detection_frame'], self.stop_event))
process.daemon = True
camera_process['process'] = process
process.start()
Expand All @@ -135,7 +135,7 @@ def run(self):
camera_capture.start()
camera_process['ffmpeg_process'] = ffmpeg_process
camera_process['capture_thread'] = camera_capture
elif now - camera_process['capture_thread'].current_frame > 5:
elif now - camera_process['capture_thread'].current_frame.value > 5:
print(f"No frames received from {name} in 5 seconds. Exiting ffmpeg...")
ffmpeg_process = camera_process['ffmpeg_process']
ffmpeg_process.terminate()
Expand Down Expand Up @@ -181,6 +181,7 @@ def on_connect(client, userdata, flags, rc):
'show_timestamp': config.get('snapshots', {}).get('show_timestamp', True),
'draw_zones': config.get('snapshots', {}).get('draw_zones', False)
}
config['zones'] = {}

# Queue for cameras to push tracked objects to
tracked_objects_queue = mp.Queue()
Expand Down Expand Up @@ -259,7 +260,23 @@ def on_connect(client, userdata, flags, rc):
'capture_thread': camera_capture
}

camera_process = mp.Process(target=track_camera, args=(name, config, GLOBAL_OBJECT_CONFIG, frame_queue, frame_shape,
# merge global object config into camera object config
camera_objects_config = config.get('objects', {})
# get objects to track for camera
objects_to_track = camera_objects_config.get('track', GLOBAL_OBJECT_CONFIG.get('track', ['person']))
# merge object filters
global_object_filters = GLOBAL_OBJECT_CONFIG.get('filters', {})
camera_object_filters = camera_objects_config.get('filters', {})
objects_with_config = set().union(global_object_filters.keys(), camera_object_filters.keys())
object_filters = {}
for obj in objects_with_config:
object_filters[obj] = {**global_object_filters.get(obj, {}), **camera_object_filters.get(obj, {})}
config['objects'] = {
'track': objects_to_track,
'filters': object_filters
}

camera_process = mp.Process(target=track_camera, args=(name, config, frame_queue, frame_shape,
tflite_process.detection_queue, tracked_objects_queue, camera_processes[name]['process_fps'],
camera_processes[name]['detection_fps'],
camera_processes[name]['read_start'], camera_processes[name]['detection_frame'], stop_event))
Expand Down Expand Up @@ -340,7 +357,7 @@ def stats():
'pid': camera_stats['process'].pid,
'ffmpeg_pid': camera_stats['ffmpeg_process'].pid,
'frame_info': {
'read': capture_thread.current_frame,
'read': capture_thread.current_frame.value,
'detect': camera_stats['detection_frame'].value,
'process': object_processor.camera_data[name]['current_frame_time']
}
Expand Down
Loading

0 comments on commit acb75fa

Please sign in to comment.