objects.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. import time
  2. import datetime
  3. import threading
  4. import cv2
  5. from object_detection.utils import visualization_utils as vis_util
  6. class ObjectParser(threading.Thread):
  7. def __init__(self, object_queue, objects_parsed, detected_objects):
  8. threading.Thread.__init__(self)
  9. self._object_queue = object_queue
  10. self._objects_parsed = objects_parsed
  11. self._detected_objects = detected_objects
  12. def run(self):
  13. # frame_times = {}
  14. while True:
  15. obj = self._object_queue.get()
  16. # frame_time = obj['frame_time']
  17. # if frame_time in frame_times:
  18. # if frame_times[frame_time] == 7:
  19. # del frame_times[frame_time]
  20. # else:
  21. # frame_times[frame_time] += 1
  22. # else:
  23. # frame_times[frame_time] = 1
  24. # print(frame_times)
  25. self._detected_objects.append(obj)
  26. # notify that objects were parsed
  27. with self._objects_parsed:
  28. self._objects_parsed.notify_all()
  29. class ObjectCleaner(threading.Thread):
  30. def __init__(self, objects_parsed, detected_objects, motion_changed, motion_regions):
  31. threading.Thread.__init__(self)
  32. self._objects_parsed = objects_parsed
  33. self._detected_objects = detected_objects
  34. self.motion_changed = motion_changed
  35. self.motion_regions = motion_regions
  36. def run(self):
  37. while True:
  38. # while there is motion
  39. while len([r for r in self.motion_regions if r.is_set()]) > 0:
  40. # wait a bit before checking for expired frames
  41. time.sleep(0.2)
  42. # expire the objects that are more than 1 second old
  43. now = datetime.datetime.now().timestamp()
  44. # look for the first object found within the last second
  45. # (newest objects are appended to the end)
  46. detected_objects = self._detected_objects.copy()
  47. #print([round(now-obj['frame_time'],2) for obj in detected_objects])
  48. num_to_delete = 0
  49. for obj in detected_objects:
  50. if now-obj['frame_time']<2:
  51. break
  52. num_to_delete += 1
  53. if num_to_delete > 0:
  54. del self._detected_objects[:num_to_delete]
  55. # notify that parsed objects were changed
  56. with self._objects_parsed:
  57. self._objects_parsed.notify_all()
  58. # wait for the global motion flag to change
  59. with self.motion_changed:
  60. self.motion_changed.wait()
  61. # Maintains the frame and person with the highest score from the most recent
  62. # motion event
  63. class BestPersonFrame(threading.Thread):
  64. def __init__(self, objects_parsed, recent_frames, detected_objects, motion_changed, motion_regions):
  65. threading.Thread.__init__(self)
  66. self.objects_parsed = objects_parsed
  67. self.recent_frames = recent_frames
  68. self.detected_objects = detected_objects
  69. self.motion_changed = motion_changed
  70. self.motion_regions = motion_regions
  71. self.best_person = None
  72. self.best_frame = None
  73. def run(self):
  74. motion_start = 0.0
  75. motion_end = 0.0
  76. while True:
  77. # while there is motion
  78. while len([r for r in self.motion_regions if r.is_set()]) > 0:
  79. # wait until objects have been parsed
  80. with self.objects_parsed:
  81. self.objects_parsed.wait()
  82. # make a copy of detected objects
  83. detected_objects = self.detected_objects.copy()
  84. detected_people = [obj for obj in detected_objects if obj['name'] == 'person']
  85. # make a copy of the recent frames
  86. recent_frames = self.recent_frames.copy()
  87. # get the highest scoring person
  88. new_best_person = max(detected_people, key=lambda x:x['score'], default=self.best_person)
  89. # if there isnt a person, continue
  90. if new_best_person is None:
  91. continue
  92. # if there is no current best_person
  93. if self.best_person is None:
  94. self.best_person = new_best_person
  95. # if there is already a best_person
  96. else:
  97. now = datetime.datetime.now().timestamp()
  98. # if the new best person is a higher score than the current best person
  99. # or the current person is more than 1 minute old, use the new best person
  100. if new_best_person['score'] > self.best_person['score'] or (now - self.best_person['frame_time']) > 60:
  101. self.best_person = new_best_person
  102. if not self.best_person is None and self.best_person['frame_time'] in recent_frames:
  103. best_frame = recent_frames[self.best_person['frame_time']]
  104. best_frame = cv2.cvtColor(best_frame, cv2.COLOR_BGR2RGB)
  105. # draw the bounding box on the frame
  106. vis_util.draw_bounding_box_on_image_array(best_frame,
  107. self.best_person['ymin'],
  108. self.best_person['xmin'],
  109. self.best_person['ymax'],
  110. self.best_person['xmax'],
  111. color='red',
  112. thickness=2,
  113. display_str_list=["{}: {}%".format(self.best_person['name'],int(self.best_person['score']*100))],
  114. use_normalized_coordinates=False)
  115. # convert back to BGR
  116. self.best_frame = cv2.cvtColor(best_frame, cv2.COLOR_RGB2BGR)
  117. motion_end = datetime.datetime.now().timestamp()
  118. # wait for the global motion flag to change
  119. with self.motion_changed:
  120. self.motion_changed.wait()
  121. motion_start = datetime.datetime.now().timestamp()