pyfaceau 1.3.10__tar.gz → 1.3.11__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyfaceau-1.3.10/pyfaceau.egg-info → pyfaceau-1.3.11}/PKG-INFO +2 -1
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/__init__.py +1 -1
- pyfaceau-1.3.11/pyfaceau/download_weights.py +270 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11/pyfaceau.egg-info}/PKG-INFO +2 -1
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau.egg-info/requires.txt +1 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyproject.toml +2 -1
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/setup.py +1 -1
- pyfaceau-1.3.10/pyfaceau/download_weights.py +0 -343
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/LICENSE +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/MANIFEST.in +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/README.md +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/alignment/__init__.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/alignment/calc_params.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/alignment/face_aligner.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/alignment/numba_calcparams_accelerator.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/alignment/paw.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/config.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/data/__init__.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/data/hdf5_dataset.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/data/quality_filter.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/data/training_data_generator.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/detectors/__init__.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/detectors/extract_mtcnn_weights.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/detectors/openface_mtcnn.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/detectors/pfld.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/detectors/pymtcnn_detector.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/detectors/retinaface.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/features/__init__.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/features/histogram_median_tracker.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/features/pdm.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/features/triangulation.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/nn/__init__.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/nn/au_prediction_inference.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/nn/au_prediction_net.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/nn/fast_pipeline.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/nn/landmark_pose_inference.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/nn/landmark_pose_net.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/nn/train_au_prediction.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/nn/train_landmark_pose.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/parallel_pipeline.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/pipeline.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/prediction/__init__.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/prediction/au_predictor.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/prediction/batched_au_predictor.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/prediction/model_parser.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/prediction/online_au_correction.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/prediction/running_median.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/prediction/running_median_fallback.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/processor.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/refinement/__init__.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/refinement/pdm.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/refinement/svr_patch_expert.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/refinement/targeted_refiner.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/utils/__init__.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/utils/cython_extensions/cython_histogram_median.pyx +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/utils/cython_extensions/cython_rotation_update.pyx +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau/utils/cython_extensions/setup.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau.egg-info/SOURCES.txt +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau.egg-info/dependency_links.txt +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau.egg-info/entry_points.txt +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau.egg-info/not-zip-safe +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau.egg-info/top_level.txt +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/pyfaceau_gui.py +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/requirements.txt +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/setup.cfg +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_10_dynamic.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_10_static.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_12_dynamic.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_12_static.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_14_dynamic.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_14_static.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_15_dynamic.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_15_static.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_17_dynamic.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_17_static.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_1_dynamic.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_1_static.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_20_dynamic.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_20_static.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_23_dynamic.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_23_static.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_25_dynamic.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_25_static.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_26_dynamic.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_26_static.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_28_dynamic.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_28_static.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_2_dynamic.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_2_static.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_45_dynamic.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_45_static.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_4_dynamic.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_4_static.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_5_dynamic.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_5_static.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_6_dynamic.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_6_static.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_7_dynamic.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_7_static.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_9_dynamic.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_combined/AU_9_static.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_disfa/AU_12_dyn.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_disfa/AU_12_stat.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_disfa/AU_15_dyn.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_disfa/AU_15_stat.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_disfa/AU_17_dyn.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_disfa/AU_17_stat.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_disfa/AU_1_dyn.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_disfa/AU_1_stat.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_disfa/AU_20_dyn.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_disfa/AU_20_stat.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_disfa/AU_25_dyn.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_disfa/AU_25_stat.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_disfa/AU_26_dyn.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_disfa/AU_26_stat.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_disfa/AU_2_dyn.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_disfa/AU_2_stat.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_disfa/AU_4_dyn.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_disfa/AU_4_stat.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_disfa/AU_5_dyn.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_disfa/AU_5_stat.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_disfa/AU_6_dyn.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_disfa/AU_6_stat.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_disfa/AU_9_dyn.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svm_disfa/AU_9_stat.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_combined/AU_10_static_intensity_comb.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_combined/AU_12_static_intensity_comb.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_combined/AU_14_static_intensity.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_combined/AU_15_dynamic_intensity_comb.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_combined/AU_15_static_intensity_comb.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_combined/AU_17_dynamic_intensity_comb.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_combined/AU_17_static_intensity_comb.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_combined/AU_1_dynamic_intensity_comb.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_combined/AU_1_static_intensity.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_combined/AU_1_static_intensity_comb.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_combined/AU_20_dynamic_intensity.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_combined/AU_20_static_intensity.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_combined/AU_23_dynamic_intensity_comb.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_combined/AU_23_static_intensity_comb.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_combined/AU_25_dynamic_intensity_comb.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_combined/AU_25_static_intensity.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_combined/AU_26_dynamic_intensity_comb.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_combined/AU_26_static_intensity_comb.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_combined/AU_2_dynamic_intensity_comb.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_combined/AU_2_static_intensity_comb.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_combined/AU_45_dynamic_intensity_comb.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_combined/AU_45_static_intensity_comb.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_combined/AU_4_static_intensity_comb.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_combined/AU_5_dynamic_intensity.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_combined/AU_5_static_intensity.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_combined/AU_6_static_intensity_comb.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_combined/AU_7_static_intensity_comb.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_combined/AU_9_dynamic_intensity.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_combined/AU_9_static_intensity.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_disfa/AU_12_dynamic_intensity.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_disfa/AU_12_static_intensity.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_disfa/AU_15_dynamic_intensity.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_disfa/AU_15_static_intensity.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_disfa/AU_17_dynamic_intensity.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_disfa/AU_17_static_intensity.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_disfa/AU_1_dynamic_intensity.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_disfa/AU_1_static_intensity.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_disfa/AU_20_dynamic_intensity.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_disfa/AU_20_static_intensity.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_disfa/AU_25_dynamic_intensity.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_disfa/AU_25_static_intensity.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_disfa/AU_26_dynamic_intensity.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_disfa/AU_26_static_intensity.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_disfa/AU_2_dynamic_intensity.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_disfa/AU_2_static_intensity.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_disfa/AU_4_dynamic_intensity.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_disfa/AU_4_static_intensity.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_disfa/AU_5_dynamic_intensity.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_disfa/AU_5_static_intensity.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_disfa/AU_6_dynamic_intensity.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_disfa/AU_6_static_intensity.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_disfa/AU_9_dynamic_intensity.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/AU_predictors/svr_disfa/AU_9_static_intensity.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/patch_experts/cen_patches_0.25_of.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/patch_experts/cen_patches_0.35_of.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/patch_experts/cen_patches_0.50_of.dat +0 -0
- {pyfaceau-1.3.10 → pyfaceau-1.3.11}/weights/patch_experts/cen_patches_1.00_of.dat +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyfaceau
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.11
|
|
4
4
|
Summary: Pure Python OpenFace 2.2 AU extraction with CLNF landmark refinement
|
|
5
5
|
Home-page: https://github.com/johnwilsoniv/face-analysis
|
|
6
6
|
Author: John Wilson
|
|
@@ -32,6 +32,7 @@ Requires-Dist: scipy>=1.7.0
|
|
|
32
32
|
Requires-Dist: scikit-learn>=1.0.0
|
|
33
33
|
Requires-Dist: tqdm>=4.62.0
|
|
34
34
|
Requires-Dist: numba>=0.56.0
|
|
35
|
+
Requires-Dist: torch>=2.0.0
|
|
35
36
|
Requires-Dist: pyfhog>=0.1.0
|
|
36
37
|
Requires-Dist: pyclnf>=0.2.0
|
|
37
38
|
Requires-Dist: pymtcnn>=0.1.0
|
|
@@ -5,7 +5,7 @@ A complete Python implementation of OpenFace 2.2's AU extraction pipeline
|
|
|
5
5
|
with high-performance parallel processing support and CLNF landmark refinement.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
__version__ = "1.3.
|
|
8
|
+
__version__ = "1.3.11"
|
|
9
9
|
|
|
10
10
|
# Weight management functions can be imported without heavy dependencies
|
|
11
11
|
from .download_weights import (
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Download model weights for PyFaceAU
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
python -m pyfaceau.download_weights
|
|
7
|
+
|
|
8
|
+
Or programmatically:
|
|
9
|
+
from pyfaceau.download_weights import ensure_weights
|
|
10
|
+
weights_dir = ensure_weights()
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import os
|
|
14
|
+
import sys
|
|
15
|
+
import urllib.request
|
|
16
|
+
import zipfile
|
|
17
|
+
import tempfile
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
|
|
20
|
+
# Try to import tqdm, fall back to simple progress if not available
|
|
21
|
+
try:
|
|
22
|
+
from tqdm import tqdm
|
|
23
|
+
TQDM_AVAILABLE = True
|
|
24
|
+
except ImportError:
|
|
25
|
+
TQDM_AVAILABLE = False
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# GitHub release URL for weights zip (~1.6MB compressed)
|
|
29
|
+
WEIGHTS_ZIP_URL = "https://github.com/johnwilsoniv/pyfaceau/releases/download/weights-v1.0/pyfaceau-weights-v1.0.zip"
|
|
30
|
+
|
|
31
|
+
# Required files to verify successful download
|
|
32
|
+
REQUIRED_FILES = [
|
|
33
|
+
"In-the-wild_aligned_PDM_68.txt",
|
|
34
|
+
"svr_patches_0.25_general.txt",
|
|
35
|
+
"tris_68_full.txt",
|
|
36
|
+
"AU_predictors/AU_all_best.txt",
|
|
37
|
+
"AU_predictors/svr_combined/AU_1_dynamic_intensity_comb.dat",
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
if TQDM_AVAILABLE:
|
|
42
|
+
class DownloadProgressBar(tqdm):
|
|
43
|
+
"""Progress bar for downloads"""
|
|
44
|
+
def update_to(self, b=1, bsize=1, tsize=None):
|
|
45
|
+
if tsize is not None:
|
|
46
|
+
self.total = tsize
|
|
47
|
+
self.update(b * bsize - self.n)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def download_file(url, output_path, desc=None):
|
|
51
|
+
"""Download a file with progress bar"""
|
|
52
|
+
if TQDM_AVAILABLE:
|
|
53
|
+
with DownloadProgressBar(unit='B', unit_scale=True, miniters=1, desc=desc) as t:
|
|
54
|
+
urllib.request.urlretrieve(url, filename=output_path, reporthook=t.update_to)
|
|
55
|
+
else:
|
|
56
|
+
print(f" Downloading {desc or url}...")
|
|
57
|
+
urllib.request.urlretrieve(url, filename=output_path)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def get_user_weights_dir():
|
|
61
|
+
"""
|
|
62
|
+
Get user-writable weights directory.
|
|
63
|
+
|
|
64
|
+
Priority:
|
|
65
|
+
1. PYFACEAU_WEIGHTS_DIR environment variable
|
|
66
|
+
2. ~/.pyfaceau/weights/
|
|
67
|
+
"""
|
|
68
|
+
env_dir = os.environ.get('PYFACEAU_WEIGHTS_DIR')
|
|
69
|
+
if env_dir:
|
|
70
|
+
weights_dir = Path(env_dir)
|
|
71
|
+
else:
|
|
72
|
+
weights_dir = Path.home() / ".pyfaceau" / "weights"
|
|
73
|
+
|
|
74
|
+
weights_dir.mkdir(parents=True, exist_ok=True)
|
|
75
|
+
return weights_dir
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def get_weights_dir():
|
|
79
|
+
"""
|
|
80
|
+
Get weights directory, checking multiple locations.
|
|
81
|
+
|
|
82
|
+
Priority:
|
|
83
|
+
1. PYFACEAU_WEIGHTS_DIR environment variable
|
|
84
|
+
2. Sibling 'weights' directory (for development installs)
|
|
85
|
+
3. User home directory ~/.pyfaceau/weights/
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
Path to weights directory (may not exist if weights not downloaded)
|
|
89
|
+
"""
|
|
90
|
+
# Check environment variable first
|
|
91
|
+
env_dir = os.environ.get('PYFACEAU_WEIGHTS_DIR')
|
|
92
|
+
if env_dir and Path(env_dir).exists():
|
|
93
|
+
if weights_exist(Path(env_dir)):
|
|
94
|
+
return Path(env_dir)
|
|
95
|
+
|
|
96
|
+
# Check sibling weights directory (for development/editable installs)
|
|
97
|
+
try:
|
|
98
|
+
pkg_dir = Path(__file__).parent.parent # pyfaceau package parent
|
|
99
|
+
dev_weights = pkg_dir / "weights"
|
|
100
|
+
if dev_weights.exists() and weights_exist(dev_weights):
|
|
101
|
+
return dev_weights
|
|
102
|
+
except Exception:
|
|
103
|
+
pass
|
|
104
|
+
|
|
105
|
+
# Check user home directory
|
|
106
|
+
user_weights = Path.home() / ".pyfaceau" / "weights"
|
|
107
|
+
if user_weights.exists() and weights_exist(user_weights):
|
|
108
|
+
return user_weights
|
|
109
|
+
|
|
110
|
+
# Return user weights dir (will need download)
|
|
111
|
+
return user_weights
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def weights_exist(weights_dir=None):
|
|
115
|
+
"""Check if required weights exist"""
|
|
116
|
+
if weights_dir is None:
|
|
117
|
+
weights_dir = get_weights_dir()
|
|
118
|
+
weights_dir = Path(weights_dir)
|
|
119
|
+
|
|
120
|
+
# Check main PDM file
|
|
121
|
+
pdm_file = weights_dir / "In-the-wild_aligned_PDM_68.txt"
|
|
122
|
+
if not pdm_file.exists():
|
|
123
|
+
return False
|
|
124
|
+
|
|
125
|
+
# Check at least one AU model
|
|
126
|
+
au_model = weights_dir / "AU_predictors" / "svr_combined" / "AU_1_dynamic_intensity_comb.dat"
|
|
127
|
+
if not au_model.exists():
|
|
128
|
+
return False
|
|
129
|
+
|
|
130
|
+
return True
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def ensure_weights(auto_download=True, verbose=True):
|
|
134
|
+
"""
|
|
135
|
+
Ensure weights are available, downloading if necessary.
|
|
136
|
+
|
|
137
|
+
Args:
|
|
138
|
+
auto_download: If True, automatically download missing weights
|
|
139
|
+
verbose: If True, print progress messages
|
|
140
|
+
|
|
141
|
+
Returns:
|
|
142
|
+
Path to weights directory
|
|
143
|
+
|
|
144
|
+
Raises:
|
|
145
|
+
FileNotFoundError: If weights are missing and auto_download is False
|
|
146
|
+
"""
|
|
147
|
+
weights_dir = get_weights_dir()
|
|
148
|
+
|
|
149
|
+
if weights_exist(weights_dir):
|
|
150
|
+
return weights_dir
|
|
151
|
+
|
|
152
|
+
if not auto_download:
|
|
153
|
+
raise FileNotFoundError(
|
|
154
|
+
f"PyFaceAU weights not found.\n"
|
|
155
|
+
f"Expected location: {weights_dir}\n"
|
|
156
|
+
f"\n"
|
|
157
|
+
f"To download weights, run:\n"
|
|
158
|
+
f" python -m pyfaceau.download_weights\n"
|
|
159
|
+
f"\n"
|
|
160
|
+
f"Or set PYFACEAU_WEIGHTS_DIR environment variable to your weights directory."
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
if verbose:
|
|
164
|
+
print("PyFaceAU weights not found. Downloading (~1.6MB)...")
|
|
165
|
+
|
|
166
|
+
# Download to user weights directory
|
|
167
|
+
download_dir = get_user_weights_dir()
|
|
168
|
+
result = download_weights(download_dir, verbose=verbose)
|
|
169
|
+
|
|
170
|
+
if result != 0:
|
|
171
|
+
raise RuntimeError("Failed to download PyFaceAU weights")
|
|
172
|
+
|
|
173
|
+
return download_dir
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def download_weights(weights_dir=None, verbose=True):
|
|
177
|
+
"""
|
|
178
|
+
Download all required weights.
|
|
179
|
+
|
|
180
|
+
Args:
|
|
181
|
+
weights_dir: Directory to download weights to (default: ~/.pyfaceau/weights/)
|
|
182
|
+
verbose: If True, print progress messages
|
|
183
|
+
|
|
184
|
+
Returns:
|
|
185
|
+
0 on success, 1 on failure
|
|
186
|
+
"""
|
|
187
|
+
if weights_dir is None:
|
|
188
|
+
weights_dir = get_user_weights_dir()
|
|
189
|
+
weights_dir = Path(weights_dir)
|
|
190
|
+
|
|
191
|
+
if verbose:
|
|
192
|
+
print("PyFaceAU Weight Downloader")
|
|
193
|
+
print("=" * 60)
|
|
194
|
+
print(f"Downloading weights to: {weights_dir}")
|
|
195
|
+
print()
|
|
196
|
+
|
|
197
|
+
# Create directory
|
|
198
|
+
weights_dir.mkdir(parents=True, exist_ok=True)
|
|
199
|
+
|
|
200
|
+
# Download zip file to temp location
|
|
201
|
+
try:
|
|
202
|
+
with tempfile.NamedTemporaryFile(suffix='.zip', delete=False) as tmp_file:
|
|
203
|
+
tmp_path = tmp_file.name
|
|
204
|
+
|
|
205
|
+
if verbose:
|
|
206
|
+
print(f"Downloading weights from GitHub release...")
|
|
207
|
+
print(f" URL: {WEIGHTS_ZIP_URL}")
|
|
208
|
+
|
|
209
|
+
download_file(WEIGHTS_ZIP_URL, tmp_path, desc="pyfaceau-weights.zip")
|
|
210
|
+
|
|
211
|
+
if verbose:
|
|
212
|
+
print(f"\nExtracting weights...")
|
|
213
|
+
|
|
214
|
+
# Extract zip
|
|
215
|
+
with zipfile.ZipFile(tmp_path, 'r') as zip_ref:
|
|
216
|
+
zip_ref.extractall(weights_dir)
|
|
217
|
+
|
|
218
|
+
if verbose:
|
|
219
|
+
print(f" Extracted to: {weights_dir}")
|
|
220
|
+
|
|
221
|
+
# Verify extraction
|
|
222
|
+
missing = []
|
|
223
|
+
for req_file in REQUIRED_FILES:
|
|
224
|
+
if not (weights_dir / req_file).exists():
|
|
225
|
+
missing.append(req_file)
|
|
226
|
+
|
|
227
|
+
if missing:
|
|
228
|
+
print(f"\n[WARNING] Some files missing after extraction:")
|
|
229
|
+
for f in missing:
|
|
230
|
+
print(f" - {f}")
|
|
231
|
+
return 1
|
|
232
|
+
|
|
233
|
+
if verbose:
|
|
234
|
+
print("\n" + "=" * 60)
|
|
235
|
+
print("[OK] All weights downloaded successfully!")
|
|
236
|
+
print(f"Weights location: {weights_dir}")
|
|
237
|
+
print("\nYou can now use PyFaceAU:")
|
|
238
|
+
print(" from pyfaceau import OpenFaceProcessor")
|
|
239
|
+
print(" processor = OpenFaceProcessor()")
|
|
240
|
+
|
|
241
|
+
return 0
|
|
242
|
+
|
|
243
|
+
except urllib.error.URLError as e:
|
|
244
|
+
print(f"\n[ERROR] Failed to download weights: {e}")
|
|
245
|
+
print("\nPlease check your internet connection and try again.")
|
|
246
|
+
print("Or download manually from:")
|
|
247
|
+
print(f" {WEIGHTS_ZIP_URL}")
|
|
248
|
+
print(f"And extract to: {weights_dir}")
|
|
249
|
+
return 1
|
|
250
|
+
|
|
251
|
+
except Exception as e:
|
|
252
|
+
print(f"\n[ERROR] Unexpected error: {e}")
|
|
253
|
+
return 1
|
|
254
|
+
|
|
255
|
+
finally:
|
|
256
|
+
# Clean up temp file
|
|
257
|
+
try:
|
|
258
|
+
if 'tmp_path' in locals():
|
|
259
|
+
os.unlink(tmp_path)
|
|
260
|
+
except Exception:
|
|
261
|
+
pass
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def main():
|
|
265
|
+
"""Command-line entry point for weight download"""
|
|
266
|
+
return download_weights(verbose=True)
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
if __name__ == "__main__":
|
|
270
|
+
sys.exit(main())
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyfaceau
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.11
|
|
4
4
|
Summary: Pure Python OpenFace 2.2 AU extraction with CLNF landmark refinement
|
|
5
5
|
Home-page: https://github.com/johnwilsoniv/face-analysis
|
|
6
6
|
Author: John Wilson
|
|
@@ -32,6 +32,7 @@ Requires-Dist: scipy>=1.7.0
|
|
|
32
32
|
Requires-Dist: scikit-learn>=1.0.0
|
|
33
33
|
Requires-Dist: tqdm>=4.62.0
|
|
34
34
|
Requires-Dist: numba>=0.56.0
|
|
35
|
+
Requires-Dist: torch>=2.0.0
|
|
35
36
|
Requires-Dist: pyfhog>=0.1.0
|
|
36
37
|
Requires-Dist: pyclnf>=0.2.0
|
|
37
38
|
Requires-Dist: pymtcnn>=0.1.0
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pyfaceau"
|
|
7
|
-
version = "1.3.
|
|
7
|
+
version = "1.3.11"
|
|
8
8
|
description = "Pure Python OpenFace 2.2 AU extraction with CLNF landmark refinement"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -35,6 +35,7 @@ dependencies = [
|
|
|
35
35
|
"scikit-learn>=1.0.0",
|
|
36
36
|
"tqdm>=4.62.0",
|
|
37
37
|
"numba>=0.56.0",
|
|
38
|
+
"torch>=2.0.0", # Required for pyclnf GPU acceleration
|
|
38
39
|
"pyfhog>=0.1.0",
|
|
39
40
|
"pyclnf>=0.2.0",
|
|
40
41
|
"pymtcnn>=0.1.0",
|
|
@@ -11,7 +11,7 @@ long_description = (this_directory / "README.md").read_text()
|
|
|
11
11
|
|
|
12
12
|
setup(
|
|
13
13
|
name="pyfaceau",
|
|
14
|
-
version="1.3.
|
|
14
|
+
version="1.3.11",
|
|
15
15
|
author="John Wilson",
|
|
16
16
|
author_email="", # Add email if desired
|
|
17
17
|
description="Pure Python OpenFace 2.2 AU extraction with PyMTCNN face detection and CLNF refinement",
|
|
@@ -1,343 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
Download model weights for PyFaceAU
|
|
4
|
-
|
|
5
|
-
Usage:
|
|
6
|
-
python -m pyfaceau.download_weights
|
|
7
|
-
|
|
8
|
-
Or programmatically:
|
|
9
|
-
from pyfaceau.download_weights import ensure_weights
|
|
10
|
-
weights_dir = ensure_weights()
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
import os
|
|
14
|
-
import sys
|
|
15
|
-
import urllib.request
|
|
16
|
-
from pathlib import Path
|
|
17
|
-
|
|
18
|
-
# Try to import tqdm, fall back to simple progress if not available
|
|
19
|
-
try:
|
|
20
|
-
from tqdm import tqdm
|
|
21
|
-
TQDM_AVAILABLE = True
|
|
22
|
-
except ImportError:
|
|
23
|
-
TQDM_AVAILABLE = False
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
# GitHub release URL for weights (use releases for large files, not raw repo)
|
|
27
|
-
# Create a release at: https://github.com/johnwilsoniv/pyfaceau/releases with weights.zip
|
|
28
|
-
WEIGHTS_BASE_URL = "https://github.com/johnwilsoniv/pyfaceau/releases/download/weights-v1.0/"
|
|
29
|
-
|
|
30
|
-
# Fallback: Raw GitHub URL (for smaller text files)
|
|
31
|
-
# Note: Binary .dat files may need LFS or release hosting
|
|
32
|
-
WEIGHTS_FALLBACK_URL = "https://raw.githubusercontent.com/johnwilsoniv/pyfaceau/main/weights/"
|
|
33
|
-
|
|
34
|
-
REQUIRED_WEIGHTS = {
|
|
35
|
-
# Note: Face detection uses PyMTCNN (installed separately)
|
|
36
|
-
# Note: Landmark detection uses CLNF (Constrained Local Neural Fields)
|
|
37
|
-
"In-the-wild_aligned_PDM_68.txt": "67KB - PDM shape model",
|
|
38
|
-
"svr_patches_0.25_general.txt": "1.1MB - CLNF patch experts",
|
|
39
|
-
"tris_68_full.txt": "1KB - Triangulation data",
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
# AU predictor files stored in AU_predictors/svr_combined/ subdirectory
|
|
43
|
-
AU_PREDICTOR_FILES = [
|
|
44
|
-
"svr_combined/AU_1_dynamic_intensity_comb.dat",
|
|
45
|
-
"svr_combined/AU_2_dynamic_intensity_comb.dat",
|
|
46
|
-
"svr_combined/AU_4_static_intensity_comb.dat",
|
|
47
|
-
"svr_combined/AU_5_dynamic_intensity_comb.dat",
|
|
48
|
-
"svr_combined/AU_6_static_intensity_comb.dat",
|
|
49
|
-
"svr_combined/AU_7_static_intensity_comb.dat",
|
|
50
|
-
"svr_combined/AU_9_dynamic_intensity_comb.dat",
|
|
51
|
-
"svr_combined/AU_10_static_intensity_comb.dat",
|
|
52
|
-
"svr_combined/AU_12_static_intensity_comb.dat",
|
|
53
|
-
"svr_combined/AU_14_static_intensity_comb.dat",
|
|
54
|
-
"svr_combined/AU_15_dynamic_intensity_comb.dat",
|
|
55
|
-
"svr_combined/AU_17_dynamic_intensity_comb.dat",
|
|
56
|
-
"svr_combined/AU_20_dynamic_intensity_comb.dat",
|
|
57
|
-
"svr_combined/AU_23_dynamic_intensity_comb.dat",
|
|
58
|
-
"svr_combined/AU_25_dynamic_intensity_comb.dat",
|
|
59
|
-
"svr_combined/AU_26_dynamic_intensity_comb.dat",
|
|
60
|
-
"svr_combined/AU_45_dynamic_intensity_comb.dat",
|
|
61
|
-
]
|
|
62
|
-
|
|
63
|
-
# AU predictor config files
|
|
64
|
-
AU_CONFIG_FILES = [
|
|
65
|
-
"AU_all_best.txt",
|
|
66
|
-
"main_dynamic_svms.txt",
|
|
67
|
-
]
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
if TQDM_AVAILABLE:
|
|
71
|
-
class DownloadProgressBar(tqdm):
|
|
72
|
-
"""Progress bar for downloads"""
|
|
73
|
-
def update_to(self, b=1, bsize=1, tsize=None):
|
|
74
|
-
if tsize is not None:
|
|
75
|
-
self.total = tsize
|
|
76
|
-
self.update(b * bsize - self.n)
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
def download_file(url, output_path, desc=None):
|
|
80
|
-
"""Download a file with progress bar"""
|
|
81
|
-
os.makedirs(os.path.dirname(output_path), exist_ok=True)
|
|
82
|
-
|
|
83
|
-
if TQDM_AVAILABLE:
|
|
84
|
-
with DownloadProgressBar(unit='B', unit_scale=True, miniters=1, desc=desc) as t:
|
|
85
|
-
urllib.request.urlretrieve(url, filename=output_path, reporthook=t.update_to)
|
|
86
|
-
else:
|
|
87
|
-
# Simple fallback without progress bar
|
|
88
|
-
print(f" Downloading {desc or url}...")
|
|
89
|
-
urllib.request.urlretrieve(url, filename=output_path)
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
def get_user_weights_dir():
|
|
93
|
-
"""
|
|
94
|
-
Get user-writable weights directory.
|
|
95
|
-
|
|
96
|
-
Priority:
|
|
97
|
-
1. PYFACEAU_WEIGHTS_DIR environment variable
|
|
98
|
-
2. ~/.pyfaceau/weights/
|
|
99
|
-
"""
|
|
100
|
-
# Check environment variable first
|
|
101
|
-
env_dir = os.environ.get('PYFACEAU_WEIGHTS_DIR')
|
|
102
|
-
if env_dir:
|
|
103
|
-
weights_dir = Path(env_dir)
|
|
104
|
-
else:
|
|
105
|
-
# Default to user home directory
|
|
106
|
-
weights_dir = Path.home() / ".pyfaceau" / "weights"
|
|
107
|
-
|
|
108
|
-
weights_dir.mkdir(parents=True, exist_ok=True)
|
|
109
|
-
return weights_dir
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
def get_weights_dir():
|
|
113
|
-
"""
|
|
114
|
-
Get weights directory, checking multiple locations.
|
|
115
|
-
|
|
116
|
-
Priority:
|
|
117
|
-
1. PYFACEAU_WEIGHTS_DIR environment variable
|
|
118
|
-
2. Sibling 'weights' directory (for development installs)
|
|
119
|
-
3. User home directory ~/.pyfaceau/weights/
|
|
120
|
-
|
|
121
|
-
Returns:
|
|
122
|
-
Path to weights directory (may not exist if weights not downloaded)
|
|
123
|
-
"""
|
|
124
|
-
# Check environment variable first
|
|
125
|
-
env_dir = os.environ.get('PYFACEAU_WEIGHTS_DIR')
|
|
126
|
-
if env_dir and Path(env_dir).exists():
|
|
127
|
-
return Path(env_dir)
|
|
128
|
-
|
|
129
|
-
# Check sibling weights directory (for development/editable installs)
|
|
130
|
-
try:
|
|
131
|
-
pkg_dir = Path(__file__).parent.parent # pyfaceau package parent
|
|
132
|
-
dev_weights = pkg_dir / "weights"
|
|
133
|
-
if dev_weights.exists() and (dev_weights / "In-the-wild_aligned_PDM_68.txt").exists():
|
|
134
|
-
return dev_weights
|
|
135
|
-
except Exception:
|
|
136
|
-
pass
|
|
137
|
-
|
|
138
|
-
# Check user home directory
|
|
139
|
-
user_weights = Path.home() / ".pyfaceau" / "weights"
|
|
140
|
-
if user_weights.exists() and (user_weights / "In-the-wild_aligned_PDM_68.txt").exists():
|
|
141
|
-
return user_weights
|
|
142
|
-
|
|
143
|
-
# Return user weights dir (will need download)
|
|
144
|
-
return user_weights
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
def weights_exist(weights_dir=None):
|
|
148
|
-
"""Check if required weights exist"""
|
|
149
|
-
if weights_dir is None:
|
|
150
|
-
weights_dir = get_weights_dir()
|
|
151
|
-
weights_dir = Path(weights_dir)
|
|
152
|
-
|
|
153
|
-
# Check main PDM file
|
|
154
|
-
pdm_file = weights_dir / "In-the-wild_aligned_PDM_68.txt"
|
|
155
|
-
if not pdm_file.exists():
|
|
156
|
-
return False
|
|
157
|
-
|
|
158
|
-
# Check at least one AU model
|
|
159
|
-
au_dir = weights_dir / "AU_predictors" / "svr_combined"
|
|
160
|
-
if not au_dir.exists():
|
|
161
|
-
return False
|
|
162
|
-
|
|
163
|
-
return True
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
def ensure_weights(auto_download=True, verbose=True):
|
|
167
|
-
"""
|
|
168
|
-
Ensure weights are available, downloading if necessary.
|
|
169
|
-
|
|
170
|
-
Args:
|
|
171
|
-
auto_download: If True, automatically download missing weights
|
|
172
|
-
verbose: If True, print progress messages
|
|
173
|
-
|
|
174
|
-
Returns:
|
|
175
|
-
Path to weights directory
|
|
176
|
-
|
|
177
|
-
Raises:
|
|
178
|
-
FileNotFoundError: If weights are missing and auto_download is False
|
|
179
|
-
"""
|
|
180
|
-
weights_dir = get_weights_dir()
|
|
181
|
-
|
|
182
|
-
if weights_exist(weights_dir):
|
|
183
|
-
return weights_dir
|
|
184
|
-
|
|
185
|
-
if not auto_download:
|
|
186
|
-
raise FileNotFoundError(
|
|
187
|
-
f"PyFaceAU weights not found.\n"
|
|
188
|
-
f"Expected location: {weights_dir}\n"
|
|
189
|
-
f"\n"
|
|
190
|
-
f"To download weights, run:\n"
|
|
191
|
-
f" python -m pyfaceau.download_weights\n"
|
|
192
|
-
f"\n"
|
|
193
|
-
f"Or set PYFACEAU_WEIGHTS_DIR environment variable to your weights directory."
|
|
194
|
-
)
|
|
195
|
-
|
|
196
|
-
if verbose:
|
|
197
|
-
print("PyFaceAU weights not found. Downloading...")
|
|
198
|
-
|
|
199
|
-
# Download to user weights directory
|
|
200
|
-
download_dir = get_user_weights_dir()
|
|
201
|
-
result = download_weights(download_dir, verbose=verbose)
|
|
202
|
-
|
|
203
|
-
if result != 0:
|
|
204
|
-
raise RuntimeError("Failed to download PyFaceAU weights")
|
|
205
|
-
|
|
206
|
-
return download_dir
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
def download_weights(weights_dir=None, verbose=True):
|
|
210
|
-
"""
|
|
211
|
-
Download all required weights.
|
|
212
|
-
|
|
213
|
-
Args:
|
|
214
|
-
weights_dir: Directory to download weights to (default: ~/.pyfaceau/weights/)
|
|
215
|
-
verbose: If True, print progress messages
|
|
216
|
-
|
|
217
|
-
Returns:
|
|
218
|
-
0 on success, 1 on failure
|
|
219
|
-
"""
|
|
220
|
-
if weights_dir is None:
|
|
221
|
-
weights_dir = get_user_weights_dir()
|
|
222
|
-
weights_dir = Path(weights_dir)
|
|
223
|
-
|
|
224
|
-
if verbose:
|
|
225
|
-
print("PyFaceAU Weight Downloader")
|
|
226
|
-
print("=" * 60)
|
|
227
|
-
print(f"Downloading weights to: {weights_dir}")
|
|
228
|
-
print()
|
|
229
|
-
|
|
230
|
-
# Create directory structure
|
|
231
|
-
weights_dir.mkdir(parents=True, exist_ok=True)
|
|
232
|
-
(weights_dir / "AU_predictors" / "svr_combined").mkdir(parents=True, exist_ok=True)
|
|
233
|
-
|
|
234
|
-
# Try primary URL first, fall back to secondary
|
|
235
|
-
base_urls = [WEIGHTS_BASE_URL, WEIGHTS_FALLBACK_URL]
|
|
236
|
-
|
|
237
|
-
# Download main weights
|
|
238
|
-
if verbose:
|
|
239
|
-
print("Downloading main model weights...")
|
|
240
|
-
|
|
241
|
-
for filename, description in REQUIRED_WEIGHTS.items():
|
|
242
|
-
output_path = weights_dir / filename
|
|
243
|
-
|
|
244
|
-
if output_path.exists():
|
|
245
|
-
if verbose:
|
|
246
|
-
print(f"[OK] {filename} (already exists)")
|
|
247
|
-
continue
|
|
248
|
-
|
|
249
|
-
downloaded = False
|
|
250
|
-
for base_url in base_urls:
|
|
251
|
-
url = base_url + filename
|
|
252
|
-
try:
|
|
253
|
-
download_file(url, str(output_path), desc=f"{filename} ({description})")
|
|
254
|
-
if verbose:
|
|
255
|
-
print(f"[OK] Downloaded {filename}")
|
|
256
|
-
downloaded = True
|
|
257
|
-
break
|
|
258
|
-
except Exception as e:
|
|
259
|
-
if verbose:
|
|
260
|
-
print(f" (trying fallback URL...)")
|
|
261
|
-
continue
|
|
262
|
-
|
|
263
|
-
if not downloaded:
|
|
264
|
-
print(f"[FAILED] Failed to download {filename}")
|
|
265
|
-
print(f" Please download manually from GitHub and place in: {output_path}")
|
|
266
|
-
return 1
|
|
267
|
-
|
|
268
|
-
# Download AU predictor config files
|
|
269
|
-
if verbose:
|
|
270
|
-
print("\nDownloading AU predictor config files...")
|
|
271
|
-
|
|
272
|
-
au_dir = weights_dir / "AU_predictors"
|
|
273
|
-
for filename in AU_CONFIG_FILES:
|
|
274
|
-
output_path = au_dir / filename
|
|
275
|
-
|
|
276
|
-
if output_path.exists():
|
|
277
|
-
if verbose:
|
|
278
|
-
print(f"[OK] {filename} (already exists)")
|
|
279
|
-
continue
|
|
280
|
-
|
|
281
|
-
downloaded = False
|
|
282
|
-
for base_url in base_urls:
|
|
283
|
-
url = base_url + "AU_predictors/" + filename
|
|
284
|
-
try:
|
|
285
|
-
download_file(url, str(output_path), desc=filename)
|
|
286
|
-
if verbose:
|
|
287
|
-
print(f"[OK] Downloaded {filename}")
|
|
288
|
-
downloaded = True
|
|
289
|
-
break
|
|
290
|
-
except Exception:
|
|
291
|
-
continue
|
|
292
|
-
|
|
293
|
-
if not downloaded:
|
|
294
|
-
print(f"[FAILED] Failed to download {filename}")
|
|
295
|
-
return 1
|
|
296
|
-
|
|
297
|
-
# Download AU predictor models
|
|
298
|
-
if verbose:
|
|
299
|
-
print("\nDownloading AU predictor models (SVR weights)...")
|
|
300
|
-
|
|
301
|
-
for filename in AU_PREDICTOR_FILES:
|
|
302
|
-
output_path = au_dir / filename
|
|
303
|
-
|
|
304
|
-
if output_path.exists():
|
|
305
|
-
if verbose:
|
|
306
|
-
print(f"[OK] {filename} (already exists)")
|
|
307
|
-
continue
|
|
308
|
-
|
|
309
|
-
downloaded = False
|
|
310
|
-
for base_url in base_urls:
|
|
311
|
-
url = base_url + "AU_predictors/" + filename
|
|
312
|
-
try:
|
|
313
|
-
download_file(url, str(output_path), desc=filename.split('/')[-1])
|
|
314
|
-
if verbose:
|
|
315
|
-
print(f"[OK] Downloaded {filename}")
|
|
316
|
-
downloaded = True
|
|
317
|
-
break
|
|
318
|
-
except Exception:
|
|
319
|
-
continue
|
|
320
|
-
|
|
321
|
-
if not downloaded:
|
|
322
|
-
print(f"[FAILED] Failed to download {filename}")
|
|
323
|
-
print(f" Please download manually from GitHub and place in: {output_path}")
|
|
324
|
-
return 1
|
|
325
|
-
|
|
326
|
-
if verbose:
|
|
327
|
-
print("\n" + "=" * 60)
|
|
328
|
-
print("[OK] All weights downloaded successfully!")
|
|
329
|
-
print(f"Weights location: {weights_dir}")
|
|
330
|
-
print("\nYou can now use PyFaceAU:")
|
|
331
|
-
print(" from pyfaceau import OpenFaceProcessor")
|
|
332
|
-
print(" processor = OpenFaceProcessor()")
|
|
333
|
-
|
|
334
|
-
return 0
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
def main():
|
|
338
|
-
"""Command-line entry point for weight download"""
|
|
339
|
-
return download_weights(verbose=True)
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
if __name__ == "__main__":
|
|
343
|
-
sys.exit(main())
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|