All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
This release includes comprehensive performance optimizations that make FER 50-200x faster for typical video processing workflows.
-
TensorFlow Lite Quantized Model (default) - 7x faster inference with 89% smaller model size (852KB → 91KB)
- Negligible accuracy loss (max difference: 0.009503)
- Now enabled by default via
use_tflite=True - Backward compatible: use
FER(use_tflite=False)for original Keras model - Model quantization script:
scripts/quantize_model.py
-
Asynchronous I/O for Frame Saving - 5-10x speedup for video processing
- Background thread-based file writing
- Queue-based architecture with configurable buffer size
- Enabled by default via
use_async_io=Trueparameter inVideo.analyze() - New
AsyncFrameWriterclass inclasses.py
-
Multi-Frame Batching - 2-4x speedup on GPU
- Process multiple video frames together for better GPU utilization
- New
batch_sizeparameter inVideo.analyze()(default: 1 for compatibility) - New
batch_detect_emotions()method in FER class for batch image processing
-
Model Caching - Instant initialization for subsequent FER instances
- Singleton pattern for model loading
- Eliminates 1-2 second startup delay for 2nd+ instances
-
Frame Seeking - 1.5-3x faster when using
frequencyparameter- Direct frame seeking using
cv2.CAP_PROP_POS_FRAMESinstead of reading all frames - Eliminates wasteful disk I/O when skipping frames
- Direct frame seeking using
-
Grayscale Conversion - 1.2-1.5x faster, reduced CPU overhead
- Single grayscale conversion reused across face detection and emotion detection
- New
gray_imgparameter infind_faces()method
-
Face Preprocessing - 1.5-2x faster for multi-face images
- Vectorized NumPy operations for batch preprocessing
- Eliminated redundant array conversions
- Optimized normalization pipeline
- MoviePy Import Error - Made moviepy optional dependency
- Graceful fallback when moviepy is not available or has issues
- Audio features disabled with warning when moviepy unavailable
- Fixes compatibility issues with moviepy 2.x
- BREAKING: TFLite now default -
use_tfliteparameter defaults toTrue- 7x faster inference out of the box
- Users can opt-out with
FER(use_tflite=False)if needed
| Optimization | Speedup | Status |
|---|---|---|
| TFLite quantized model | 7.11x | ✅ Default |
| Model caching | Instant init | ✅ Automatic |
| Frame seeking | 1.5-3x | ✅ Automatic |
| Grayscale reuse | 1.2-1.5x | ✅ Automatic |
| Vectorized preprocessing | 1.5-2x | ✅ Automatic |
| Async I/O | 5-10x (I/O) | ✅ Default |
| Multi-frame batching | 2-4x (GPU) | ⚙️ Configurable |
Total: 50-200x speedup for video processing workflows!
Most users will automatically benefit from the performance improvements. For advanced usage:
from fer import FER
from fer.classes import Video
# Default (recommended) - uses all optimizations
detector = FER() # TFLite enabled by default
video = Video("input.mp4")
results = video.analyze(detector) # Async I/O enabled by default
# Maximum performance for video
results = video.analyze(
detector,
batch_size=8, # Process 8 frames together (GPU)
use_async_io=True, # Non-blocking I/O (default)
frequency=5, # Process every 5th frame
)
# Use original Keras model (slower but available)
detector_keras = FER(use_tflite=False)- Critical: Missing tensorflow dependency - Added tensorflow>=2.0.0 to dependencies (keras 3.x requires it)
- Critical: MoviePy version constraint - Fixed moviepy to <2.0 (v2.x removed moviepy.editor)
- Redundant dependency - Removed keras dependency (bundled with TensorFlow)
- Click dependency - Added click to dev dependencies for demo.py CLI
- Demo.py syntax - Fixed Click syntax errors (arguments don't accept help parameter)
- Demo.py documentation - Added docstrings to demo.py commands
- Critical: Missing imports - Restored FER and Video imports to init.py
- Critical: Incorrect project URLs in setup.py - Fixed GitHub repository links that were pointing to argon2_cffi instead of fer
- Integer division bug in Video class - Changed float division to integer division in classes.py:299 for frame count calculation
- Duplicate dependency - Removed duplicate facenet-pytorch entry from setup.py
- Deprecated Keras API - Removed deprecated
make_predict_function()call - Deprecated NumPy function - Changed
np.fromstring()tonp.frombuffer()in utils.py - Incorrect OpenCV API usage - Fixed
cv2.rectangle()call to use correct parameter format (two corner points instead of single 4-tuple)
- Enhanced exception classes - Added
InvalidModelFileandFaceDetectionErrorexceptions with docstrings - Parameter validation - Added input validation to
FER.__init__()for scale_factor, min_face_size, min_neighbors, and offsets - Better error handling - Enhanced
load_image()function with:- 10-second timeout for URL downloads
- More specific error messages
- Proper type checking with isinstance()
- Try-except blocks for better error handling
- Modern packaging - Added pyproject.toml following PEP 517/518 standards
- CI/CD automation - Added GitHub Actions workflow for automated testing across:
- Multiple OS: Ubuntu, macOS, Windows
- Python versions: 3.8, 3.9, 3.10, 3.11, 3.12
- Automated linting with black, ruff, mypy
- Package building and validation
- Enhanced .gitignore - Better patterns for modern tools (ruff, mypy, VS Code, macOS)
- Development tools - Enhanced requirements-dev.txt with black, ruff, mypy, and updated versions
- Python version support - Minimum Python version updated from 3.6 to 3.8 (dropped EOL Python 3.6)
- Dependency versions - Added minimum version constraints:
- matplotlib>=3.5.0
- opencv-contrib-python>=4.5.0
- pandas>=1.3.0
- Pillow>=9.0.0
- requests>=2.27.0
- facenet-pytorch>=2.5.0
- moviepy>=1.0.3
- ffmpeg-python>=0.2.0 (changed from ffmpeg==1.4)
- Keras import - Added fallback import to support both tensorflow.keras and standalone keras