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