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): ...@@ -26,12 +26,13 @@ class FFTFeatures(Extractor, object):
debug: boolean debug: boolean
Plot stuff 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) super(FFTFeatures, self).__init__(**kwargs)
self.framerate = framerate self.framerate = framerate
self.nfft = nfft self.nfft = nfft
self.concat = concat
self.debug = debug self.debug = debug
...@@ -72,7 +73,11 @@ class FFTFeatures(Extractor, object): ...@@ -72,7 +73,11 @@ class FFTFeatures(Extractor, object):
ffts = numpy.zeros((3, output_dim)) ffts = numpy.zeros((3, output_dim))
for i in range(3): for i in range(3):
ffts[i] = abs(numpy.fft.rfft(signal[:, i], n=self.nfft)) 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: if self.debug:
from matplotlib import pyplot from matplotlib import pyplot
......
...@@ -8,7 +8,6 @@ from bob.bio.base.extractor import Extractor ...@@ -8,7 +8,6 @@ from bob.bio.base.extractor import Extractor
import logging import logging
logger = logging.getLogger("bob.pad.face") logger = logging.getLogger("bob.pad.face")
from scipy.signal import welch
class FreqFeatures(Extractor, object): 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 ...@@ -9,6 +9,8 @@ from .FrequencySpectrum import FrequencySpectrum
from .FreqFeatures import FreqFeatures from .FreqFeatures import FreqFeatures
from .NormalizeLength import NormalizeLength from .NormalizeLength import NormalizeLength
from .FFTFeatures import FFTFeatures from .FFTFeatures import FFTFeatures
from .LTSS import LTSS
from .Autocorrelation import Autocorrelation
def __appropriate__(*args): def __appropriate__(*args):
"""Says object was actually declared here, and not in the import module. """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