mirror of
				https://github.com/blakeblackshear/frigate.git
				synced 2025-10-31 19:14:49 +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: | ||||
| with open('/config/config.yml') 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) | ||||
|  | ||||
| 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,10 +388,8 @@ 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 = 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)) | ||||
|   | ||||
| @@ -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', {})): | ||||
|                 # 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