A cross-platform C++ application for detecting faces in images. The project consists of:
- A dynamic library (
face_detector) for face detection using OpenCV Haar cascades - A console application that processes images recursively and saves results
- A WebAssembly (WASM) module for browser-based face detection
- Automatic binding generation from IDL for C++ runtime loading, Java JNI, and WebAssembly
Note: The application is designed to be cross-platform but has only been tested on Linux and WebAssembly (browser).
- Detects faces in images using OpenCV's Haar cascade classifier
- Recursively processes directories with unlimited nesting
- Creates half-size copies of images with blurred face regions
- Saves detection results in JSON format
- Dynamic library loading at runtime
- Web-based face detection demo using WebAssembly
- IDL-based code generation for multiple platforms:
- C API with dynamic library export and import
- C++ client wrapper with runtime library loading
- Emscripten/WebAssembly bindings
- Java JNI bindings
- CMake 3.16+
- C++17 compatible compiler
- Python 3.8+ (for code generation)
- Ninja build system
- vcpkg package manager
- Emscripten SDK (for WASM build)
This project uses git submodules for the IDL code generator. Clone with:
git clone --recurse-submodules git@github.com:vttrtp/face-recognition.gitOr if you already cloned without submodules:
git submodule update --init --recursive# Clone vcpkg (should be at ../vcpkg relative to this project)
cd ..
git clone https://github.com/microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh # Linux/macOS
# or bootstrap-vcpkg.bat on Windows# Clone and install emsdk (should be at ../emsdk relative to this project)
cd ..
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install latest
./emsdk activate latest
source ./emsdk_env.sh # Linux/macOSNote: Update the EMSDK path in CMakePresets.json to match your installation location if needed.
Managed via vcpkg:
- OpenCV 4 (with jpeg, png, objdetect modules)
- jsoncpp
- Google Test (for unit tests)
The project uses CMake presets for easy building. Make sure vcpkg is installed at ../vcpkg relative to this project.
Available presets:
| Preset | Description | Build Directory |
|---|---|---|
default |
Release build with vcpkg | build/ |
debug |
Debug build with vcpkg | build-debug/ |
wasm |
WASM build (single-threaded) | build-wasm/ |
wasm-threads |
WASM build with pthreads (3x faster) | build-wasm-threads/ |
Native build:
cmake --preset default
cmake --build --preset defaultDebug build:
cmake --preset debug
cmake --build --preset debugA convenience script is provided to build all targets and run all tests:
.vscode/build_all.sh # Build all and run tests
.vscode/build_all.sh --clean # Clean build./build/src/app/face_recognition_app <input_directory> [options]--library <path>- Path to face_detector library (auto-detected by default)--cascade <path>- Path to Haar cascade XML file--output <path>- Output directory for result images (preserves folder structure; defaults to saving next to originals)--help- Show help message
./build/src/app/face_recognition_app ./tests/data --output ./resultsThis will:
- Find all images in
./tests/dataand its subdirectories - Detect faces in each image
- Create half-size copies with blurred faces in
./results(preserving folder structure) - Save
result.jsonin the output directory
Without --output, result images are saved next to the original images.
For each processed image, a *_result.jpg file is created with:
- Half the original dimensions
- Gaussian blur applied to detected face regions
result.json contains an array of results:
[
{
"original_file": "/path/to/image.jpg",
"result_file": "/path/to/image_result.jpg",
"success": true,
"faces": [
{"x": 100, "y": 50, "width": 200, "height": 200}
],
"face_count": 1
}
]Run all tests using the test preset:
ctest --preset defaultOr run the test executable directly:
./build/tests/face_detector_testTwo WASM build options are available:
| Build | Performance | Browser Support | Notes |
|---|---|---|---|
wasm |
Baseline | All browsers | Simple, works everywhere |
wasm-threads |
~3x faster | Modern browsers | Requires COOP/COEP headers |
cmake --preset wasm
cmake --build --preset wasmcmake --preset wasm-threads
cmake --build --preset wasm-threadsThe multithreaded build uses WebAssembly pthreads and SharedArrayBuffer for parallel processing, achieving approximately 3x faster face detection compared to single-threaded WASM.
Requirements for multithreaded WASM:
- Modern browser with SharedArrayBuffer support
- Server must send COOP/COEP headers (included via
coi-serviceworker.jsfor GitHub Pages)
Single-threaded (simple HTTP server):
cd build-wasm/web
python3 -m http.server 8080Then open your browser to: http://localhost:8080
The demo allows you to:
- Load a test image (automatically loaded) or select your own
- Detect faces with a single click
- View detection results with green rectangles drawn around faces
- See detection time in milliseconds
face-recognition/
βββ CMakeLists.txt # Root CMake configuration
βββ CMakePresets.json # CMake presets (default, debug, wasm, idl-wasm)
βββ vcpkg.json # vcpkg dependencies manifest
βββ cmake/ # CMake helper modules
βββ triplets/ # Custom vcpkg triplets (wasm32-emscripten)
βββ idlgen/ # IDL code generator submodule
βββ src/
β βββ facedetector/ # Face detector library implementation
β β βββ face_detector.idl # IDL interface definition
β βββ generated/ # Auto-generated bindings (C API, WASM, JNI)
β βββ app/ # Console application
β βββ wasm/ # WebAssembly module build config
β βββ web/ # Web demo HTML/CSS/JS
β βββ java/ # Java JNI sample application
βββ tests/ # Unit tests (face detector)
βββ data/ # Haar cascade XML files
βββ .vscode/ # VS Code configuration
βββ build_all.sh # Build and test all targets
The project uses a custom IDL (Interface Definition Language) to automatically generate:
- C API - Exported functions for the shared library
- C++ Client - Wrapper with dynamic library loading
- WASM Bindings - Emscripten JavaScript interop
- Java JNI - Native bindings for Java applications
Bindings are auto-regenerated during CMake build when the IDL file changes.
MIT License