From 1d8f20775177c23c0c47a7a811b3227b052d1dee Mon Sep 17 00:00:00 2001 From: Olegs NIKISINS <onikisins@italix03.idiap.ch> Date: Wed, 27 Sep 2017 15:06:29 +0200 Subject: [PATCH] Added entry point for VideoSparseCoding preprocessor amd initial version of VideoHistOfSparseCodes extractor --- .../preprocessor/video_sparse_coding.py | 23 +++ .../face/extractor/VideoHistOfSparseCodes.py | 166 ++++++++++++++++++ bob/pad/face/preprocessor/__init__.py | 3 + setup.py | 3 + 4 files changed, 195 insertions(+) create mode 100644 bob/pad/face/config/preprocessor/video_sparse_coding.py create mode 100644 bob/pad/face/extractor/VideoHistOfSparseCodes.py diff --git a/bob/pad/face/config/preprocessor/video_sparse_coding.py b/bob/pad/face/config/preprocessor/video_sparse_coding.py new file mode 100644 index 00000000..5de78ecf --- /dev/null +++ b/bob/pad/face/config/preprocessor/video_sparse_coding.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python + +from bob.pad.face.preprocessor import VideoSparseCoding + + +#======================================================================================= +# Define instances here: + +BLOCK_SIZE = 5 +BLOCK_LENGTH = 10 +MIN_FACE_SIZE = 50 +NORM_FACE_SIZE = 64 +DICTIONARY_FILE_NAMES = ["/idiap/user/onikisins/Projects/ODIN/Python/scripts/test_scripts/data/dictionary_front.hdf5", + "/idiap/user/onikisins/Projects/ODIN/Python/scripts/test_scripts/data/dictionary_hor.hdf5", + "/idiap/user/onikisins/Projects/ODIN/Python/scripts/test_scripts/data/dictionary_vert.hdf5"] +FRAME_STEP = 10 + +preprocessor = VideoSparseCoding(gblock_size = BLOCK_SIZE, + block_length = BLOCK_LENGTH, + min_face_size = MIN_FACE_SIZE, + norm_face_size = NORM_FACE_SIZE, + dictionary_file_names = DICTIONARY_FILE_NAMES, + frame_step = FRAME_STEP) \ No newline at end of file diff --git a/bob/pad/face/extractor/VideoHistOfSparseCodes.py b/bob/pad/face/extractor/VideoHistOfSparseCodes.py new file mode 100644 index 00000000..61747358 --- /dev/null +++ b/bob/pad/face/extractor/VideoHistOfSparseCodes.py @@ -0,0 +1,166 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- +""" +Created on Wed Sep 27 11:33:45 2017 + +@author: Olegs Nikisins +""" + +#============================================================================== +# Import what is needed here: + +from bob.bio.base.extractor import Extractor + +import numpy as np + +import bob.bio.video + +from bob.pad.face.extractor import ImageQualityMeasure + +#============================================================================== +# Main body: + +class VideoHistOfSparseCodes(Extractor, object): + """ + This class is designed to extract histograms of sparse codes. + + **Parameters:** + + ``method`` : :py:class:`str` + A method to use in the histogram computation. Two options are available: + "mean" and "hist". Default: "mean". + """ + + #========================================================================== + def __init__(self, + method = "mean"): + + super(VideoHistOfSparseCodes, self).__init__(method = method) + + self.method = method + + # extractor to process a single image/frame: + extractor = ImageQualityMeasure() + + # This extractor is used only to write and read the feature vectors. + self.video_extractor = bob.bio.video.extractor.Wrapper(extractor) + + + #========================================================================== + def comp_hist_of_sparse_codes(self, frames, method): + """ + Compute the histograms of sparse codes. + """ + + histograms = [] + + for frame_data in frames: + + frame = frame_data[1] + + if method == "mean": + + frame_codes = np.mean(frame, axis=1) + + if method == "hist": + + frame_codes = np.mean(frame!=0, axis=1) + + for idx, row in enumerate(frame_codes): + + frame_codes[idx,:] = row/np.sum(row) + + hist = frame_codes.flatten() + + histograms.append(hist) + + return histograms + + + #========================================================================== + def convert_sparse_codes_to_frame_container(self, list_of_arrays): + """ + Convert an input list of arrays into Frame Container. + + **Parameters:** + + ``list_of_arrays`` : [:py:class:`numpy.ndarray`] + A list of arrays. + + **Returns:** + + ``frame_container`` : FrameContainer + FrameContainer containing the feature vectors. + """ + + frame_container = bob.bio.video.FrameContainer() # initialize the FrameContainer + + for idx, item in enumerate(list_of_arrays): + + frame_container.add(idx, item) # add frame to FrameContainer + + return frame_container + + + #========================================================================== + def __call__(self, frames): + """ + Extract feature vectors. + + **Parameters:** + + ``frames`` : FrameContainer or string. + Data stored in the FrameContainer, + see ``bob.bio.video.utils.FrameContainer`` for further details. + + **Returns:** + + ``frame_container`` : FrameContainer + Histograms of sparse codes stored in the FrameContainer. + """ + + histograms = self.comp_hist_of_sparse_codes(frames, self.method) + + frame_container = self.convert_sparse_codes_to_frame_container(histograms) + + return frame_container + + + #========================================================================== + def write_feature(self, frames, file_name): + """ + Writes the given data (that has been generated using the __call__ function of this class) to file. + This method overwrites the write_data() method of the Extractor class. + + **Parameters:** + + ``frames`` : + Data returned by the __call__ method of the class. + + ``file_name`` : :py:class:`str` + Name of the file. + """ + + self.video_extractor.write_feature(frames, file_name) + + + #========================================================================== + def read_feature(self, file_name): + """ + Reads the preprocessed data from file. + This method overwrites the read_data() method of the Extractor class. + + **Parameters:** + + ``file_name`` : :py:class:`str` + Name of the file. + + **Returns:** + + ``frames`` : :py:class:`bob.bio.video.FrameContainer` + Frames stored in the frame container. + """ + + frames = self.video_extractor.read_feature(file_name) + + return frames diff --git a/bob/pad/face/preprocessor/__init__.py b/bob/pad/face/preprocessor/__init__.py index c9c5a422..dc5b3685 100644 --- a/bob/pad/face/preprocessor/__init__.py +++ b/bob/pad/face/preprocessor/__init__.py @@ -1,6 +1,7 @@ from .VideoFaceCrop import VideoFaceCrop from .ImageFaceCrop import ImageFaceCrop from .FrameDifference import FrameDifference +from .VideoSparseCoding import VideoSparseCoding def __appropriate__(*args): @@ -25,5 +26,7 @@ __appropriate__( VideoFaceCrop, ImageFaceCrop, FrameDifference, + VideoSparseCoding, ) __all__ = [_ for _ in dir() if not _.startswith('_')] + diff --git a/setup.py b/setup.py index 7ca82566..aea2d186 100644 --- a/setup.py +++ b/setup.py @@ -103,6 +103,9 @@ setup( # registered preprocessors: 'bob.pad.preprocessor': [ 'empty-preprocessor = bob.pad.face.config.preprocessor.filename:empty_preprocessor', # no preprocessing + + # The sparse coding based preprocessors + 'sparse-coding-preprocessor = bob.pad.face.config.preprocessor.video_sparse_coding:preprocessor', ], # registered preprocessors: -- GitLab