Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 57 additions & 6 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ jobs:
run: |
pytest --disable-warnings tests/test_module_loading.py

gtests:
gtests-onnx:
runs-on: ubuntu-latest
strategy:
matrix:
Expand All @@ -98,17 +98,14 @@ jobs:
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install -r requirements-engagement.txt
pip install -r requirements-torch.txt
pip install -r tests/requirements.txt

- name: Set PYTHONPATH environment variable
run: echo "PYTHONPATH=$(pwd)" >> $GITHUB_ENV

- name: Download and unpack LibTorch and ONNXRuntime
- name: Download and unpack ONNXRuntime
run: |
wget https://download.pytorch.org/libtorch/cpu/libtorch-cxx11-abi-shared-with-deps-2.6.0%2Bcpu.zip -O libtorch.zip
wget https://github.com/microsoft/onnxruntime/releases/download/v1.20.1/onnxruntime-linux-x64-1.20.1.tgz -O onnxruntime.tgz
unzip libtorch.zip
mkdir onnxruntime
tar -xzf onnxruntime.tgz -C onnxruntime --strip-components=1
# Workaround for Linux build in CI
Expand All @@ -124,7 +121,61 @@ jobs:
- name: Build EmotiEffCppLib
run: |
mkdir build
cmake -S emotieffcpplib -B build -DWITH_TORCH="$PWD/libtorch" -DWITH_ONNX="$PWD/onnxruntime" -DBUILD_TESTS=ON
cmake -S emotieffcpplib -B build -DWITH_ONNX="$PWD/onnxruntime" -DBUILD_TESTS=ON
cmake --build build --config Release -- -j$(nproc)

- name: Prepare torch models
run: python3 models/prepare_models_for_emotieffcpplib.py

- name: Run GTests
run: |
EMOTIEFFLIB_ROOT=$PWD ./build/bin/unit_tests

gtests-torch:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10"]
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
submodules: true
fetch-depth: 1 # shallow clone

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
sudo apt-get update && sudo apt-get install -y cmake g++ make wget libopencv-dev python3
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install -r requirements-engagement.txt
pip install -r requirements-torch.txt
pip install -r tests/requirements.txt

- name: Set PYTHONPATH environment variable
run: echo "PYTHONPATH=$(pwd)" >> $GITHUB_ENV

- name: Download and unpack LibTorch
run: |
wget https://download.pytorch.org/libtorch/cpu/libtorch-cxx11-abi-shared-with-deps-2.6.0%2Bcpu.zip -O libtorch.zip
unzip libtorch.zip

- name: Download and unpack test data
run: |
cd tests/
./download_test_data.sh
tar -xzf data.tar.gz
cd ..

- name: Build EmotiEffCppLib
run: |
mkdir build
cmake -S emotieffcpplib -B build -DWITH_TORCH="$PWD/libtorch" -DBUILD_TESTS=ON
cmake --build build --config Release -- -j$(nproc)

- name: Prepare torch models
Expand Down
8 changes: 4 additions & 4 deletions docs/tutorials/cpp/One image emotion recognition.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,10 @@
"#include <emotiefflib/facial_analysis.h>\n",
"#include <mtcnn/detector.h>\n",
"\n",
"#include <xtensor/xarray.hpp>\n",
"#include <xtensor/xio.hpp>\n",
"#include <xtensor/xmath.hpp>\n",
"#include <xtensor/xsort.hpp>\n",
"#include <xtensor/containers/xarray.hpp>\n",
"#include <xtensor/io/xio.hpp>\n",
"#include <xtensor/core/xmath.hpp>\n",
"#include <xtensor/misc/xsort.hpp>\n",
"\n",
"#include \"xtl/xbase64.hpp\"\n",
"#include \"nlohmann/json.hpp\""
Expand Down
8 changes: 4 additions & 4 deletions docs/tutorials/cpp/Predict emotions on video.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,10 @@
"#include <emotiefflib/facial_analysis.h>\n",
"#include <mtcnn/detector.h>\n",
"\n",
"#include <xtensor/xarray.hpp>\n",
"#include <xtensor/xio.hpp>\n",
"#include <xtensor/xmath.hpp>\n",
"#include <xtensor/xsort.hpp>\n",
"#include <xtensor/containers/xarray.hpp>\n",
"#include <xtensor/io/xio.hpp>\n",
"#include <xtensor/core/xmath.hpp>\n",
"#include <xtensor/misc/xsort.hpp>\n",
"\n",
"#include \"xtl/xbase64.hpp\"\n",
"#include \"nlohmann/json.hpp\""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,10 @@
"#include <emotiefflib/facial_analysis.h>\n",
"#include <mtcnn/detector.h>\n",
"\n",
"#include <xtensor/xarray.hpp>\n",
"#include <xtensor/xio.hpp>\n",
"#include <xtensor/xmath.hpp>\n",
"#include <xtensor/xsort.hpp>\n",
"#include <xtensor/containers/xarray.hpp>\n",
"#include <xtensor/io/xio.hpp>\n",
"#include <xtensor/core/xmath.hpp>\n",
"#include <xtensor/misc/xsort.hpp>\n",
"\n",
"#include \"xtl/xbase64.hpp\"\n",
"#include \"nlohmann/json.hpp\""
Expand Down
2 changes: 1 addition & 1 deletion emotieffcpplib/3rdparty/xtensor
Submodule xtensor updated 262 files
2 changes: 1 addition & 1 deletion emotieffcpplib/include/emotiefflib/facial_analysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#include <opencv2/opencv.hpp>
#include <string>
#include <vector>
#include <xtensor/xarray.hpp>
#include <xtensor/containers/xarray.hpp>

