forked from Github/frigate
Compare commits
41 Commits
v0.4.0-bet
...
v0.5.0-rc4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd057370e1 | ||
|
|
6263912655 | ||
|
|
af247275cf | ||
|
|
1198c29dac | ||
|
|
169603d3ff | ||
|
|
dc7eecebc6 | ||
|
|
0dd4087d5d | ||
|
|
6ecf87fc60 | ||
|
|
ebcf1482f8 | ||
|
|
50bcf60893 | ||
|
|
38efbd63ea | ||
|
|
50bcad8b77 | ||
|
|
cfffb219ae | ||
|
|
382d7be50a | ||
|
|
f43dc36a37 | ||
|
|
38e7fa07d2 | ||
|
|
e261c20819 | ||
|
|
3a66e672d3 | ||
|
|
2aada930e3 | ||
|
|
d87f4407a0 | ||
|
|
be5a114f6a | ||
|
|
32b212c7b6 | ||
|
|
76c8e3a12f | ||
|
|
16f7a361c3 | ||
|
|
634b87307f | ||
|
|
1d4fbbdba3 | ||
|
|
65579e9cbf | ||
|
|
49dc029c43 | ||
|
|
08174d8db2 | ||
|
|
5199242a68 | ||
|
|
725dd3220c | ||
|
|
10dc56f6ea | ||
|
|
cc2abe93a6 | ||
|
|
0c6717090c | ||
|
|
f5a2252b29 | ||
|
|
02efb6f415 | ||
|
|
5b4c6e50bc | ||
|
|
9cc46a71cb | ||
|
|
be1673b00a | ||
|
|
b6130e77ff | ||
|
|
4180c710cd |
@@ -1,4 +1,4 @@
|
||||
FROM debian:stretch-slim
|
||||
FROM ubuntu:18.04
|
||||
LABEL maintainer "blakeb@blakeshome.com"
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
@@ -16,7 +16,7 @@ RUN apt -qq update && apt -qq install --no-install-recommends -y \
|
||||
# pillow-simd
|
||||
# zlib1g-dev libjpeg-dev \
|
||||
# VAAPI drivers for Intel hardware accel
|
||||
i965-va-driver vainfo \
|
||||
libva-drm2 libva2 i965-va-driver vainfo \
|
||||
&& 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 \
|
||||
|
||||
@@ -81,6 +81,12 @@ cameras:
|
||||
# hwaccel_args: []
|
||||
# input_args: []
|
||||
# output_args: []
|
||||
|
||||
################
|
||||
## Optionally specify the resolution of the video feed. Frigate will try to auto detect if not specified
|
||||
################
|
||||
# height: 1280
|
||||
# width: 720
|
||||
|
||||
################
|
||||
## Optional mask. Must be the same dimensions as your video feed.
|
||||
@@ -100,7 +106,19 @@ cameras:
|
||||
take_frame: 1
|
||||
|
||||
################
|
||||
# Overrides for global object config
|
||||
# The number of seconds frigate will allow a camera to go without sending a frame before
|
||||
# assuming the ffmpeg process has a problem and restarting.
|
||||
################
|
||||
# watchdog_timeout: 300
|
||||
|
||||
################
|
||||
# Configuration for the snapshot sent over mqtt
|
||||
################
|
||||
snapshots:
|
||||
show_timestamp: True
|
||||
|
||||
################
|
||||
# Camera level object config. This config is merged with the global config above.
|
||||
################
|
||||
objects:
|
||||
track:
|
||||
|
||||
@@ -88,21 +88,30 @@ class DetectedObjectsProcessor(threading.Thread):
|
||||
obj['clipped'] = True
|
||||
|
||||
# Compute the area
|
||||
# TODO: +1 right?
|
||||
obj['area'] = (obj['box']['xmax']-obj['box']['xmin'])*(obj['box']['ymax']-obj['box']['ymin'])
|
||||
|
||||
self.camera.detected_objects[frame['frame_time']].append(obj)
|
||||
|
||||
# TODO: use in_process and processed counts instead to avoid lock
|
||||
with self.camera.regions_in_process_lock:
|
||||
self.camera.regions_in_process[frame['frame_time']] -= 1
|
||||
if frame['frame_time'] in self.camera.regions_in_process:
|
||||
self.camera.regions_in_process[frame['frame_time']] -= 1
|
||||
# print(f"{frame['frame_time']} remaining regions {self.camera.regions_in_process[frame['frame_time']]}")
|
||||
|
||||
if self.camera.regions_in_process[frame['frame_time']] == 0:
|
||||
del self.camera.regions_in_process[frame['frame_time']]
|
||||
# print(f"{frame['frame_time']} no remaining regions")
|
||||
if self.camera.regions_in_process[frame['frame_time']] == 0:
|
||||
del self.camera.regions_in_process[frame['frame_time']]
|
||||
# print(f"{frame['frame_time']} no remaining regions")
|
||||
self.camera.finished_frame_queue.put(frame['frame_time'])
|
||||
else:
|
||||
self.camera.finished_frame_queue.put(frame['frame_time'])
|
||||
|
||||
# Thread that checks finished frames for clipped objects and sends back
|
||||
# for processing if needed
|
||||
# TODO: evaluate whether or not i really need separate threads/queues for each step
|
||||
# given that only 1 thread will really be able to run at a time. you need a
|
||||
# separate process to actually do things in parallel for when you are CPU bound.
|
||||
# threads are good when you are waiting and could be processing while you wait
|
||||
class RegionRefiner(threading.Thread):
|
||||
def __init__(self, camera):
|
||||
threading.Thread.__init__(self)
|
||||
@@ -360,6 +369,9 @@ class ObjectTracker(threading.Thread):
|
||||
# than the number of existing object centroids we need to
|
||||
# register each new input centroid as a trackable object
|
||||
# if D.shape[0] < D.shape[1]:
|
||||
# TODO: rather than assuming these are new objects, we could
|
||||
# look to see if any of the remaining boxes have a large amount
|
||||
# of overlap...
|
||||
for col in unusedCols:
|
||||
self.register(col, group[col])
|
||||
|
||||
@@ -399,7 +411,8 @@ class BestFrames(threading.Thread):
|
||||
obj['box']['xmax'], obj['box']['ymax'], obj['name'], "{}% {}".format(int(obj['score']*100), obj['area']))
|
||||
|
||||
# print a timestamp
|
||||
time_to_show = datetime.datetime.fromtimestamp(obj['frame_time']).strftime("%m/%d/%Y %H:%M:%S")
|
||||
cv2.putText(best_frame, time_to_show, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, fontScale=.8, color=(255, 255, 255), thickness=2)
|
||||
if self.camera.snapshot_config['show_timestamp']:
|
||||
time_to_show = datetime.datetime.fromtimestamp(obj['frame_time']).strftime("%m/%d/%Y %H:%M:%S")
|
||||
cv2.putText(best_frame, time_to_show, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, fontScale=.8, color=(255, 255, 255), thickness=2)
|
||||
|
||||
self.best_frames[name] = best_frame
|
||||
@@ -11,6 +11,7 @@ import numpy as np
|
||||
import prctl
|
||||
import copy
|
||||
import itertools
|
||||
import json
|
||||
from collections import defaultdict
|
||||
from frigate.util import tonumpyarray, LABELS, draw_box_with_label, calculate_region, EventsPerSecond
|
||||
from frigate.object_detection import RegionPrepper, RegionRequester
|
||||
@@ -42,8 +43,29 @@ class FrameTracker(threading.Thread):
|
||||
del self.recent_frames[k]
|
||||
|
||||
def get_frame_shape(source):
|
||||
# capture a single frame and check the frame shape so the correct array
|
||||
# size can be allocated in memory
|
||||
ffprobe_cmd = " ".join([
|
||||
'ffprobe',
|
||||
'-v',
|
||||
'panic',
|
||||
'-show_error',
|
||||
'-show_streams',
|
||||
'-of',
|
||||
'json',
|
||||
'"'+source+'"'
|
||||
])
|
||||
print(ffprobe_cmd)
|
||||
p = sp.Popen(ffprobe_cmd, stdout=sp.PIPE, shell=True)
|
||||
(output, err) = p.communicate()
|
||||
p_status = p.wait()
|
||||
info = json.loads(output)
|
||||
print(info)
|
||||
|
||||
video_info = [s for s in info['streams'] if s['codec_type'] == 'video'][0]
|
||||
|
||||
if video_info['height'] != 0 and video_info['width'] != 0:
|
||||
return (video_info['height'], video_info['width'], 3)
|
||||
|
||||
# fallback to using opencv if ffprobe didnt succeed
|
||||
video = cv2.VideoCapture(source)
|
||||
ret, frame = video.read()
|
||||
frame_shape = frame.shape
|
||||
@@ -65,7 +87,7 @@ class CameraWatchdog(threading.Thread):
|
||||
# wait a bit before checking
|
||||
time.sleep(10)
|
||||
|
||||
if self.camera.frame_time.value != 0.0 and (datetime.datetime.now().timestamp() - self.camera.frame_time.value) > 300:
|
||||
if self.camera.frame_time.value != 0.0 and (datetime.datetime.now().timestamp() - self.camera.frame_time.value) > self.camera.watchdog_timeout:
|
||||
print(self.camera.name + ": last frame is more than 5 minutes old, restarting camera capture...")
|
||||
self.camera.start_or_restart_capture()
|
||||
time.sleep(5)
|
||||
@@ -151,8 +173,15 @@ class Camera:
|
||||
camera_objects_config = config.get('objects', {})
|
||||
|
||||
self.take_frame = self.config.get('take_frame', 1)
|
||||
self.watchdog_timeout = self.config.get('watchdog_timeout', 300)
|
||||
self.snapshot_config = {
|
||||
'show_timestamp': self.config.get('snapshots', {}).get('show_timestamp', True)
|
||||
}
|
||||
self.regions = self.config['regions']
|
||||
self.frame_shape = get_frame_shape(self.ffmpeg_input)
|
||||
if 'width' in self.config and 'height' in self.config:
|
||||
self.frame_shape = (self.config['height'], self.config['width'], 3)
|
||||
else:
|
||||
self.frame_shape = get_frame_shape(self.ffmpeg_input)
|
||||
self.frame_size = self.frame_shape[0] * self.frame_shape[1] * self.frame_shape[2]
|
||||
self.mqtt_client = mqtt_client
|
||||
self.mqtt_topic_prefix = '{}/{}'.format(mqtt_prefix, self.name)
|
||||
|
||||
Reference in New Issue
Block a user