Source code for annotations.FaceDetection.videofacedetect

# -*- coding : UTF-8 -*-
"""
:filename: sppas.src.annotations.FaceDetection.videofacedetect.py
:author:   Brigitte Bigi
:contact:  develop@sppas.org
:summary:  Automatic detection of faces in a video.

.. _This file is part of SPPAS: http://www.sppas.org/
..
    ---------------------------------------------------------------------

     ___   __    __    __    ___
    /     |  \  |  \  |  \  /              the automatic
    \__   |__/  |__/  |___| \__             annotation and
       \  |     |     |   |    \             analysis
    ___/  |     |     |   | ___/              of speech

    Copyright (C) 2011-2021  Brigitte Bigi
    Laboratoire Parole et Langage, Aix-en-Provence, France

    Use of this software is governed by the GNU Public License, version 3.

    SPPAS is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    SPPAS is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with SPPAS. If not, see <http://www.gnu.org/licenses/>.

    This banner notice must not be removed.

    ---------------------------------------------------------------------

"""

import logging

from sppas.src.config import sppasError
from sppas.src.videodata import sppasCoordsVideoBuffer

from .imgfacedetect import ImageFaceDetection

# ---------------------------------------------------------------------------


[docs]class VideoFaceDetection(object): """Search for faces on all images of a video. """
[docs] def __init__(self, face_detection): """Create a new instance. :param face_detection: (ImageFaceDetection) FD image system """ # The face detection system if isinstance(face_detection, ImageFaceDetection) is False: raise sppasError("A face detection system was expected.") self._video_buffer = sppasCoordsVideoBuffer() # Configure the face detection system self.__fd = face_detection self.__confidence = face_detection.get_min_score() self.__nbest = 0 self.__portrait = True
# -----------------------------------------------------------------------
[docs] def get_filter_confidence(self): """Return the min scores of faces to detect.""" return self.__confidence
# -----------------------------------------------------------------------
[docs] def set_filter_confidence(self, value=0.2): """Force to detect only the faces with a confidence score > value. It means that any detected face with a score lesser than the given one will be ignored. The score of detected faces are supposed to range between 0. and 1. :param value: (float) Value ranging [0., 1.] :raise: ValueError """ self.__confidence = value
# -----------------------------------------------------------------------
[docs] def get_filter_best(self): """Return the max nb of faces to detect.""" return self.__nbest
# -----------------------------------------------------------------------
[docs] def set_filter_best(self, value=-1): """Force to detect at max the given number of faces. :param value: (int) Number of faces to detect or -1 to not force. """ value = int(value) self.__nbest = value
# -----------------------------------------------------------------------
[docs] def set_portrait(self, value=True): """Consider the portrait instead of the face. :param value: (bool) """ self.__portrait = bool(value)
# ----------------------------------------------------------------------- # Automatic detection of the faces in a video # -----------------------------------------------------------------------
[docs] def video_face_detect(self, video, video_writer=None, output=None): """Browse the video, detect faces and write results. :param video: (str) Video filename :param video_writer: () :param output: (str) The output name for the folder and/or the video :return: (list) The coordinates of all detected faces on all images """ # Browse the video using the buffer of images result = list() read_next = True nb = 0 # Open the video stream self._video_buffer.open(video) self._video_buffer.seek_buffer(0) video_writer.set_fps(self._video_buffer.get_framerate()) while read_next is True: # fill-in the buffer with 'size'-images of the video read_next = self._video_buffer.next() nb += 1 logging.info("Buffer number {:d}".format(nb)) # face detection on the current images of the buffer self.detect_buffer() # save the current results: file names or list of face coordinates if output is not None and video_writer is not None: new_files = video_writer.write(self._video_buffer, output) result.extend(new_files) else: for i in range(len(self._video_buffer)): faces = self._video_buffer.get_coordinates(i) result.append(faces) # Release the video stream self._video_buffer.close() self._video_buffer.reset() return result
# ----------------------------------------------------------------------- # Work on a buffer... # -----------------------------------------------------------------------
[docs] def detect_buffer(self): """Search for faces in the currently loaded buffer of the video. Determine the coordinates of all the detected faces of all images. They are ranked from the highest score to the lowest one. :raise: sppasError if no model was loaded. """ # No buffer is in-use. if len(self._video_buffer) == 0: logging.warning("Nothing to detect: no images in the buffer.") return # The detection system isn't ready if self.__fd.get_nb_recognizers() == 0: raise sppasError("A face detector must be initialized first.") # Find the coordinates of faces in each image. for i, image in enumerate(self._video_buffer): # Perform face detection to detect all faces in the current image self.__fd.detect(image) # Apply filters to keep the better ones if self.__nbest != 0: self.__fd.filter_best(self.__nbest) self.__fd.filter_confidence(self.__confidence) # Resize the detected face to the portrait if self.__portrait is True: self.__fd.to_portrait(image) # Save results into the list of coordinates of such image coords = [c.copy() for c in self.__fd] self._video_buffer.set_coordinates(i, coords) self.__fd.invalidate()