|
--- |
|
license: mit |
|
library_name: py-feat |
|
pipeline_tag: image-feature-extraction |
|
--- |
|
|
|
# svm_au |
|
|
|
## Model Description |
|
svm_au combines histogram of oriented gradient feature extraction with a linear support vector machine to predict facial action units from single frame images. |
|
|
|
## Model Details |
|
- **Model Type**: Support Vector Machine (SVM) |
|
- **Framework**: sklearn |
|
|
|
## Model Sources |
|
- **Repository**: [GitHub Repository](https://github.com/cosanlab/py-feat) |
|
- **Paper**: [Py-feat: Python facial expression analysis toolbox](https://link.springer.com/article/10.1007/s42761-023-00191-4) |
|
|
|
## Citation |
|
If you use the svm_au model in your research or application, please cite the following paper: |
|
|
|
Cheong, J.H., Jolly, E., Xie, T. et al. Py-Feat: Python Facial Expression Analysis Toolbox. Affec Sci 4, 781–796 (2023). https://doi.org/10.1007/s42761-023-00191-4 |
|
|
|
``` |
|
@article{cheong2023py, |
|
title={Py-feat: Python facial expression analysis toolbox}, |
|
author={Cheong, Jin Hyun and Jolly, Eshin and Xie, Tiankang and Byrne, Sophie and Kenney, Matthew and Chang, Luke J}, |
|
journal={Affective Science}, |
|
volume={4}, |
|
number={4}, |
|
pages={781--796}, |
|
year={2023}, |
|
publisher={Springer} |
|
} |
|
``` |
|
|
|
## Example Useage |
|
|
|
```python |
|
import numpy as np |
|
from skops.io import dump, load, get_untrusted_types |
|
from huggingface_hub import hf_hub_download |
|
|
|
class SVMClassifier: |
|
def __init__(self) -> None: |
|
self.weights_loaded = False |
|
|
|
def load_weights(self, scaler_upper=None, pca_model_upper=None, scaler_lower=None, pca_model_lower=None, scaler_full=None, pca_model_full=None, classifiers=None): |
|
self.scaler_upper = scaler_upper |
|
self.pca_model_upper = pca_model_upper |
|
self.scaler_lower = scaler_lower |
|
self.pca_model_lower = pca_model_lower |
|
self.scaler_full = scaler_full |
|
self.pca_model_full = pca_model_full |
|
self.classifiers = classifiers |
|
self.weights_loaded = True |
|
|
|
def pca_transform(self, frame, scaler, pca_model, landmarks): |
|
if not self.weights_loaded: |
|
raise ValueError('Need to load weights before running pca_transform') |
|
else: |
|
transformed_frame = pca_model.transform(scaler.transform(frame)) |
|
return np.concatenate((transformed_frame, landmarks), axis=1) |
|
|
|
def detect_au(self, frame, landmarks): |
|
""" |
|
Note that here frame is represented by hogs |
|
""" |
|
if not self.weights_loaded: |
|
raise ValueError('Need to load weights before running detect_au') |
|
else: |
|
landmarks = np.concatenate(landmarks) |
|
landmarks = landmarks.reshape(-1, landmarks.shape[1] * landmarks.shape[2]) |
|
|
|
pca_transformed_upper = self.pca_transform(frame, self.scaler_upper, self.pca_model_upper, landmarks) |
|
pca_transformed_lower = self.pca_transform(frame, self.scaler_lower, self.pca_model_lower, landmarks) |
|
pca_transformed_full = self.pca_transform(frame, self.scaler_full, self.pca_model_full, landmarks) |
|
|
|
aus_list = sorted(self.classifiers.keys(), key=lambda x: int(x[2::])) |
|
|
|
pred_aus = [] |
|
for keys in aus_list: |
|
if keys in ["AU1", "AU4", "AU6"]: |
|
au_pred = self.classifiers[keys].predict(pca_transformed_upper) |
|
elif keys in ["AU11", "AU12", "AU17"]: |
|
au_pred = self.classifiers[keys].predict(pca_transformed_lower) |
|
elif keys in [ |
|
"AU2", |
|
"AU5", |
|
"AU7", |
|
"AU9", |
|
"AU10", |
|
"AU14", |
|
"AU15", |
|
"AU20", |
|
"AU23", |
|
"AU24", |
|
"AU25", |
|
"AU26", |
|
"AU28", |
|
"AU43", |
|
]: |
|
au_pred = self.classifiers[keys].predict(pca_transformed_full) |
|
else: |
|
raise ValueError("unknown AU detected") |
|
|
|
pred_aus.append(au_pred) |
|
pred_aus = np.array(pred_aus).T |
|
return pred_aus |
|
|
|
# Load model and weights |
|
au_model = SVMClassifier() |
|
model_path = hf_hub_download(repo_id="py-feat/svm_au", filename="svm_au_classifier.skops") |
|
unknown_types = get_untrusted_types(file=model_path) |
|
loaded_model = load(model_path, trusted=unknown_types) |
|
au_model.load_weights(scaler_upper = loaded_model.scaler_upper, |
|
pca_model_upper = loaded_model.pca_model_upper, |
|
scaler_lower = loaded_model.scaler_lower, |
|
pca_model_lower = loaded_model.scaler_full, |
|
pca_model_full=loaded_model.pca_model_full, |
|
classifiers=loaded_model.classifiers) |
|
|
|
# Test model |
|
frame = "path/to/your/test_image.jpg" # Replace with your loaded image |
|
landmarks = np.array([...]) # Replace with your landmarks data |
|
pred = au_model.detect_au(frame, landmarks) |
|
print(pred) |
|
|
|
``` |
|
|
|
|
|
|