瀏覽代碼

switch to a thread for object detection

blakeblackshear 6 年之前
父節點
當前提交
0514eeac03
共有 2 個文件被更改,包括 29 次插入109 次删除
  1. 3 34
      detect_objects.py
  2. 26 75
      frigate/object_detection.py

+ 3 - 34
detect_objects.py

@@ -75,22 +75,12 @@ def main():
     frame_lock = mp.Lock()
     # Condition for notifying that a new frame is ready
     frame_ready = mp.Condition()
-    # Shared memory array for passing prepped frame to tensorflow
-    prepped_frame_array = mp.Array(ctypes.c_uint8, 300*300*3)
-    # create shared value for storing the frame_time
-    prepped_frame_time = mp.Value('d', 0.0)
-    # Event for notifying that object detection needs a new frame
-    prepped_frame_grabbed = mp.Event()
-    # Event for notifying that new frame is ready for detection
-    prepped_frame_ready = mp.Event()
     # Condition for notifying that objects were parsed
     objects_parsed = mp.Condition()
     # Queue for detected objects
-    object_queue = mp.Queue()
+    object_queue = queue.Queue()
     # Queue for prepped frames
     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)
 
     # shape current frame so it can be treated as an image
     frame_arr = tonumpyarray(shared_arr).reshape(frame_shape)
@@ -113,28 +103,11 @@ def main():
         ))
 
     prepped_queue_processor = PreppedQueueProcessor(
-        prepped_frame_array,
-        prepped_frame_time,
-        prepped_frame_ready,
-        prepped_frame_grabbed,
-        prepped_frame_box,
-        prepped_frame_queue
+        prepped_frame_queue,
+        object_queue
     )
     prepped_queue_processor.start()
 
-    # create a process for object detection
-    # if the coprocessor is doing the work, can this run as a thread
-    # since it is waiting for IO?
-    detection_process = mp.Process(target=detect_objects, args=(
-        prepped_frame_array,
-        prepped_frame_time,
-        prepped_frame_ready,
-        prepped_frame_grabbed,
-        prepped_frame_box,
-        object_queue, DEBUG
-    ))
-    detection_process.daemon = True
-
     # start a thread to store recent motion frames for processing
     frame_tracker = FrameTracker(frame_arr, shared_frame_time, frame_ready, frame_lock, 
         recent_frames)
@@ -176,9 +149,6 @@ def main():
     # start the object detection prep threads
     for detection_prep_thread in detection_prep_threads:
         detection_prep_thread.start()
-    
-    detection_process.start()
-    print("detection_process pid ", detection_process.pid)
 
     # create a flask app that encodes frames a mjpeg on demand
     app = Flask(__name__)
@@ -237,7 +207,6 @@ def main():
     capture_process.join()
     for detection_prep_thread in detection_prep_threads:
         detection_prep_thread.join()
-    detection_process.join()
     frame_tracker.join()
     best_person_frame.join()
     object_parser.join()

+ 26 - 75
frigate/object_detection.py

@@ -21,89 +21,40 @@ def ReadLabelFile(file_path):
         ret[int(pair[0])] = pair[1].strip()
     return ret
 
-def detect_objects(prepped_frame_array, prepped_frame_time,
-                   prepped_frame_ready, prepped_frame_grabbed,
-                   prepped_frame_box, object_queue, debug):
-    prepped_frame_np = tonumpyarray(prepped_frame_array)
-
-    # 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]
-    while True:
-        # wait until a frame is ready
-        prepped_frame_ready.wait()
-
-        prepped_frame_copy = prepped_frame_np.copy()
-        frame_time = prepped_frame_time.value
-        region_box[:] = prepped_frame_box
-
-        prepped_frame_grabbed.set()
-        # print("Grabbed " + str(region_box[1]) + "," + str(region_box[2]))
-
-        # Actual detection.
-        objects = engine.DetectWithInputTensor(prepped_frame_copy, threshold=0.5, top_k=3)
-        # time.sleep(0.1)
-        # objects = []
-        # 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])
-        #                 })
-
 class PreppedQueueProcessor(threading.Thread):
-    def __init__(self, prepped_frame_array,
-        prepped_frame_time,
-        prepped_frame_ready,
-        prepped_frame_grabbed,
-        prepped_frame_box,
-        prepped_frame_queue):
+    def __init__(self, prepped_frame_queue, object_queue):
 
         threading.Thread.__init__(self)
-        self.prepped_frame_array = prepped_frame_array
-        self.prepped_frame_time = prepped_frame_time
-        self.prepped_frame_ready = prepped_frame_ready
-        self.prepped_frame_grabbed = prepped_frame_grabbed
-        self.prepped_frame_box = prepped_frame_box
         self.prepped_frame_queue = prepped_frame_queue
+        self.object_queue = object_queue
+        
+        # Load the edgetpu engine and labels
+        self.engine = DetectionEngine(PATH_TO_CKPT)
+        self.labels = ReadLabelFile(PATH_TO_LABELS)
 
     def run(self):
-        prepped_frame_np = tonumpyarray(self.prepped_frame_array)
         # process queue...
         while True:
             frame = self.prepped_frame_queue.get()
             # print(self.prepped_frame_queue.qsize())
-            prepped_frame_np[:] = frame['frame']
-            self.prepped_frame_time.value = frame['frame_time']
-            self.prepped_frame_box[0] = frame['region_size']
-            self.prepped_frame_box[1] = frame['region_x_offset']
-            self.prepped_frame_box[2] = frame['region_y_offset']
-            # print("Passed " + str(frame['region_x_offset']) + "," + str(frame['region_x_offset']))
-            self.prepped_frame_ready.set()
-            self.prepped_frame_grabbed.wait()
-            self.prepped_frame_grabbed.clear()
-            self.prepped_frame_ready.clear()
+            # Actual detection.
+            objects = self.engine.DetectWithInputTensor(frame['frame'], threshold=0.5, top_k=3)
+            # time.sleep(0.1)
+            # objects = []
+            # print(engine.get_inference_time())
+            # put detected objects in the queue
+            if objects:
+                for obj in objects:
+                    box = obj.bounding_box.flatten().tolist()
+                    self.object_queue.put({
+                                'frame_time': frame['frame_time'],
+                                'name': str(self.labels[obj.label_id]),
+                                'score': float(obj.score),
+                                'xmin': int((box[0] * frame['region_size']) + frame['region_x_offset']),
+                                'ymin': int((box[1] * frame['region_size']) + frame['region_y_offset']),
+                                'xmax': int((box[2] * frame['region_size']) + frame['region_x_offset']),
+                                'ymax': int((box[3] * frame['region_size']) + frame['region_y_offset'])
+                            })
 
 
 # should this be a region class?
@@ -156,5 +107,5 @@ class FramePrepper(threading.Thread):
                     'region_x_offset': self.region_x_offset,
                     'region_y_offset': self.region_y_offset
                 })
-            # else:
-            #     print("queue full. moving on")
+            else:
+                print("queue full. moving on")