Source code for bob.rppg.ssr.ssr_utils

#!/usr/bin/env python
# encoding: utf-8

# Copyright (c) 2017 Idiap Research Institute, http://www.idiap.ch/
# Written by Guillaume Heusch <guillaume.heusch@idiap.ch>,
# 
# This file is part of bob.rpgg.base.
# 
# bob.rppg.base is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3 as
# published by the Free Software Foundation.
# 
# bob.rppg.base 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 bob.rppg.base. If not, see <http://www.gnu.org/licenses/>.

import numpy
import bob.ip.base
from ..base.utils import crop_face

from bob.ip.skincolorfilter import SkinColorFilter
skin_filter = SkinColorFilter()

[docs]def get_skin_pixels(face_frame, index, skininit, threshold, bounding_boxes=None, skin_frame=None, plot=False): """get_skin_pixels(face_frame, index, facewidth, skininit, threshold, bounding_boxes=None, skin_frame=None, plot=False) -> skin_pixels Get a list of skin colored pixels inside the given frame. **Parameters** ``face_frame`` (numpy array): The frame where the face has to be detected. ``index`` (int): The index of the frame containing the face to be detected. ``skininit`` (boolean): Flag if you want the parameters of the skin model to be re-estimated. ``threshold`` (float [0-1]): The threshold on the skin color probability. ``bounding_boxes`` (list of BoundingBoxes): The face bounding boxes corresponding to the sequence. ``skin_frame`` (numpy array): The frame where the skin pixels have to be retrieved. If not set, face_frame will be used. ``plot`` (boolean): Flag to plot the result of skin pixels detection **Returns** ``skin_pixels`` (numpy array): The RGB values of all detected skin colored pixels """ if skin_frame is None: skin_frame = face_frame if bounding_boxes: bbox = bounding_boxes[index] else: bbox, quality = bob.ip.facedetect.detect_single_face(face_frame) face = crop_face(skin_frame, bbox, bbox.size[1]) if skininit: skin_filter.estimate_gaussian_parameters(face) skin_mask = skin_filter.get_skin_mask(face, threshold) skin_pixels = face[:, skin_mask] if plot: from matplotlib import pyplot skin_mask_image = numpy.copy(face) skin_mask_image[:, skin_mask] = 255 pyplot.title("skin pixels in frame {0}".format(index)) pyplot.imshow(numpy.rollaxis(numpy.rollaxis(skin_mask_image, 2),2)) pyplot.show() skin_pixels = skin_pixels.astype('float64') / 255.0 return skin_pixels
[docs]def get_eigen(skin_pixels): """get_eigen(skin_pixels) -> eigenvalues, eigenvectors Build the C matrix, get eigenvalues and eigenvectors, sort them. **Parameters** ``skin_pixels`` (numpy array): The RGB values of skin-colored pixels. **Returns** ``eigenvalues`` (numpy array): The eigenvalues of the correlation matrix ``eigenvectors`` (numpy array): The (sorted) eigenvectors of the correlation matrix """ # build the correlation matrix c = numpy.dot(skin_pixels, skin_pixels.T) c /= skin_pixels.shape[1] # get eigenvectors and sort them according to eigenvalues (largest first) evals, evecs = numpy.linalg.eig(c) idx = evals.argsort()[::-1] eigenvalues = evals[idx] eigenvectors = evecs[:,idx] return eigenvalues, eigenvectors
[docs]def plot_eigenvectors(skin_pixels, eigenvectors): """plot_eigenvectors(skin_pixels, eigenvectors, counter) Plots skin pixel cluster and eignevectors in the RGB space. **Parameters** ``skin_pixels`` (numpy array): The RGB values of skin-colored pixels. ``eigenvectors`` (numpy array): The eigenvectors of the correlation matrix. """ origin = numpy.array([0, 0, 0]) import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D fig = plt.figure() ax = fig.add_subplot(111, projection='3d') ax.scatter(skin_pixels[0], skin_pixels[1], skin_pixels[2]) ax.plot([origin[0], eigenvectors[0, 0]], [origin[1], eigenvectors[1, 0]], zs=[origin[2], eigenvectors[2, 0]], color='g') for k in range(1,3,1): ax.plot([origin[0], eigenvectors[k, 0]], [origin[1], eigenvectors[k, 1]], zs=[origin[2], eigenvectors[k, 2]], color='r') plt.show()
[docs]def build_P(counter, temporal_stride, eigenvectors, eigenvalues, plot=False): """build_P(counter, temporal_stride, eigenvectors, eigenvalues, plot=False) -> p Builds P **Parameters** ``counter`` (int): The frame index ``temporal_stride`` (int): The temporal stride to use ``eigenvectors`` (numpy array): The eigenvectors of the c matrix (for all frames up to counter). ``eigenvalues`` (numpy array): The eigenvalues of the c matrix (for all frames up to counter). ``plot`` (boolean): If you want something to be plotted **Returns** ``p`` (numpy array): The p signal to add to the pulse. """ tau = counter - temporal_stride # SR' sr_prime_vec = numpy.zeros((3, temporal_stride), 'float64') c2 = 0 for t in range(tau, counter, 1): # equation 11 sr_prime = numpy.sqrt(eigenvalues[0, t] / eigenvalues[1, tau]) * numpy.dot(eigenvectors[:, 0, t].T, numpy.outer(eigenvectors[:, 1, tau], eigenvectors[:, 1, tau].T)) sr_prime += numpy.sqrt(eigenvalues[0, t] / eigenvalues[2, tau]) * numpy.dot(eigenvectors[:, 0, t].T, numpy.outer(eigenvectors[:, 2, tau], eigenvectors[:, 2, tau].T)) sr_prime_vec[:, c2] = sr_prime c2 += 1 # build p and add it to the final pulse signal (equation 12 and 13) p = sr_prime_vec[0, :] - ((numpy.std(sr_prime_vec[0, :])/numpy.std(sr_prime_vec[1, :])) * sr_prime_vec[1, :]) if plot: import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_subplot(111) ax.plot(range(temporal_stride), sr_prime_vec[0, :], c='b') ax.plot(range(temporal_stride), sr_prime_vec[1, :], c='b') ax.plot(range(temporal_stride), p, c='r') plt.show() return p