mirror of
https://github.com/blakeblackshear/frigate.git
synced 2024-11-26 19:06:11 +01:00
maintain thumbnail frames for tracked objects
This commit is contained in:
parent
8b8f5b5c40
commit
24b703a875
@ -52,6 +52,34 @@ def zone_filtered(obj, object_config):
|
|||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def on_edge(box, frame_shape):
|
||||||
|
if (
|
||||||
|
box[0] == 0 or
|
||||||
|
box[1] == 0 or
|
||||||
|
box[2] == frame_shape[1]-1 or
|
||||||
|
box[3] == frame_shape[0]-1
|
||||||
|
):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def is_better_thumbnail(current_thumb, new_obj, frame_shape) -> bool:
|
||||||
|
# larger is better
|
||||||
|
# cutoff images are less ideal, but they should also be smaller?
|
||||||
|
# better scores are obviously better too
|
||||||
|
|
||||||
|
# if the new_thumb is on an edge, and the current thumb is not
|
||||||
|
if on_edge(new_obj['box'], frame_shape) and not on_edge(current_thumb['box'], frame_shape):
|
||||||
|
return False
|
||||||
|
|
||||||
|
# if the score is better by more than 5%
|
||||||
|
if new_obj['score'] > current_thumb['score']+.05:
|
||||||
|
return True
|
||||||
|
|
||||||
|
# if the area is 10% larger
|
||||||
|
if new_obj['area'] > current_thumb['area']*1.1:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
# Maintains the state of a camera
|
# Maintains the state of a camera
|
||||||
class CameraState():
|
class CameraState():
|
||||||
def __init__(self, name, config, frame_manager):
|
def __init__(self, name, config, frame_manager):
|
||||||
@ -62,6 +90,7 @@ class CameraState():
|
|||||||
self.best_objects = {}
|
self.best_objects = {}
|
||||||
self.object_status = defaultdict(lambda: 'OFF')
|
self.object_status = defaultdict(lambda: 'OFF')
|
||||||
self.tracked_objects = {}
|
self.tracked_objects = {}
|
||||||
|
self.thumbnail_frames = {}
|
||||||
self.zone_objects = defaultdict(lambda: [])
|
self.zone_objects = defaultdict(lambda: [])
|
||||||
self._current_frame = np.zeros(self.config.frame_shape_yuv, np.uint8)
|
self._current_frame = np.zeros(self.config.frame_shape_yuv, np.uint8)
|
||||||
self.current_frame_lock = threading.Lock()
|
self.current_frame_lock = threading.Lock()
|
||||||
@ -138,44 +167,63 @@ class CameraState():
|
|||||||
updated_ids = list(set(current_ids).intersection(previous_ids))
|
updated_ids = list(set(current_ids).intersection(previous_ids))
|
||||||
|
|
||||||
for id in new_ids:
|
for id in new_ids:
|
||||||
self.tracked_objects[id] = tracked_objects[id]
|
new_obj = self.tracked_objects[id] = tracked_objects[id]
|
||||||
self.tracked_objects[id]['zones'] = []
|
new_obj['zones'] = []
|
||||||
self.tracked_objects[id]['entered_zones'] = set()
|
new_obj['entered_zones'] = set()
|
||||||
|
new_obj['thumbnail'] = {
|
||||||
|
'frame': new_obj['frame_time'],
|
||||||
|
'box': new_obj['box'],
|
||||||
|
'area': new_obj['area'],
|
||||||
|
'region': new_obj['region'],
|
||||||
|
'score': new_obj['score']
|
||||||
|
}
|
||||||
|
|
||||||
# start the score history
|
# start the score history
|
||||||
self.tracked_objects[id]['score_history'] = [self.tracked_objects[id]['score']]
|
new_obj['score_history'] = [self.tracked_objects[id]['score']]
|
||||||
|
|
||||||
# calculate if this is a false positive
|
# calculate if this is a false positive
|
||||||
self.tracked_objects[id]['computed_score'] = self.compute_score(self.tracked_objects[id])
|
new_obj['computed_score'] = self.compute_score(self.tracked_objects[id])
|
||||||
self.tracked_objects[id]['top_score'] = self.tracked_objects[id]['computed_score']
|
new_obj['top_score'] = self.tracked_objects[id]['computed_score']
|
||||||
self.tracked_objects[id]['false_positive'] = self.false_positive(self.tracked_objects[id])
|
new_obj['false_positive'] = self.false_positive(self.tracked_objects[id])
|
||||||
|
|
||||||
# call event handlers
|
# call event handlers
|
||||||
for c in self.callbacks['start']:
|
for c in self.callbacks['start']:
|
||||||
c(self.name, tracked_objects[id])
|
c(self.name, new_obj)
|
||||||
|
|
||||||
for id in updated_ids:
|
for id in updated_ids:
|
||||||
self.tracked_objects[id].update(tracked_objects[id])
|
self.tracked_objects[id].update(tracked_objects[id])
|
||||||
|
|
||||||
|
updated_obj = self.tracked_objects[id]
|
||||||
|
|
||||||
# if the object is not in the current frame, add a 0.0 to the score history
|
# if the object is not in the current frame, add a 0.0 to the score history
|
||||||
if self.tracked_objects[id]['frame_time'] != self.current_frame_time:
|
if updated_obj['frame_time'] != self.current_frame_time:
|
||||||
self.tracked_objects[id]['score_history'].append(0.0)
|
updated_obj['score_history'].append(0.0)
|
||||||
else:
|
else:
|
||||||
self.tracked_objects[id]['score_history'].append(self.tracked_objects[id]['score'])
|
updated_obj['score_history'].append(updated_obj['score'])
|
||||||
# only keep the last 10 scores
|
# only keep the last 10 scores
|
||||||
if len(self.tracked_objects[id]['score_history']) > 10:
|
if len(updated_obj['score_history']) > 10:
|
||||||
self.tracked_objects[id]['score_history'] = self.tracked_objects[id]['score_history'][-10:]
|
updated_obj['score_history'] = updated_obj['score_history'][-10:]
|
||||||
|
|
||||||
# calculate if this is a false positive
|
# calculate if this is a false positive
|
||||||
computed_score = self.compute_score(self.tracked_objects[id])
|
computed_score = self.compute_score(updated_obj)
|
||||||
self.tracked_objects[id]['computed_score'] = computed_score
|
updated_obj['computed_score'] = computed_score
|
||||||
if computed_score > self.tracked_objects[id]['top_score']:
|
if computed_score > updated_obj['top_score']:
|
||||||
self.tracked_objects[id]['top_score'] = computed_score
|
updated_obj['top_score'] = computed_score
|
||||||
self.tracked_objects[id]['false_positive'] = self.false_positive(self.tracked_objects[id])
|
updated_obj['false_positive'] = self.false_positive(updated_obj)
|
||||||
|
|
||||||
|
# determine if this frame is a better thumbnail
|
||||||
|
if is_better_thumbnail(updated_obj['thumbnail'], updated_obj, self.config.frame_shape):
|
||||||
|
updated_obj['thumbnail'] = {
|
||||||
|
'frame': updated_obj['frame_time'],
|
||||||
|
'box': updated_obj['box'],
|
||||||
|
'area': updated_obj['area'],
|
||||||
|
'region': updated_obj['region'],
|
||||||
|
'score': updated_obj['score']
|
||||||
|
}
|
||||||
|
|
||||||
# call event handlers
|
# call event handlers
|
||||||
for c in self.callbacks['update']:
|
for c in self.callbacks['update']:
|
||||||
c(self.name, self.tracked_objects[id])
|
c(self.name, updated_obj)
|
||||||
|
|
||||||
for id in removed_ids:
|
for id in removed_ids:
|
||||||
# publish events to mqtt
|
# publish events to mqtt
|
||||||
@ -201,6 +249,13 @@ class CameraState():
|
|||||||
|
|
||||||
obj['zones'] = current_zones
|
obj['zones'] = current_zones
|
||||||
|
|
||||||
|
# update frame storage for thumbnails based on thumbnails for all tracked objects
|
||||||
|
current_thumb_frames = set([obj['thumbnail']['frame'] for obj in self.tracked_objects.values()])
|
||||||
|
if self.current_frame_time in current_thumb_frames:
|
||||||
|
self.thumbnail_frames[self.current_frame_time] = np.copy(current_frame)
|
||||||
|
thumb_frames_to_delete = [t for t in self.thumbnail_frames.keys() if not t in current_thumb_frames]
|
||||||
|
for t in thumb_frames_to_delete: del self.thumbnail_frames[t]
|
||||||
|
|
||||||
# maintain best objects
|
# maintain best objects
|
||||||
for obj in self.tracked_objects.values():
|
for obj in self.tracked_objects.values():
|
||||||
object_type = obj['label']
|
object_type = obj['label']
|
||||||
|
Loading…
Reference in New Issue
Block a user