Source code for bob.pad.face.database.database

from functools import partial
import os
from bob.pad.base.database import PadFile
import bob.bio.video
import bob.io.video
from bob.db.base.annotations import read_annotation_file
from sklearn.preprocessing import FunctionTransformer
from bob.bio.video import VideoAsArray
from bob.pipelines import DelayedSample


def delayed_video_load(
    samples,
    original_directory,
    annotation_directory=None,
    selection_style=None,
    max_number_of_frames=None,
    step_size=None,
    get_transform=None,
    keep_extension_for_annotation=False,
):
    if get_transform is None:
        def get_transform(x):
            return None

    original_directory = original_directory or ""
    annotation_directory = annotation_directory or ""
    results = []
    for sample in samples:
        video_path = os.path.join(original_directory, sample.filename)
        data = partial(
            VideoAsArray,
            path=video_path,
            selection_style=selection_style,
            max_number_of_frames=max_number_of_frames,
            step_size=step_size,
            transform=get_transform(sample),
        )
        annotations, delayed_attributes = None, None
        if annotation_directory:
            path = sample.filename
            if not keep_extension_for_annotation:
                path = os.path.splitext(sample.filename)[0]
            delayed_annotations = partial(
                read_annotation_file,
                file_name=f"{annotation_directory}:{path}.json",
                annotation_type="json",
            )
            delayed_attributes = {"annotations": delayed_annotations}

        results.append(
            DelayedSample(
                data,
                parent=sample,
                delayed_attributes=delayed_attributes,
                annotations=annotations,
            )
        )
    return results


def VideoPadSample(
    original_directory,
    annotation_directory=None,
    selection_style=None,
    max_number_of_frames=None,
    step_size=None,
    get_transform=None,
    keep_extension_for_annotation=False,
):
    return FunctionTransformer(
        delayed_video_load,
        validate=False,
        kw_args=dict(
            original_directory=original_directory,
            annotation_directory=annotation_directory,
            selection_style=selection_style,
            max_number_of_frames=max_number_of_frames,
            step_size=step_size,
            get_transform=get_transform,
            keep_extension_for_annotation=keep_extension_for_annotation,
        ),
    )


class VideoPadFile(PadFile):
    """A simple base class that defines basic properties of File object for the
    use in face PAD experiments.
    """

    def __init__(
        self,
        attack_type,
        client_id,
        path,
        file_id=None,
        original_directory=None,
        original_extension=".avi",
        annotation_directory=None,
        annotation_extension=None,
        annotation_type=None,
        selection_style=None,
        max_number_of_frames=None,
        step_size=None,
    ):
        super().__init__(
            attack_type=attack_type,
            client_id=client_id,
            path=path,
            file_id=file_id,
            original_directory=original_directory,
            original_extension=original_extension,
            annotation_directory=annotation_directory,
            annotation_extension=annotation_extension,
            annotation_type=annotation_type,
        )
        self.selection_style = selection_style or "all"
        self.max_number_of_frames = max_number_of_frames
        self.step_size = step_size

[docs] def load( self, ): """Loads the video file and returns in a `bob.bio.video.FrameContainer`. Returns ------- :any:`bob.bio.video.VideoAsArray` The loaded frames inside a frame container. """ path = self.make_path(self.original_directory, self.original_extension) video = bob.bio.video.VideoAsArray( path, selection_style=self.selection_style, max_number_of_frames=self.max_number_of_frames, step_size=self.step_size, ) return video
@property def frames(self): """Returns an iterator of frames in the video. If your database video files need to be loaded in a special way, you need to override this property. Returns ------- collections.abc.Iterator An iterator returning frames of the video. """ path = self.make_path( directory=self.original_directory, extension=self.original_extension ) return iter(bob.io.video.reader(path)) @property def number_of_frames(self): path = self.make_path( directory=self.original_directory, extension=self.original_extension ) return bob.io.video.reader(path).number_of_frames @property def frame_shape(self): """Returns the size of each frame in this database. This implementation assumes all frames have the same shape. It's best to override this method in your database implementation and return a constant. Returns ------- (int, int, int) The (Channels, Height, Width) sizes. """ path = self.make_path( directory=self.original_directory, extension=self.original_extension ) frame = next(bob.io.video.reader(path)) return frame.shape @property def annotations(self): """Reads the annotations For this property to work, you need to set ``annotation_directory``, ``annotation_extension``, and ``annotation_type`` attributes of the files when database's object method is called. Returns ------- dict The annotations as a dictionary. """ if self.annotation_directory is None: return None annotation_file = self.make_path( directory=self.annotation_directory, extension=self.annotation_extension ) return read_annotation_file(annotation_file, self.annotation_type)