Browse Source

looping over all regions with motion. ugly, but working

blakeblackshear 6 years ago
parent
commit
7d3027e056
2 changed files with 62 additions and 57 deletions
  1. 14 20
      detect_objects.py
  2. 48 37
      frigate/object_detection.py

+ 14 - 20
detect_objects.py

@@ -52,11 +52,12 @@ def main():
             'mask': region_mask,
             # Event for motion detection signaling
             'motion_detected': mp.Event(),
-            # create shared array for storing 10 detected objects
-            # note: this must be a double even though the value you are storing
-            #       is a float. otherwise it stops updating the value in shared
-            #       memory. probably something to do with the size of the memory block
-            'output_array': mp.Array(ctypes.c_double, 6*10)
+            # array for prepped frame with shape (1, 300, 300, 3)
+            'prepped_frame_array': mp.Array(ctypes.c_uint8, 300*300*3),
+            # shared value for storing the prepped_frame_time
+            'prepped_frame_time': mp.Value('d', 0.0),
+            # Lock to control access to the prepped frame
+            'prepped_frame_lock': mp.Lock()
         })
     # capture a single frame and check the frame shape so the correct array
     # size can be allocated in memory
@@ -85,16 +86,6 @@ def main():
     objects_parsed = mp.Condition()
     # Queue for detected objects
     object_queue = mp.Queue()
-    # array for prepped frame with shape (1, 300, 300, 3)
-    prepped_frame_array = mp.Array(ctypes.c_uint8, 300*300*3)
-    # shared value for storing the prepped_frame_time
-    prepped_frame_time = mp.Value('d', 0.0)
-    # Condition for notifying that a new prepped frame is ready
-    prepped_frame_ready = mp.Condition()
-    # Lock to control access to the prepped frame
-    prepped_frame_lock = mp.Lock()
-    # array for prepped frame box [x1, y1, x2, y2]
-    prepped_frame_box = mp.Array(ctypes.c_uint16, 4)
 
     # shape current frame so it can be treated as an image
     frame_arr = tonumpyarray(shared_arr).reshape(frame_shape)
@@ -116,8 +107,8 @@ def main():
             region['motion_detected'],
             frame_shape, 
             region['size'], region['x_offset'], region['y_offset'],
-            prepped_frame_array, prepped_frame_time, prepped_frame_ready,
-            prepped_frame_lock, prepped_frame_box))
+            region['prepped_frame_array'], region['prepped_frame_time'],
+            region['prepped_frame_lock']))
         detection_prep_process.daemon = True
         detection_prep_processes.append(detection_prep_process)
 
@@ -135,9 +126,12 @@ def main():
 
     # create a process for object detection
     detection_process = mp.Process(target=detect_objects, args=(
-        prepped_frame_array, prepped_frame_time,
-        prepped_frame_lock, prepped_frame_ready,
-        prepped_frame_box, object_queue, DEBUG
+        [region['prepped_frame_array'] for region in regions],
+        [region['prepped_frame_time'] for region in regions],
+        [region['prepped_frame_lock'] for region in regions],
+        [[region['size'], region['x_offset'], region['y_offset']] for region in regions],
+        motion_changed, [region['motion_detected'] for region in regions],
+        object_queue, DEBUG
     ))
     detection_process.daemon = True
 

+ 48 - 37
frigate/object_detection.py

@@ -19,48 +19,64 @@ def ReadLabelFile(file_path):
         ret[int(pair[0])] = pair[1].strip()
     return ret
 
-def detect_objects(prepped_frame_array, prepped_frame_time, prepped_frame_lock, 
-                   prepped_frame_ready, prepped_frame_box, object_queue, debug):
-    prepped_frame_np = tonumpyarray(prepped_frame_array)
+def detect_objects(prepped_frame_arrays, prepped_frame_times, prepped_frame_locks, 
+                   prepped_frame_boxes, motion_changed, motion_regions, object_queue, debug):
+    prepped_frame_nps = [tonumpyarray(prepped_frame_array) for prepped_frame_array in prepped_frame_arrays]
     # Load the edgetpu engine and labels
     engine = DetectionEngine(PATH_TO_CKPT)
     labels = ReadLabelFile(PATH_TO_LABELS)
 
     frame_time = 0.0
