Source code for bob.rppg.cvpr14.illum_utils

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

import numpy

[docs]def rectify_illumination(face_color, bg_color, step, length): """performs illumination rectification. The correction is made on the face green values using the background green values, so as to remove global illumination variations in the face green color signal. Parameters ---------- face_color: numpy.ndarray The mean green value of the face across the video sequence. bg_color: numpy.ndarray The mean green value of the background across the video sequence. step: float Step size in the filter's weight adaptation. length: int Length of the filter. Returns ------- rectified color: numpy.ndarray The mean green values of the face, corrected for illumination variations. """ # first pass to find the filter coefficients # - y: filtered signal # - e: error (aka difference between face and background) # - w: filter coefficient(s) yg, eg, wg = nlms(bg_color, face_color, length, step) # second pass to actually filter the signal, using previous weights as initial conditions # the second pass just filters the signal and does NOT update the weights ! yg2, eg2, wg2 = nlms(bg_color, face_color, length, step, initCoeffs=wg, adapt=False) return eg2
[docs]def nlms(signal, desired_signal, n_filter_taps, step, initCoeffs=None, adapt=True): """Normalized least mean square filter. Based on adaptfilt 0.2: https://pypi.python.org/pypi/adaptfilt/0.2 Parameters ---------- signal: numpy.ndarray The signal to be filtered. desired_signal: numpy.ndarray The target signal. n_filter_taps: int The number of filter taps (related to the filter order). step: float Adaptation step for the filter weights. initCoeffs: numpy.ndarray Initial values for the weights. Defaults to zero. adapt: bool If True, adapt the filter weights. If False, only filters. Returns ------- y: numpy.ndarray The filtered signal. e: numpy.ndarray The error signal (difference between filtered and desired) w: numpy.ndarray The found weights of the filter. """ eps = 0.001 number_of_iterations = len(signal) - n_filter_taps + 1 if initCoeffs is None: initCoeffs = numpy.zeros(n_filter_taps) # Initialization y = numpy.zeros(number_of_iterations) # Filter output e = numpy.zeros(number_of_iterations) # Error signal w = initCoeffs # Initial filter coeffs # Perform filtering errors = [] for n in range(number_of_iterations): x = numpy.flipud(signal[n:(n + n_filter_taps)]) # Slice to get view of M latest datapoints y[n] = numpy.dot(x, w) e[n] = desired_signal[n + n_filter_taps - 1] - y[n] errors.append(e[n]) if adapt: normFactor = 1./(numpy.dot(x, x) + eps) w = w + step * normFactor * x * e[n] y[n] = numpy.dot(x, w) return y, e, w