From a5de091af8de711c96957e6b759c1d57c9226160 Mon Sep 17 00:00:00 2001 From: Olegs NIKISINS <onikisins@italix03.idiap.ch> Date: Wed, 12 Jul 2017 13:43:53 +0200 Subject: [PATCH] Updated VideoFaceCrop preprocessor to deal with missing and excess annotations of MSU MFSD --- bob/pad/face/preprocessor/VideoFaceCrop.py | 62 ++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/bob/pad/face/preprocessor/VideoFaceCrop.py b/bob/pad/face/preprocessor/VideoFaceCrop.py index 85c559e2..fd975676 100644 --- a/bob/pad/face/preprocessor/VideoFaceCrop.py +++ b/bob/pad/face/preprocessor/VideoFaceCrop.py @@ -159,6 +159,12 @@ class VideoFaceCrop(Preprocessor, object): ``min_face_size`` : :py:class:`int` The minimal size of the face in pixels. + + **Returns:** + + ``cleaned_frame_container`` : FrameContainer + FrameContainer containing the frames with faces of the size + overcoming the specified threshold. """ cleaned_frame_container = bob.bio.video.FrameContainer() # initialize the FrameContainer @@ -183,6 +189,57 @@ class VideoFaceCrop(Preprocessor, object): return cleaned_frame_container + #========================================================================== + def select_annotated_frames(self, frames, annotations): + """ + Select only annotated frames in the input FrameContainer ``frames``. + + **Parameters:** + + ``frames`` : FrameContainer + Video data stored in the FrameContainer, see ``bob.bio.video.utils.FrameContainer`` + for further details. + + ``annotations`` : :py:class:`dict` + A dictionary containing the annotations for each frame in the video. + Dictionary structure: ``annotations = {'1': frame1_dict, '2': frame1_dict, ...}``. + Where ``frameN_dict = {'topleft': (row, col), 'bottomright': (row, col)}`` + is the dictionary defining the coordinates of the face bounding box in frame N. + + **Returns:** + + ``cleaned_frame_container`` : FrameContainer + FrameContainer containing the annotated frames only. + + ``cleaned_annotations`` : :py:class:`dict` + A dictionary containing the annotations for each frame in the output video. + Dictionary structure: ``annotations = {'1': frame1_dict, '2': frame1_dict, ...}``. + Where ``frameN_dict = {'topleft': (row, col), 'bottomright': (row, col)}`` + is the dictionary defining the coordinates of the face bounding box in frame N. + """ + + annotated_frames = np.sort( [np.int(item) for item in annotations.keys()] ) # annotated frame numbers + + available_frames = range(0,len(frames)) # frame numbers in the input video + + valid_frames = list(set(annotated_frames).intersection(available_frames)) # valid and annotated frames + + cleaned_frame_container = bob.bio.video.FrameContainer() # initialize the FrameContainer + + cleaned_annotations = {} + + for idx, valid_frame_num in enumerate(valid_frames): + ## valid_frame_num - is the number of the original frame having annotations + + cleaned_annotations[str(idx)] = annotations[str(valid_frame_num)] # correct the frame numbers + + selected_frame = frames[valid_frame_num][1] # get current frame + + cleaned_frame_container.add(idx, selected_frame) # add current frame to FrameContainer + + return cleaned_frame_container, cleaned_annotations + + #========================================================================== def __call__(self, frames, annotations): """ @@ -206,6 +263,11 @@ class VideoFaceCrop(Preprocessor, object): Cropped faces stored in the FrameContainer. """ + if len(frames) != len(annotations): # if some annotations are missing + + ## Select only annotated frames: + frames, annotations = self.select_annotated_frames(frames, annotations) + preprocessed_video = self.video_preprocessor(frames = frames, annotations = annotations) if self.check_face_size_flag: -- GitLab