-    region_box = [0,0,0,0]
+    region_box = [0,0,0]
     while True:
-        with prepped_frame_ready:
-            prepped_frame_ready.wait()
+        # while there is motion
+        while len([r for r in motion_regions if r.is_set()]) > 0:
         
-        # make a copy of the cropped frame
-        with prepped_frame_lock:
-            prepped_frame_copy = prepped_frame_np.copy()
-            frame_time = prepped_frame_time.value
-            region_box[:] = prepped_frame_box
+            # loop over all the motion regions and look for objects
+            for i, motion_region in enumerate(motion_regions):
+                # skip the region if no motion
+                if not motion_region.is_set():
+                    continue
 
-        # Actual detection.
-        objects = engine.DetectWithInputTensor(prepped_frame_copy, threshold=0.5, top_k=3)
-        # print(engine.get_inference_time())
-        # put detected objects in the queue
-        if objects:
-            # assumes square
-            region_size = region_box[2]-region_box[0]
-            for obj in objects:
-                box = obj.bounding_box.flatten().tolist()
-                object_queue.put({
-                            'frame_time': frame_time,
-                            'name': str(labels[obj.label_id]),
-                            'score': float(obj.score),
-                            'xmin': int((box[0] * region_size) + region_box[0]),
-                            'ymin': int((box[1] * region_size) + region_box[1]),
-                            'xmax': int((box[2] * region_size) + region_box[0]),
-                            'ymax': int((box[3] * region_size) + region_box[1])
-                        })
+                # make a copy of the cropped frame
+                with prepped_frame_locks[i]:
+                    prepped_frame_copy = prepped_frame_nps[i].copy()
+                    frame_time = prepped_frame_times[i].value
+                    region_box[:] = prepped_frame_boxes[i]
+
+                # Actual detection.
+                objects = engine.DetectWithInputTensor(prepped_frame_copy, threshold=0.5, top_k=3)
+                # print(engine.get_inference_time())
+                # put detected objects in the queue
+                if objects:
+                    for obj in objects:
+                        box = obj.bounding_box.flatten().tolist()
+                        object_queue.put({
+                                    'frame_time': frame_time,
+                                    'name': str(labels[obj.label_id]),
+                                    'score': float(obj.score),
+                                    'xmin': int((box[0] * region_box[0]) + region_box[1]),
+                                    'ymin': int((box[1] * region_box[0]) + region_box[2]),
+                                    'xmax': int((box[2] * region_box[0]) + region_box[1]),
+                                    'ymax': int((box[3] * region_box[0]) + region_box[2])
+                                })
+                else:
+                    object_queue.put({
+                                    'frame_time': frame_time,
+                                    'name': 'dummy',
+                                    'score': 0.99,
+                                    'xmin': int(0 + region_box[1]),
+                                    'ymin': int(0 + region_box[2]),
+                                    'xmax': int(10 + region_box[1]),
+                                    'ymax': int(10 + region_box[2])
+                                })
+        # wait for the global motion flag to change
+        with motion_changed:
+            motion_changed.wait()
 
 def prep_for_detection(shared_whole_frame_array, shared_frame_time, frame_lock, frame_ready, 
                    motion_detected, frame_shape, region_size, region_x_offset, region_y_offset,
-                   prepped_frame_array, prepped_frame_time, prepped_frame_ready, prepped_frame_lock,
-                   prepped_frame_box):
+                   prepped_frame_array, prepped_frame_time, prepped_frame_lock):
     # shape shared input array into frame for processing
     shared_whole_frame = tonumpyarray(shared_whole_frame_array).reshape(frame_shape)
 
@@ -94,9 +110,4 @@ def prep_for_detection(shared_whole_frame_array, shared_frame_time, frame_lock,
         # copy the prepped frame to the shared output array
         with prepped_frame_lock:
             shared_prepped_frame[:] = frame_expanded
-            prepped_frame_time = frame_time
-            prepped_frame_box[:] = [region_x_offset, region_y_offset, region_x_offset+region_size, region_y_offset+region_size]
-
-        # signal that a prepped frame is ready
-        with prepped_frame_ready:
-            prepped_frame_ready.notify_all()
+            prepped_frame_time.value = frame_time