mirror of
https://github.com/blakeblackshear/frigate.git
synced 2025-10-30 02:32:04 +08:00
Compare commits
29 Commits
v0.7.1
...
v0.7.0-rc2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
45e9f84f6c | ||
|
|
20cff853e8 | ||
|
|
d28d5e04a9 | ||
|
|
26f4e27df0 | ||
|
|
106d513e0b | ||
|
|
223ec76601 | ||
|
|
405837de22 | ||
|
|
51bd107536 | ||
|
|
08c43e7918 | ||
|
|
6f070502b5 | ||
|
|
61081b91a3 | ||
|
|
2a84d0afb9 | ||
|
|
2c17f27ab4 | ||
|
|
5bb9838c4f | ||
|
|
d59018a14c | ||
|
|
5f2b8bb6ad | ||
|
|
6554640a61 | ||
|
|
5fbb092212 | ||
|
|
dbb4ca7c87 | ||
|
|
e506931830 | ||
|
|
feaf63c15f | ||
|
|
a94179be4d | ||
|
|
7837de8bc8 | ||
|
|
0366781728 | ||
|
|
e898fca70a | ||
|
|
d788ceb1d3 | ||
|
|
90a48fc761 | ||
|
|
de57c79bf9 | ||
|
|
af8c4e7eac |
32
Makefile
32
Makefile
@@ -12,26 +12,26 @@ amd64_frigate:
|
||||
|
||||
amd64_all: amd64_wheels amd64_ffmpeg amd64_frigate
|
||||
|
||||
aarch64_wheels:
|
||||
docker build --tag blakeblackshear/frigate-wheels:aarch64 --file docker/Dockerfile.wheels.aarch64 .
|
||||
arm64_wheels:
|
||||
docker build --tag blakeblackshear/frigate-wheels:arm64 --file docker/Dockerfile.wheels.arm64 .
|
||||
|
||||
aarch64_ffmpeg:
|
||||
docker build --tag blakeblackshear/frigate-ffmpeg:aarch64 --file docker/Dockerfile.ffmpeg.aarch64 .
|
||||
arm64_ffmpeg:
|
||||
docker build --tag blakeblackshear/frigate-ffmpeg:arm64 --file docker/Dockerfile.ffmpeg.arm64 .
|
||||
|
||||
aarch64_frigate:
|
||||
docker build --tag frigate-base --build-arg ARCH=aarch64 --file docker/Dockerfile.base .
|
||||
docker build --tag frigate --file docker/Dockerfile.aarch64 .
|
||||
arm64_frigate:
|
||||
docker build --tag frigate-base --build-arg ARCH=arm64 --file docker/Dockerfile.base .
|
||||
docker build --tag frigate --file docker/Dockerfile.arm64 .
|
||||
|
||||
armv7_all: armv7_wheels armv7_ffmpeg armv7_frigate
|
||||
armv7hf_all: arm64_wheels arm64_ffmpeg arm64_frigate
|
||||
|
||||
armv7_wheels:
|
||||
docker build --tag blakeblackshear/frigate-wheels:armv7 --file docker/Dockerfile.wheels .
|
||||
armv7hf_wheels:
|
||||
docker build --tag blakeblackshear/frigate-wheels:armv7hf --file docker/Dockerfile.wheels .
|
||||
|
||||
armv7_ffmpeg:
|
||||
docker build --tag blakeblackshear/frigate-ffmpeg:armv7 --file docker/Dockerfile.ffmpeg.armv7 .
|
||||
armv7hf_ffmpeg:
|
||||
docker build --tag blakeblackshear/frigate-ffmpeg:armv7hf --file docker/Dockerfile.ffmpeg.armv7hf .
|
||||
|
||||
armv7_frigate:
|
||||
docker build --tag frigate-base --build-arg ARCH=armv7 --file docker/Dockerfile.base .
|
||||
docker build --tag frigate --file docker/Dockerfile.armv7 .
|
||||
armv7hf_frigate:
|
||||
docker build --tag frigate-base --build-arg ARCH=armv7hf --file docker/Dockerfile.base .
|
||||
docker build --tag frigate --file docker/Dockerfile.armv7hf .
|
||||
|
||||
armv7_all: armv7_wheels armv7_ffmpeg armv7_frigate
|
||||
armv7hf_all: armv7hf_wheels armv7hf_ffmpeg armv7hf_frigate
|
||||
|
||||
@@ -31,7 +31,7 @@ docker run --rm \
|
||||
-v /etc/localtime:/etc/localtime:ro \
|
||||
-p 5000:5000 \
|
||||
-e FRIGATE_RTSP_PASSWORD='password' \
|
||||
blakeblackshear/frigate:0.7.0-amd64
|
||||
blakeblackshear/frigate:stable
|
||||
```
|
||||
|
||||
Example docker-compose:
|
||||
@@ -41,7 +41,7 @@ Example docker-compose:
|
||||
restart: unless-stopped
|
||||
privileged: true
|
||||
shm_size: '100m' # only needed with large numbers of high res cameras
|
||||
image: blakeblackshear/frigate:0.7.0-amd64
|
||||
image: blakeblackshear/frigate:stable
|
||||
volumes:
|
||||
- /dev/bus/usb:/dev/bus/usb
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
|
||||
@@ -31,8 +31,6 @@ save_clips:
|
||||
# will begin to expire and the resulting clip will be the last x seconds of the event.
|
||||
###########
|
||||
max_seconds: 300
|
||||
clips_dir: /clips
|
||||
cache_dir: /cache
|
||||
|
||||
#################
|
||||
# Default ffmpeg args. Optional and can be overwritten per camera.
|
||||
@@ -217,7 +215,6 @@ cameras:
|
||||
snapshots:
|
||||
show_timestamp: True
|
||||
draw_zones: False
|
||||
draw_bounding_boxes: True
|
||||
|
||||
################
|
||||
# Camera level object config. If defined, this is used instead of the global config.
|
||||
|
||||
@@ -9,7 +9,6 @@ import time
|
||||
import datetime
|
||||
import queue
|
||||
import yaml
|
||||
import json
|
||||
import threading
|
||||
import multiprocessing as mp
|
||||
import subprocess as sp
|
||||
@@ -26,22 +25,8 @@ from frigate.edgetpu import EdgeTPUProcess
|
||||
|
||||
FRIGATE_VARS = {k: v for k, v in os.environ.items() if k.startswith('FRIGATE_')}
|
||||
|
||||
CONFIG_FILE = os.environ.get('CONFIG_FILE', '/config/config.yml')
|
||||
|
||||
if CONFIG_FILE.endswith(".yml"):
|
||||
with open(CONFIG_FILE) as f:
|
||||
CONFIG = yaml.safe_load(f)
|
||||
elif CONFIG_FILE.endswith(".json"):
|
||||
with open(CONFIG_FILE) as f:
|
||||
CONFIG = json.load(f)
|
||||
|
||||
CACHE_DIR = CONFIG.get('save_clips', {}).get('cache_dir', '/cache')
|
||||
CLIPS_DIR = CONFIG.get('save_clips', {}).get('clips_dir', '/clips')
|
||||
|
||||
if not os.path.exists(CACHE_DIR) and not os.path.islink(CACHE_DIR):
|
||||
os.makedirs(CACHE_DIR)
|
||||
if not os.path.exists(CLIPS_DIR) and not os.path.islink(CLIPS_DIR):
|
||||
os.makedirs(CLIPS_DIR)
|
||||
with open('/config/config.yml') as f:
|
||||
CONFIG = yaml.safe_load(f)
|
||||
|
||||
MQTT_HOST = CONFIG['mqtt']['host']
|
||||
MQTT_PORT = CONFIG.get('mqtt', {}).get('port', 1883)
|
||||
@@ -179,8 +164,7 @@ def main():
|
||||
for name, config in CONFIG['cameras'].items():
|
||||
config['snapshots'] = {
|
||||
'show_timestamp': config.get('snapshots', {}).get('show_timestamp', True),
|
||||
'draw_zones': config.get('snapshots', {}).get('draw_zones', False),
|
||||
'draw_bounding_boxes': config.get('snapshots', {}).get('draw_bounding_boxes', True)
|
||||
'draw_zones': config.get('snapshots', {}).get('draw_zones', False)
|
||||
}
|
||||
config['zones'] = config.get('zones', {})
|
||||
|
||||
@@ -238,7 +222,7 @@ def main():
|
||||
"-an",
|
||||
"-map",
|
||||
"0",
|
||||
f"{os.path.join(CACHE_DIR, name)}-%Y%m%d%H%M%S.mp4"
|
||||
f"/cache/{name}-%Y%m%d%H%M%S.mp4"
|
||||
] + ffmpeg_output_args
|
||||
ffmpeg_cmd = (['ffmpeg'] +
|
||||
ffmpeg_global_args +
|
||||
@@ -304,7 +288,7 @@ def main():
|
||||
camera_process['process'].start()
|
||||
print(f"Camera_process started for {name}: {camera_process['process'].pid}")
|
||||
|
||||
event_processor = EventProcessor(CONFIG, camera_processes, CACHE_DIR, CLIPS_DIR, event_queue, stop_event)
|
||||
event_processor = EventProcessor(CONFIG, camera_processes, '/cache', '/clips', event_queue, stop_event)
|
||||
event_processor.start()
|
||||
|
||||
object_processor = TrackedObjectProcessor(CONFIG['cameras'], client, MQTT_TOPIC_PREFIX, tracked_objects_queue, event_queue, stop_event)
|
||||
@@ -328,7 +312,7 @@ def main():
|
||||
shm.close()
|
||||
shm.unlink()
|
||||
|
||||
for detector in detectors.values():
|
||||
for detector in detectors:
|
||||
detector.stop()
|
||||
for shm in camera_shms:
|
||||
shm.close()
|
||||
@@ -404,11 +388,9 @@ def main():
|
||||
def best(camera_name, label):
|
||||
if camera_name in CONFIG['cameras']:
|
||||
best_object = object_processor.get_best(camera_name, label)
|
||||
best_frame = best_object.get('frame')
|
||||
if best_frame is None:
|
||||
best_frame = np.zeros((720,1280,3), np.uint8)
|
||||
else:
|
||||
best_frame = cv2.cvtColor(best_frame, cv2.COLOR_YUV2BGR_I420)
|
||||
best_frame = best_object.get('frame', np.zeros((720,1280,3), np.uint8))
|
||||
|
||||
best_frame = cv2.cvtColor(best_frame, cv2.COLOR_YUV2BGR_I420)
|
||||
|
||||
crop = bool(request.args.get('crop', 0, type=int))
|
||||
if crop:
|
||||
|
||||
@@ -181,12 +181,10 @@ class CameraState():
|
||||
# check each zone
|
||||
for name, zone in self.config['zones'].items():
|
||||
contour = zone['contour']
|
||||
# check if the object is in the zone
|
||||
if (cv2.pointPolygonTest(contour, bottom_center, False) >= 0):
|
||||
# if the object passed the filters once, dont apply again
|
||||
if name in obj.get('zones', []) or not zone_filtered(obj, zone.get('filters', {})):
|
||||
current_zones.append(name)
|
||||
|
||||
# check if the object is in the zone and not filtered
|
||||
if (cv2.pointPolygonTest(contour, bottom_center, False) >= 0
|
||||
and not zone_filtered(obj, zone.get('filters', {}))):
|
||||
current_zones.append(name)
|
||||
obj['zones'] = current_zones
|
||||
|
||||
# maintain best objects
|
||||
@@ -268,14 +266,7 @@ class TrackedObjectProcessor(threading.Thread):
|
||||
def snapshot(camera, obj):
|
||||
if not 'frame' in obj:
|
||||
return
|
||||
|
||||
best_frame = cv2.cvtColor(obj['frame'], cv2.COLOR_YUV2BGR_I420)
|
||||
if self.camera_config[camera]['snapshots']['draw_bounding_boxes']:
|
||||
thickness = 2
|
||||
color = COLOR_MAP[obj['label']]
|
||||
box = obj['box']
|
||||
draw_box_with_label(best_frame, box[0], box[1], box[2], box[3], obj['label'], f"{int(obj['score']*100)}% {int(obj['area'])}", thickness=thickness, color=color)
|
||||
|
||||
mqtt_config = self.camera_config[camera].get('mqtt', {'crop_to_region': False})
|
||||
if mqtt_config.get('crop_to_region'):
|
||||
region = obj['region']
|
||||
@@ -284,16 +275,6 @@ class TrackedObjectProcessor(threading.Thread):
|
||||
height = int(mqtt_config['snapshot_height'])
|
||||
width = int(height*best_frame.shape[1]/best_frame.shape[0])
|
||||
best_frame = cv2.resize(best_frame, dsize=(width, height), interpolation=cv2.INTER_AREA)
|
||||
|
||||
if self.camera_config[camera]['snapshots']['show_timestamp']:
|
||||
time_to_show = datetime.datetime.fromtimestamp(obj['frame_time']).strftime("%m/%d/%Y %H:%M:%S")
|
||||
size = cv2.getTextSize(time_to_show, cv2.FONT_HERSHEY_SIMPLEX, fontScale=1, thickness=2)
|
||||
text_width = size[0][0]
|
||||
text_height = size[0][1]
|
||||
desired_size = max(200, 0.33*best_frame.shape[1])
|
||||
font_scale = desired_size/text_width
|
||||
cv2.putText(best_frame, time_to_show, (5, best_frame.shape[0]-7), cv2.FONT_HERSHEY_SIMPLEX, fontScale=font_scale, color=(255, 255, 255), thickness=2)
|
||||
|
||||
ret, jpg = cv2.imencode('.jpg', best_frame)
|
||||
if ret:
|
||||
jpg_bytes = jpg.tobytes()
|
||||
|
||||
Reference in New Issue
Block a user