mirror of
https://github.com/blakeblackshear/frigate.git
synced 2024-11-21 19:07:46 +01:00
removing motion detection
This commit is contained in:
parent
48aa245914
commit
200d769003
@ -37,22 +37,16 @@ DEBUG = (os.getenv('DEBUG') == '1')
|
|||||||
|
|
||||||
def main():
|
def main():
|
||||||
DETECTED_OBJECTS = []
|
DETECTED_OBJECTS = []
|
||||||
recent_motion_frames = {}
|
recent_frames = {}
|
||||||
# Parse selected regions
|
# Parse selected regions
|
||||||
regions = []
|
regions = []
|
||||||
for region_string in REGIONS.split(':'):
|
for region_string in REGIONS.split(':'):
|
||||||
region_parts = region_string.split(',')
|
region_parts = region_string.split(',')
|
||||||
region_mask_image = cv2.imread("/config/{}".format(region_parts[5]), cv2.IMREAD_GRAYSCALE)
|
|
||||||
region_mask = np.where(region_mask_image==[0])
|
|
||||||
regions.append({
|
regions.append({
|
||||||
'size': int(region_parts[0]),
|
'size': int(region_parts[0]),
|
||||||
'x_offset': int(region_parts[1]),
|
'x_offset': int(region_parts[1]),
|
||||||
'y_offset': int(region_parts[2]),
|
'y_offset': int(region_parts[2]),
|
||||||
'min_person_area': int(region_parts[3]),
|
'min_person_area': int(region_parts[3]),
|
||||||
'min_object_size': int(region_parts[4]),
|
|
||||||
'mask': region_mask,
|
|
||||||
# Event for motion detection signaling
|
|
||||||
'motion_detected': mp.Event(),
|
|
||||||
# array for prepped frame with shape (1, 300, 300, 3)
|
# array for prepped frame with shape (1, 300, 300, 3)
|
||||||
'prepped_frame_array': mp.Array(ctypes.c_uint8, 300*300*3),
|
'prepped_frame_array': mp.Array(ctypes.c_uint8, 300*300*3),
|
||||||
# shared value for storing the prepped_frame_time
|
# shared value for storing the prepped_frame_time
|
||||||
@ -81,14 +75,13 @@ def main():
|
|||||||
frame_lock = mp.Lock()
|
frame_lock = mp.Lock()
|
||||||
# Condition for notifying that a new frame is ready
|
# Condition for notifying that a new frame is ready
|
||||||
frame_ready = mp.Condition()
|
frame_ready = mp.Condition()
|
||||||
# Condition for notifying that motion status changed globally
|
# Shared memory array for passing prepped frame to tensorflow
|
||||||
motion_changed = mp.Condition()
|
|
||||||
|
|
||||||
prepped_frame_array = mp.Array(ctypes.c_uint8, 300*300*3)
|
prepped_frame_array = mp.Array(ctypes.c_uint8, 300*300*3)
|
||||||
# create shared value for storing the frame_time
|
# create shared value for storing the frame_time
|
||||||
prepped_frame_time = mp.Value('d', 0.0)
|
prepped_frame_time = mp.Value('d', 0.0)
|
||||||
# Event for notifying that object detection needs a new frame
|
# Event for notifying that object detection needs a new frame
|
||||||
prepped_frame_grabbed = mp.Event()
|
prepped_frame_grabbed = mp.Event()
|
||||||
|
# Event for notifying that new frame is ready for detection
|
||||||
prepped_frame_ready = mp.Event()
|
prepped_frame_ready = mp.Event()
|
||||||
# Condition for notifying that objects were parsed
|
# Condition for notifying that objects were parsed
|
||||||
objects_parsed = mp.Condition()
|
objects_parsed = mp.Condition()
|
||||||
@ -96,6 +89,7 @@ def main():
|
|||||||
object_queue = mp.Queue()
|
object_queue = mp.Queue()
|
||||||
# Queue for prepped frames
|
# Queue for prepped frames
|
||||||
prepped_frame_queue = queue.Queue(len(regions)*2)
|
prepped_frame_queue = queue.Queue(len(regions)*2)
|
||||||
|
# Array for passing original region box to compute object bounding box
|
||||||
prepped_frame_box = mp.Array(ctypes.c_uint16, 3)
|
prepped_frame_box = mp.Array(ctypes.c_uint16, 3)
|
||||||
|
|
||||||
# shape current frame so it can be treated as an image
|
# shape current frame so it can be treated as an image
|
||||||
@ -106,32 +100,18 @@ def main():
|
|||||||
shared_frame_time, frame_lock, frame_ready, frame_shape, RTSP_URL))
|
shared_frame_time, frame_lock, frame_ready, frame_shape, RTSP_URL))
|
||||||
capture_process.daemon = True
|
capture_process.daemon = True
|
||||||
|
|
||||||
# for each region, start a separate process for motion detection and object detection
|
# for each region, start a separate thread to resize the region and prep for detection
|
||||||
detection_prep_threads = []
|
detection_prep_threads = []
|
||||||
motion_processes = []
|
|
||||||
for region in regions:
|
for region in regions:
|
||||||
detection_prep_threads.append(FramePrepper(
|
detection_prep_threads.append(FramePrepper(
|
||||||
frame_arr,
|
frame_arr,
|
||||||
shared_frame_time,
|
shared_frame_time,
|
||||||
frame_ready,
|
frame_ready,
|
||||||
frame_lock,
|
frame_lock,
|
||||||
region['motion_detected'],
|
|
||||||
region['size'], region['x_offset'], region['y_offset'],
|
region['size'], region['x_offset'], region['y_offset'],
|
||||||
prepped_frame_queue
|
prepped_frame_queue
|
||||||
))
|
))
|
||||||
|
|
||||||
motion_process = mp.Process(target=detect_motion, args=(shared_arr,
|
|
||||||
shared_frame_time,
|
|
||||||
frame_lock, frame_ready,
|
|
||||||
region['motion_detected'],
|
|
||||||
motion_changed,
|
|
||||||
frame_shape,
|
|
||||||
region['size'], region['x_offset'], region['y_offset'],
|
|
||||||
region['min_object_size'], region['mask'],
|
|
||||||
DEBUG))
|
|
||||||
motion_process.daemon = True
|
|
||||||
motion_processes.append(motion_process)
|
|
||||||
|
|
||||||
prepped_queue_processor = PreppedQueueProcessor(
|
prepped_queue_processor = PreppedQueueProcessor(
|
||||||
prepped_frame_array,
|
prepped_frame_array,
|
||||||
prepped_frame_time,
|
prepped_frame_time,
|
||||||
@ -157,20 +137,18 @@ def main():
|
|||||||
|
|
||||||
# start a thread to store recent motion frames for processing
|
# start a thread to store recent motion frames for processing
|
||||||
frame_tracker = FrameTracker(frame_arr, shared_frame_time, frame_ready, frame_lock,
|
frame_tracker = FrameTracker(frame_arr, shared_frame_time, frame_ready, frame_lock,
|
||||||
recent_motion_frames, motion_changed, [region['motion_detected'] for region in regions])
|
recent_frames)
|
||||||
frame_tracker.start()
|
frame_tracker.start()
|
||||||
|
|
||||||
# start a thread to store the highest scoring recent person frame
|
# start a thread to store the highest scoring recent person frame
|
||||||
best_person_frame = BestPersonFrame(objects_parsed, recent_motion_frames, DETECTED_OBJECTS,
|
best_person_frame = BestPersonFrame(objects_parsed, recent_frames, DETECTED_OBJECTS)
|
||||||
motion_changed, [region['motion_detected'] for region in regions])
|
|
||||||
best_person_frame.start()
|
best_person_frame.start()
|
||||||
|
|
||||||
# start a thread to parse objects from the queue
|
# start a thread to parse objects from the queue
|
||||||
object_parser = ObjectParser(object_queue, objects_parsed, DETECTED_OBJECTS)
|
object_parser = ObjectParser(object_queue, objects_parsed, DETECTED_OBJECTS)
|
||||||
object_parser.start()
|
object_parser.start()
|
||||||
# start a thread to expire objects from the detected objects list
|
# start a thread to expire objects from the detected objects list
|
||||||
object_cleaner = ObjectCleaner(objects_parsed, DETECTED_OBJECTS,
|
object_cleaner = ObjectCleaner(objects_parsed, DETECTED_OBJECTS)
|
||||||
motion_changed, [region['motion_detected'] for region in regions])
|
|
||||||
object_cleaner.start()
|
object_cleaner.start()
|
||||||
|
|
||||||
# connect to mqtt and setup last will
|
# connect to mqtt and setup last will
|
||||||
@ -191,33 +169,17 @@ def main():
|
|||||||
mqtt_publisher = MqttObjectPublisher(client, MQTT_TOPIC_PREFIX, objects_parsed, DETECTED_OBJECTS)
|
mqtt_publisher = MqttObjectPublisher(client, MQTT_TOPIC_PREFIX, objects_parsed, DETECTED_OBJECTS)
|
||||||
mqtt_publisher.start()
|
mqtt_publisher.start()
|
||||||
|
|
||||||
# start thread to publish motion status
|
|
||||||
mqtt_motion_publisher = MqttMotionPublisher(client, MQTT_TOPIC_PREFIX, motion_changed,
|
|
||||||
[region['motion_detected'] for region in regions])
|
|
||||||
mqtt_motion_publisher.start()
|
|
||||||
|
|
||||||
# start the process of capturing frames
|
# start the process of capturing frames
|
||||||
capture_process.start()
|
capture_process.start()
|
||||||
print("capture_process pid ", capture_process.pid)
|
print("capture_process pid ", capture_process.pid)
|
||||||
|
|
||||||
# start the object detection prep processes
|
# start the object detection prep threads
|
||||||
for detection_prep_thread in detection_prep_threads:
|
for detection_prep_thread in detection_prep_threads:
|
||||||
detection_prep_thread.start()
|
detection_prep_thread.start()
|
||||||
|
|
||||||
detection_process.start()
|
detection_process.start()
|
||||||
print("detection_process pid ", detection_process.pid)
|
print("detection_process pid ", detection_process.pid)
|
||||||
|
|
||||||
# start the motion detection processes
|
|
||||||
# for motion_process in motion_processes:
|
|
||||||
# motion_process.start()
|
|
||||||
# print("motion_process pid ", motion_process.pid)
|
|
||||||
|
|
||||||
# TEMP: short circuit the motion detection
|
|
||||||
for region in regions:
|
|
||||||
region['motion_detected'].set()
|
|
||||||
with motion_changed:
|
|
||||||
motion_changed.notify_all()
|
|
||||||
|
|
||||||
# create a flask app that encodes frames a mjpeg on demand
|
# create a flask app that encodes frames a mjpeg on demand
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
@ -259,8 +221,6 @@ def main():
|
|||||||
|
|
||||||
for region in regions:
|
for region in regions:
|
||||||
color = (255,255,255)
|
color = (255,255,255)
|
||||||
if region['motion_detected'].is_set():
|
|
||||||
color = (0,255,0)
|
|
||||||
cv2.rectangle(frame, (region['x_offset'], region['y_offset']),
|
cv2.rectangle(frame, (region['x_offset'], region['y_offset']),
|
||||||
(region['x_offset']+region['size'], region['y_offset']+region['size']),
|
(region['x_offset']+region['size'], region['y_offset']+region['size']),
|
||||||
color, 2)
|
color, 2)
|
||||||
@ -277,8 +237,6 @@ def main():
|
|||||||
capture_process.join()
|
capture_process.join()
|
||||||
for detection_prep_thread in detection_prep_threads:
|
for detection_prep_thread in detection_prep_threads:
|
||||||
detection_prep_thread.join()
|
detection_prep_thread.join()
|
||||||
for motion_process in motion_processes:
|
|
||||||
motion_process.join()
|
|
||||||
detection_process.join()
|
detection_process.join()
|
||||||
frame_tracker.join()
|
frame_tracker.join()
|
||||||
best_person_frame.join()
|
best_person_frame.join()
|
||||||
|
@ -47,7 +47,7 @@ def detect_objects(prepped_frame_array, prepped_frame_time,
|
|||||||
objects = engine.DetectWithInputTensor(prepped_frame_copy, threshold=0.5, top_k=3)
|
objects = engine.DetectWithInputTensor(prepped_frame_copy, threshold=0.5, top_k=3)
|
||||||
# time.sleep(0.1)
|
# time.sleep(0.1)
|
||||||
# objects = []
|
# objects = []
|
||||||
print(engine.get_inference_time())
|
# print(engine.get_inference_time())
|
||||||
# put detected objects in the queue
|
# put detected objects in the queue
|
||||||
if objects:
|
if objects:
|
||||||
for obj in objects:
|
for obj in objects:
|
||||||
@ -109,7 +109,7 @@ class PreppedQueueProcessor(threading.Thread):
|
|||||||
# should this be a region class?
|
# should this be a region class?
|
||||||
class FramePrepper(threading.Thread):
|
class FramePrepper(threading.Thread):
|
||||||
def __init__(self, shared_frame, frame_time, frame_ready,
|
def __init__(self, shared_frame, frame_time, frame_ready,
|
||||||
frame_lock, motion_detected,
|
frame_lock,
|
||||||
region_size, region_x_offset, region_y_offset,
|
region_size, region_x_offset, region_y_offset,
|
||||||
prepped_frame_queue):
|
prepped_frame_queue):
|
||||||
|
|
||||||
@ -118,7 +118,6 @@ class FramePrepper(threading.Thread):
|
|||||||
self.frame_time = frame_time
|
self.frame_time = frame_time
|
||||||
self.frame_ready = frame_ready
|
self.frame_ready = frame_ready
|
||||||
self.frame_lock = frame_lock
|
self.frame_lock = frame_lock
|
||||||
self.motion_detected = motion_detected
|
|
||||||
self.region_size = region_size
|
self.region_size = region_size
|
||||||
self.region_x_offset = region_x_offset
|
self.region_x_offset = region_x_offset
|
||||||
self.region_y_offset = region_y_offset
|
self.region_y_offset = region_y_offset
|
||||||
@ -129,9 +128,6 @@ class FramePrepper(threading.Thread):
|
|||||||
while True:
|
while True:
|
||||||
now = datetime.datetime.now().timestamp()
|
now = datetime.datetime.now().timestamp()
|
||||||
|
|
||||||
# wait until motion is detected
|
|
||||||
self.motion_detected.wait()
|
|
||||||
|
|
||||||
with self.frame_ready:
|
with self.frame_ready:
|
||||||
# if there isnt a frame ready for processing or it is old, wait for a new frame
|
# if there isnt a frame ready for processing or it is old, wait for a new frame
|
||||||
if self.frame_time.value == frame_time or (now - self.frame_time.value) > 0.5:
|
if self.frame_time.value == frame_time or (now - self.frame_time.value) > 0.5:
|
||||||
|
@ -30,18 +30,14 @@ class ObjectParser(threading.Thread):
|
|||||||
self._objects_parsed.notify_all()
|
self._objects_parsed.notify_all()
|
||||||
|
|
||||||
class ObjectCleaner(threading.Thread):
|
class ObjectCleaner(threading.Thread):
|
||||||
def __init__(self, objects_parsed, detected_objects, motion_changed, motion_regions):
|
def __init__(self, objects_parsed, detected_objects):
|
||||||
threading.Thread.__init__(self)
|
threading.Thread.__init__(self)
|
||||||
self._objects_parsed = objects_parsed
|
self._objects_parsed = objects_parsed
|
||||||
self._detected_objects = detected_objects
|
self._detected_objects = detected_objects
|
||||||
self.motion_changed = motion_changed
|
|
||||||
self.motion_regions = motion_regions
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
while True:
|
while True:
|
||||||
|
|
||||||
# while there is motion
|
|
||||||
while len([r for r in self.motion_regions if r.is_set()]) > 0:
|
|
||||||
# wait a bit before checking for expired frames
|
# wait a bit before checking for expired frames
|
||||||
time.sleep(0.2)
|
time.sleep(0.2)
|
||||||
|
|
||||||
@ -64,31 +60,21 @@ class ObjectCleaner(threading.Thread):
|
|||||||
with self._objects_parsed:
|
with self._objects_parsed:
|
||||||
self._objects_parsed.notify_all()
|
self._objects_parsed.notify_all()
|
||||||
|
|
||||||
# wait for the global motion flag to change
|
|
||||||
with self.motion_changed:
|
|
||||||
self.motion_changed.wait()
|
|
||||||
|
|
||||||
# Maintains the frame and person with the highest score from the most recent
|
# Maintains the frame and person with the highest score from the most recent
|
||||||
# motion event
|
# motion event
|
||||||
class BestPersonFrame(threading.Thread):
|
class BestPersonFrame(threading.Thread):
|
||||||
def __init__(self, objects_parsed, recent_frames, detected_objects, motion_changed, motion_regions):
|
def __init__(self, objects_parsed, recent_frames, detected_objects):
|
||||||
threading.Thread.__init__(self)
|
threading.Thread.__init__(self)
|
||||||
self.objects_parsed = objects_parsed
|
self.objects_parsed = objects_parsed
|
||||||
self.recent_frames = recent_frames
|
self.recent_frames = recent_frames
|
||||||
self.detected_objects = detected_objects
|
self.detected_objects = detected_objects
|
||||||
self.motion_changed = motion_changed
|
|
||||||
self.motion_regions = motion_regions
|
|
||||||
self.best_person = None
|
self.best_person = None
|
||||||
self.best_frame = None
|
self.best_frame = None
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
motion_start = 0.0
|
|
||||||
motion_end = 0.0
|
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
|
|
||||||
# while there is motion
|
|
||||||
while len([r for r in self.motion_regions if r.is_set()]) > 0:
|
|
||||||
# wait until objects have been parsed
|
# wait until objects have been parsed
|
||||||
with self.objects_parsed:
|
with self.objects_parsed:
|
||||||
self.objects_parsed.wait()
|
self.objects_parsed.wait()
|
||||||
@ -133,11 +119,3 @@ class BestPersonFrame(threading.Thread):
|
|||||||
|
|
||||||
# convert back to BGR
|
# convert back to BGR
|
||||||
self.best_frame = cv2.cvtColor(best_frame, cv2.COLOR_RGB2BGR)
|
self.best_frame = cv2.cvtColor(best_frame, cv2.COLOR_RGB2BGR)
|
||||||
|
|
||||||
motion_end = datetime.datetime.now().timestamp()
|
|
||||||
|
|
||||||
# wait for the global motion flag to change
|
|
||||||
with self.motion_changed:
|
|
||||||
self.motion_changed.wait()
|
|
||||||
|
|
||||||
motion_start = datetime.datetime.now().timestamp()
|
|
@ -54,21 +54,17 @@ def fetch_frames(shared_arr, shared_frame_time, frame_lock, frame_ready, frame_s
|
|||||||
|
|
||||||
# Stores 2 seconds worth of frames when motion is detected so they can be used for other threads
|
# Stores 2 seconds worth of frames when motion is detected so they can be used for other threads
|
||||||
class FrameTracker(threading.Thread):
|
class FrameTracker(threading.Thread):
|
||||||
def __init__(self, shared_frame, frame_time, frame_ready, frame_lock, recent_frames, motion_changed, motion_regions):
|
def __init__(self, shared_frame, frame_time, frame_ready, frame_lock, recent_frames):
|
||||||
threading.Thread.__init__(self)
|
threading.Thread.__init__(self)
|
||||||
self.shared_frame = shared_frame
|
self.shared_frame = shared_frame
|
||||||
self.frame_time = frame_time
|
self.frame_time = frame_time
|
||||||
self.frame_ready = frame_ready
|
self.frame_ready = frame_ready
|
||||||
self.frame_lock = frame_lock
|
self.frame_lock = frame_lock
|
||||||
self.recent_frames = recent_frames
|
self.recent_frames = recent_frames
|
||||||
self.motion_changed = motion_changed
|
|
||||||
self.motion_regions = motion_regions
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
frame_time = 0.0
|
frame_time = 0.0
|
||||||
while True:
|
while True:
|
||||||
# while there is motion
|
|
||||||
while len([r for r in self.motion_regions if r.is_set()]) > 0:
|
|
||||||
now = datetime.datetime.now().timestamp()
|
now = datetime.datetime.now().timestamp()
|
||||||
# wait for a frame
|
# wait for a frame
|
||||||
with self.frame_ready:
|
with self.frame_ready:
|
||||||
@ -89,7 +85,3 @@ class FrameTracker(threading.Thread):
|
|||||||
for k in stored_frame_times:
|
for k in stored_frame_times:
|
||||||
if (now - k) > 2:
|
if (now - k) > 2:
|
||||||
del self.recent_frames[k]
|
del self.recent_frames[k]
|
||||||
|
|
||||||
# wait for the global motion flag to change
|
|
||||||
with self.motion_changed:
|
|
||||||
self.motion_changed.wait()
|
|
Loading…
Reference in New Issue
Block a user