namespace EmotiEffLib {

Expand Down
6 changes: 3 additions & 3 deletions emotieffcpplib/src/backends/onnx/facial_analysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@

#include "emotiefflib/backends/onnx/facial_analysis.h"

#include <xtensor/xadapt.hpp>
#include <xtensor/xio.hpp>
#include <xtensor/xview.hpp>
#include <xtensor/containers/xadapt.hpp>
#include <xtensor/io/xio.hpp>
#include <xtensor/views/xview.hpp>

namespace {
/**
Expand Down
2 changes: 1 addition & 1 deletion emotieffcpplib/src/backends/torch/facial_analysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

#include "emotiefflib/backends/torch/facial_analysis.h"

#include <xtensor/xadapt.hpp>
#include <xtensor/containers/xadapt.hpp>

namespace {
/**
Expand Down
20 changes: 17 additions & 3 deletions emotieffcpplib/src/facial_analysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,18 @@
*/

#include "emotiefflib/facial_analysis.h"
#ifdef WITH_ONNX
#include "emotiefflib/backends/onnx/facial_analysis.h"
#endif
#ifdef WITH_TORCH
#include "emotiefflib/backends/torch/facial_analysis.h"
#endif

#include <filesystem>

#include <xtensor/xmath.hpp>
#include <xtensor/xsort.hpp>
#include <xtensor/xview.hpp>
#include <xtensor/core/xmath.hpp>
#include <xtensor/misc/xsort.hpp>
#include <xtensor/views/xview.hpp>

namespace fs = std::filesystem;

Expand Down Expand Up @@ -41,17 +45,27 @@ std::unique_ptr<EmotiEffLibRecognizer>
EmotiEffLibRecognizer::createInstance(const std::string& backend,
const std::string& fullPipelineModelPath) {
checkBackend(backend);
#ifdef WITH_TORCH
if (backend == "torch")
return std::make_unique<EmotiEffLibRecognizerTorch>(fullPipelineModelPath);
#elif defined(WITH_ONNX)
return std::make_unique<EmotiEffLibRecognizerOnnx>(fullPipelineModelPath);
#else
throw std::runtime_error("EmotiEffCppLib wasn't compiled with any backend support.");
#endif
}

std::unique_ptr<EmotiEffLibRecognizer>
EmotiEffLibRecognizer::createInstance(const EmotiEffLibConfig& config) {
checkBackend(config.backend);
#ifdef WITH_TORCH
if (config.backend == "torch")
return std::make_unique<EmotiEffLibRecognizerTorch>(config);
#elif defined(WITH_ONNX)
return std::make_unique<EmotiEffLibRecognizerOnnx>(config);
#else
throw std::runtime_error("EmotiEffCppLib wasn't compiled with any backend support.");
#endif
}

xt::xarray<float> EmotiEffLibRecognizer::extractFeatures(const std::vector<cv::Mat>& faceImgs) {
Expand Down
65 changes: 43 additions & 22 deletions emotieffcpplib/tests/tests_facial_analisys.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
#include <gtest/gtest.h>
#include <string>

#include <xtensor/xarray.hpp>
#include <xtensor/xio.hpp>
#include <xtensor/xmath.hpp>
#include <xtensor/xsort.hpp>
#include <xtensor/containers/xarray.hpp>
#include <xtensor/core/xmath.hpp>
#include <xtensor/io/xio.hpp>
#include <xtensor/misc/xsort.hpp>

namespace fs = std::filesystem;

Expand Down Expand Up @@ -473,6 +473,12 @@ INSTANTIATE_TEST_SUITE_P(
TEST_P(EmotiEffLibOnlyModelTests, OneImageFeatures) {
std::string modelName = GetParam();
auto facialImages = getOneImageFaces();
auto supportedBackends = EmotiEffLib::getAvailableBackends();
auto findOnnx = std::find(supportedBackends.begin(), supportedBackends.end(), "onnx");
auto findTorch = std::find(supportedBackends.begin(), supportedBackends.end(), "torch");
if (findOnnx == supportedBackends.end() or findTorch == supportedBackends.end()) {
GTEST_SKIP() << "Skipping test because of unsupported backend.";
}

fs::path modelPath(getEmotiEffLibRootDir());
modelPath = modelPath / "models" / "emotieffcpplib_prepared_models";
Expand All @@ -498,6 +504,12 @@ TEST_P(EmotiEffLibOnlyModelTests, OneImageFeatures) {
TEST_P(EmotiEffLibOnlyModelTests, OneImageMultiFeatures) {
std::string modelName = GetParam();
auto facialImages = getOneImageFaces();
auto supportedBackends = EmotiEffLib::getAvailableBackends();
auto findOnnx = std::find(supportedBackends.begin(), supportedBackends.end(), "onnx");
auto findTorch = std::find(supportedBackends.begin(), supportedBackends.end(), "torch");
if (findOnnx == supportedBackends.end() or findTorch == supportedBackends.end()) {
GTEST_SKIP() << "Skipping test because of unsupported backend.";
}

fs::path modelPath(getEmotiEffLibRootDir());
modelPath = modelPath / "models" / "emotieffcpplib_prepared_models";
Expand Down Expand Up @@ -560,26 +572,35 @@ TEST(EmotiEffLibTests, CheckIncorrectConfig) {
} catch (...) {
FAIL();
}
auto supportedBackends = EmotiEffLib::getAvailableBackends();
config = {.backend = "torch", .classifierPath = "bla-bla", .modelName = "bla-bla"};
try {
EmotiEffLib::EmotiEffLibRecognizer::createInstance(config);
FAIL();
} catch (const std::runtime_error& e) {
EXPECT_EQ("fullPipelineEmotionModelPath or featureExtractorPath MUST be specified in the "
"EmotiEffLibConfig.",
std::string(e.what()));
} catch (...) {
FAIL();
if (std::find(supportedBackends.begin(), supportedBackends.end(), config.backend) !=
supportedBackends.end()) {
try {
EmotiEffLib::EmotiEffLibRecognizer::createInstance(config);
FAIL();
} catch (const std::runtime_error& e) {
EXPECT_EQ(
"fullPipelineEmotionModelPath or featureExtractorPath MUST be specified in the "
"EmotiEffLibConfig.",
std::string(e.what()));
} catch (...) {
FAIL();
}
}
config.backend = "onnx";
try {
EmotiEffLib::EmotiEffLibRecognizer::createInstance(config);
FAIL();
} catch (const std::runtime_error& e) {
EXPECT_EQ("fullPipelineEmotionModelPath or featureExtractorPath MUST be specified in the "
"EmotiEffLibConfig.",
std::string(e.what()));
} catch (...) {
FAIL();
if (std::find(supportedBackends.begin(), supportedBackends.end(), config.backend) !=
supportedBackends.end()) {
try {
EmotiEffLib::EmotiEffLibRecognizer::createInstance(config);
FAIL();
} catch (const std::runtime_error& e) {
EXPECT_EQ(
"fullPipelineEmotionModelPath or featureExtractorPath MUST be specified in the "
"EmotiEffLibConfig.",
std::string(e.what()));
} catch (...) {
FAIL();
}
}
}
2 changes: 1 addition & 1 deletion models/prepare_models_for_emotieffcpplib.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def trace_model(
img_size = 224
input_shape = (1, 3, img_size, img_size)
model_example = torch.rand(*input_shape)
model = torch.load(torch_model, map_location=torch.device("cpu"))
model = torch.load(torch_model, map_location=torch.device("cpu"), weights_only=False)
# pylint: disable=no-else-return
if model_name in ("mbf_va_mtl.pt", "mobilevit_va_mtl.pt"):
# This is a workaround but it still is not working because of shapes issues in runtime
Expand Down
Loading