Skip to content
Snippets Groups Projects
Commit 8fc2c962 authored by Guillaume HEUSCH's avatar Guillaume HEUSCH
Browse files

[extractor] added FFT features, modified Freq Features (Li), added LTSS features

parent 594e57d4
No related branches found
No related tags found
1 merge request!53WIP: rPPG as features for PAD
Pipeline #
......@@ -26,12 +26,13 @@ class FFTFeatures(Extractor, object):
debug: boolean
Plot stuff
"""
def __init__(self, framerate=25, nfft=256, debug=False, **kwargs):
def __init__(self, framerate=25, nfft=256, concat=False, debug=False, **kwargs):
super(FFTFeatures, self).__init__(**kwargs)
self.framerate = framerate
self.nfft = nfft
self.concat = concat
self.debug = debug
......@@ -72,7 +73,11 @@ class FFTFeatures(Extractor, object):
ffts = numpy.zeros((3, output_dim))
for i in range(3):
ffts[i] = abs(numpy.fft.rfft(signal[:, i], n=self.nfft))
fft = ffts[1]
if self.concat:
fft = numpy.concatenate([ffts[0], ffts[1], ffts[2]])
else:
fft = ffts[1]
if self.debug:
from matplotlib import pyplot
......
......@@ -8,7 +8,6 @@ from bob.bio.base.extractor import Extractor
import logging
logger = logging.getLogger("bob.pad.face")
from scipy.signal import welch
class FreqFeatures(Extractor, object):
......
#!/usr/bin/env python
# encoding: utf-8
import numpy
from bob.bio.base.extractor import Extractor
import logging
logger = logging.getLogger("bob.pad.face")
from scipy.fftpack import rfft
class LTSS(Extractor, object):
"""
Compute Long-term spectral statistics of a pulse signal.
The features are described in the following article:
@Article {
Author = {Muckenhirn, Hannah and Korshunov, Pavel and
Magimai-Doss, Mathew and Marcel, Sebastien }
Title = {Long-Term Spectral Statistics for Voice Presentation
Attack Detection},
Journal = {IEEE/ACM Trans. Audio, Speech and Lang. Proc.},
Volume = {25},
Number = {11},
Pages = {2098--2111},
year = 2017
}
**Parameters:**
framerate: int
The sampling frequency of the signal (i.e the framerate ...)
nfft: int
Number of points to compute the FFT
debug: boolean
Plot stuff
"""
def __init__(self, window_size=25, framerate=25, nfft=64, concat=False, debug=False, **kwargs):
super(LTSS, self).__init__()
self.framerate = framerate
self.nfft = nfft
self.debug = debug
self.window_size = window_size
self.concat = concat
def _get_ltss(self, signal):
# log-magnitude of DFT coefficients
log_mags = []
window_stride = int(self.window_size / 2)
# go through windows
for w in range(0, (signal.shape[0] - self.window_size), window_stride):
fft = rfft(signal[w:w+self.window_size], n=self.nfft)
mags = numpy.zeros(int(self.nfft/2), dtype=numpy.float64)
mags[0] = abs(fft[0])
index = 1
for i in range(1, (fft.shape[0]-1), 2):
mags[index] = numpy.sqrt(fft[i]**2 + fft[i+1]**2)
if mags[index] < 1:
mags[index] = 1
index += 1
log_mags.append(numpy.log(mags))
# get the long term statistics
log_mags = numpy.array(log_mags)
mean = numpy.mean(log_mags, axis=0)
std = numpy.std(log_mags, axis=0)
ltss = numpy.concatenate([mean, std])
return ltss
def __call__(self, signal):
"""
Computes the long-term spectral statistics for a given signal.
**Parameters**
signal: numpy.array
The signal
**Returns:**
feature: numpy.array
the long-term spectral statistics feature vector
"""
# sanity check
if signal.ndim == 1:
if numpy.isnan(numpy.sum(signal)):
return
if signal.ndim == 2 and (signal.shape[1] == 3):
for i in range(signal.shape[1]):
if numpy.isnan(numpy.sum(signal[:, i])):
return
if signal.ndim == 1:
feature = self._get_ltss(signal)
if signal.ndim == 2 and (signal.shape[1] == 3):
if not self.concat:
feature = self._get_ltss(signal[:, 1])
else:
ltss = []
for i in range(signal.shape[1]):
ltss.append(self._get_ltss(signal[:, i]))
feature = numpy.concatenate([ltss[0], ltss[1], ltss[2]])
if numpy.isnan(numpy.sum(feature)):
logger.warn("Feature not extracted")
return
if numpy.sum(feature) == 0:
logger.warn("Feature not extracted")
return
return feature
......@@ -9,6 +9,8 @@ from .FrequencySpectrum import FrequencySpectrum
from .FreqFeatures import FreqFeatures
from .NormalizeLength import NormalizeLength
from .FFTFeatures import FFTFeatures
from .LTSS import LTSS
from .Autocorrelation import Autocorrelation
def __appropriate__(*args):
"""Says object was actually declared here, and not in the import module.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment