pyfaceau 1.3.3__tar.gz → 1.3.4__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.3/pyfaceau.egg-info → pyfaceau-1.3.4}/PKG-INFO +1 -1
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/config.py +6 -5
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/data/training_data_generator.py +69 -11
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/parallel_pipeline.py +2 -1
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/pipeline.py +39 -8
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/prediction/au_predictor.py +2 -1
- {pyfaceau-1.3.3 → pyfaceau-1.3.4/pyfaceau.egg-info}/PKG-INFO +1 -1
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyproject.toml +1 -1
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/LICENSE +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/MANIFEST.in +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/README.md +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/__init__.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/alignment/__init__.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/alignment/calc_params.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/alignment/face_aligner.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/alignment/numba_calcparams_accelerator.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/alignment/paw.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/data/__init__.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/data/hdf5_dataset.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/data/quality_filter.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/detectors/__init__.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/detectors/extract_mtcnn_weights.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/detectors/openface_mtcnn.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/detectors/pfld.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/detectors/pymtcnn_detector.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/detectors/retinaface.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/download_weights.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/features/__init__.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/features/histogram_median_tracker.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/features/pdm.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/features/triangulation.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/nn/__init__.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/nn/au_prediction_inference.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/nn/au_prediction_net.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/nn/fast_pipeline.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/nn/landmark_pose_inference.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/nn/landmark_pose_net.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/nn/train_au_prediction.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/nn/train_landmark_pose.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/prediction/__init__.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/prediction/batched_au_predictor.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/prediction/model_parser.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/prediction/online_au_correction.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/prediction/running_median.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/prediction/running_median_fallback.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/processor.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/refinement/__init__.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/refinement/pdm.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/refinement/svr_patch_expert.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/refinement/targeted_refiner.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/utils/__init__.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/utils/cython_extensions/cython_histogram_median.pyx +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/utils/cython_extensions/cython_rotation_update.pyx +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/utils/cython_extensions/setup.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau.egg-info/SOURCES.txt +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau.egg-info/dependency_links.txt +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau.egg-info/entry_points.txt +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau.egg-info/not-zip-safe +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau.egg-info/requires.txt +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau.egg-info/top_level.txt +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau_gui.py +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/requirements.txt +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/setup.cfg +0 -0
- {pyfaceau-1.3.3 → pyfaceau-1.3.4}/setup.py +0 -0
|
@@ -16,9 +16,12 @@ CLNF_CONFIG = {
|
|
|
16
16
|
'max_iterations': 10,
|
|
17
17
|
'convergence_threshold': 0.005, # Gold standard (stricter than 0.01)
|
|
18
18
|
'sigma': 2.25, # C++ CECLM default (1.5 × 1.5 scale factor)
|
|
19
|
-
'use_eye_refinement': True, #
|
|
19
|
+
'use_eye_refinement': True, # Enabled: fixed transpose bug, now improves accuracy
|
|
20
20
|
'convergence_profile': 'video', # Enable template tracking + scale adaptation
|
|
21
21
|
'detector': False, # Disable built-in detector (pyfaceau handles)
|
|
22
|
+
'use_gpu': True, # Enable GPU acceleration (10-20x speedup)
|
|
23
|
+
'gpu_device': 'auto', # GPU device: 'auto', 'mps', 'cuda', 'cpu'
|
|
24
|
+
'use_validator': False, # Disable detection validator (68% of CLNF time)
|
|
22
25
|
}
|
|
23
26
|
|
|
24
27
|
# =============================================================================
|
|
@@ -67,11 +70,9 @@ AU_CONFIG = {
|
|
|
67
70
|
'max_stored_frames': 3000, # OpenFace default for re-prediction
|
|
68
71
|
|
|
69
72
|
# AU-specific cutoff overrides
|
|
70
|
-
#
|
|
71
|
-
#
|
|
72
|
-
# See diagnose_raw_prediction_diff.py for derivation.
|
|
73
|
+
# NOTE: With the fix to include zeros in cutoff calculation (matching C++),
|
|
74
|
+
# most overrides are no longer needed. Only keep AU26_r which has unusual behavior.
|
|
73
75
|
'cutoff_overrides': {
|
|
74
|
-
'AU20_r': 0.40, # Original: 0.65 -> 0.9729 correlation (PASS)
|
|
75
76
|
'AU26_r': 0.12, # Original: 0.30 -> 0.9317 correlation (best achievable)
|
|
76
77
|
},
|
|
77
78
|
}
|
|
@@ -130,6 +130,72 @@ class TrainingDataGenerator:
|
|
|
130
130
|
# pyfhog 0.1.4+ outputs in OpenFace-compatible format (4464,)
|
|
131
131
|
return hog.astype(np.float32)
|
|
132
132
|
|
|
133
|
+
def _crop_and_align_bbox(
|
|
134
|
+
self,
|
|
135
|
+
image: np.ndarray,
|
|
136
|
+
bbox: np.ndarray
|
|
137
|
+
) -> tuple:
|
|
138
|
+
"""
|
|
139
|
+
Crop face from image using bbox (matching NNCLNF inference alignment).
|
|
140
|
+
|
|
141
|
+
This creates the SAME alignment that NNCLNF uses at inference time,
|
|
142
|
+
ensuring training and inference see the same type of crops.
|
|
143
|
+
|
|
144
|
+
Args:
|
|
145
|
+
image: BGR image
|
|
146
|
+
bbox: Face bounding box [x, y, width, height]
|
|
147
|
+
|
|
148
|
+
Returns:
|
|
149
|
+
aligned_face: 112x112 BGR face image
|
|
150
|
+
warp_matrix: 2x3 affine transform matrix (for landmark transformation)
|
|
151
|
+
"""
|
|
152
|
+
bbox_x, bbox_y, bbox_w, bbox_h = bbox
|
|
153
|
+
|
|
154
|
+
# Apply PyMTCNN bbox correction (matching NNCLNF)
|
|
155
|
+
bbox_x = bbox_x + bbox_w * 0.0625
|
|
156
|
+
bbox_y = bbox_y + bbox_h * 0.0625
|
|
157
|
+
bbox_w = bbox_w * 0.875
|
|
158
|
+
bbox_h = bbox_h * 0.875
|
|
159
|
+
|
|
160
|
+
size = max(bbox_w, bbox_h)
|
|
161
|
+
center_x = bbox_x + bbox_w / 2
|
|
162
|
+
center_y = bbox_y + bbox_h / 2
|
|
163
|
+
|
|
164
|
+
# Y offset correction (matching NNCLNF inference)
|
|
165
|
+
center_y -= size * 0.12
|
|
166
|
+
|
|
167
|
+
# Add padding (10% on each side)
|
|
168
|
+
padding = 0.1
|
|
169
|
+
size_with_pad = size * (1 + 2 * padding)
|
|
170
|
+
|
|
171
|
+
x1 = center_x - size_with_pad / 2
|
|
172
|
+
y1 = center_y - size_with_pad / 2
|
|
173
|
+
x2 = center_x + size_with_pad / 2
|
|
174
|
+
y2 = center_y + size_with_pad / 2
|
|
175
|
+
|
|
176
|
+
src_pts = np.array([
|
|
177
|
+
[x1, y1],
|
|
178
|
+
[x2, y1],
|
|
179
|
+
[x2, y2],
|
|
180
|
+
], dtype=np.float32)
|
|
181
|
+
|
|
182
|
+
dst_pts = np.array([
|
|
183
|
+
[0, 0],
|
|
184
|
+
[112, 0],
|
|
185
|
+
[112, 112],
|
|
186
|
+
], dtype=np.float32)
|
|
187
|
+
|
|
188
|
+
M = cv2.getAffineTransform(src_pts, dst_pts)
|
|
189
|
+
|
|
190
|
+
aligned_face = cv2.warpAffine(
|
|
191
|
+
image, M, (112, 112),
|
|
192
|
+
flags=cv2.INTER_LINEAR,
|
|
193
|
+
borderMode=cv2.BORDER_CONSTANT,
|
|
194
|
+
borderValue=(0, 0, 0)
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
return aligned_face, M
|
|
198
|
+
|
|
133
199
|
def _predict_aus(self, hog_features: np.ndarray, geom_features: np.ndarray) -> np.ndarray:
|
|
134
200
|
"""Predict AU intensities from features."""
|
|
135
201
|
full_vector = np.concatenate([hog_features, geom_features])
|
|
@@ -213,18 +279,10 @@ class TrainingDataGenerator:
|
|
|
213
279
|
print(f" [DEBUG] CalcParams error: {e}")
|
|
214
280
|
return None
|
|
215
281
|
|
|
216
|
-
# Face alignment -
|
|
282
|
+
# Face alignment - use bbox-based alignment (matching NNCLNF inference)
|
|
283
|
+
# This ensures training and inference use the SAME alignment approach
|
|
217
284
|
try:
|
|
218
|
-
|
|
219
|
-
aligned_face, warp_matrix = self._face_aligner.align_face_with_matrix(
|
|
220
|
-
image=frame,
|
|
221
|
-
landmarks_68=landmarks,
|
|
222
|
-
pose_tx=tx,
|
|
223
|
-
pose_ty=ty,
|
|
224
|
-
p_rz=rz,
|
|
225
|
-
apply_mask=True,
|
|
226
|
-
triangulation=self._triangulation
|
|
227
|
-
)
|
|
285
|
+
aligned_face, warp_matrix = self._crop_and_align_bbox(frame, bbox)
|
|
228
286
|
except Exception as e:
|
|
229
287
|
if self.config.verbose:
|
|
230
288
|
print(f" [DEBUG] Face alignment error: {e}")
|
|
@@ -217,7 +217,8 @@ class ParallelAUPipeline:
|
|
|
217
217
|
geom_features = frame_features['geom_features']
|
|
218
218
|
|
|
219
219
|
# Update running median (must be sequential)
|
|
220
|
-
|
|
220
|
+
# C++ increments frames_tracking BEFORE check, update on even frames
|
|
221
|
+
update_histogram = (idx % 2 == 0)
|
|
221
222
|
self.main_pipeline.running_median.update(
|
|
222
223
|
hog_features,
|
|
223
224
|
geom_features,
|
|
@@ -44,7 +44,7 @@ from pyfaceau.refinement.targeted_refiner import TargetedCLNFRefiner
|
|
|
44
44
|
|
|
45
45
|
# Import Cython-optimized running median (with fallback)
|
|
46
46
|
try:
|
|
47
|
-
from cython_histogram_median import DualHistogramMedianTrackerCython as DualHistogramMedianTracker
|
|
47
|
+
from pyfaceau.cython_histogram_median import DualHistogramMedianTrackerCython as DualHistogramMedianTracker
|
|
48
48
|
USING_CYTHON = True
|
|
49
49
|
except ImportError:
|
|
50
50
|
from pyfaceau.features.histogram_median_tracker import DualHistogramMedianTracker
|
|
@@ -57,6 +57,9 @@ try:
|
|
|
57
57
|
except ImportError:
|
|
58
58
|
USING_BATCHED_PREDICTOR = False
|
|
59
59
|
|
|
60
|
+
# NNCLNF (neural network replacement for CLNF) is defunct and archived
|
|
61
|
+
# Use pyclnf with GPU acceleration instead for best accuracy + speed
|
|
62
|
+
|
|
60
63
|
# Import online AU correction (C++ CorrectOnlineAUs equivalent)
|
|
61
64
|
from pyfaceau.prediction.online_au_correction import OnlineAUCorrection
|
|
62
65
|
|
|
@@ -191,6 +194,7 @@ class FullPythonAUPipeline:
|
|
|
191
194
|
use_calc_params: bool = True,
|
|
192
195
|
track_faces: bool = True,
|
|
193
196
|
use_batched_predictor: bool = True,
|
|
197
|
+
use_nnclnf: str = 'pyclnf', # NNCLNF is defunct, always use pyclnf
|
|
194
198
|
max_clnf_iterations: int = CLNF_CONFIG['max_iterations'],
|
|
195
199
|
clnf_convergence_threshold: float = CLNF_CONFIG['convergence_threshold'],
|
|
196
200
|
debug_mode: bool = False,
|
|
@@ -199,7 +203,7 @@ class FullPythonAUPipeline:
|
|
|
199
203
|
"""
|
|
200
204
|
Initialize the full Python AU pipeline (OpenFace-compatible)
|
|
201
205
|
|
|
202
|
-
Architecture: PyMTCNN → CLNF → AU Prediction
|
|
206
|
+
Architecture: PyMTCNN → pyclnf CLNF → AU Prediction
|
|
203
207
|
(matches OpenFace C++ 2.2 pipeline)
|
|
204
208
|
|
|
205
209
|
Args:
|
|
@@ -211,6 +215,7 @@ class FullPythonAUPipeline:
|
|
|
211
215
|
use_calc_params: DEPRECATED - pyclnf params are now used instead (default: True)
|
|
212
216
|
track_faces: Use face tracking between frames (default: True)
|
|
213
217
|
use_batched_predictor: Use optimized batched AU predictor (default: True)
|
|
218
|
+
use_nnclnf: DEPRECATED - always uses pyclnf (NNCLNF is defunct)
|
|
214
219
|
max_clnf_iterations: Maximum CLNF optimization iterations (default: 10)
|
|
215
220
|
clnf_convergence_threshold: CLNF convergence threshold in pixels (default: 0.01)
|
|
216
221
|
debug_mode: Enable debug mode for diagnostics (default: False)
|
|
@@ -236,6 +241,7 @@ class FullPythonAUPipeline:
|
|
|
236
241
|
'au_models_dir': au_models_dir,
|
|
237
242
|
'triangulation_file': triangulation_file,
|
|
238
243
|
'patch_expert_file': patch_expert_file,
|
|
244
|
+
'use_nnclnf': use_nnclnf,
|
|
239
245
|
'max_clnf_iterations': max_clnf_iterations,
|
|
240
246
|
'clnf_convergence_threshold': clnf_convergence_threshold,
|
|
241
247
|
}
|
|
@@ -317,11 +323,12 @@ class FullPythonAUPipeline:
|
|
|
317
323
|
print(f" Active backend: {backend_info}")
|
|
318
324
|
print("Face detector loaded\n")
|
|
319
325
|
|
|
320
|
-
# Component 2: Landmark Detection (CLNF
|
|
326
|
+
# Component 2: Landmark Detection (pyclnf CLNF with GPU acceleration)
|
|
321
327
|
if self.verbose:
|
|
322
328
|
print("[2/8] Loading CLNF landmark detector (pyclnf)...")
|
|
323
329
|
print(f" Max iterations: {max_clnf_iterations}")
|
|
324
330
|
print(f" Convergence threshold: {clnf_convergence_threshold} pixels")
|
|
331
|
+
print(f" GPU enabled: {CLNF_CONFIG.get('use_gpu', False)}")
|
|
325
332
|
|
|
326
333
|
# Lazy import to avoid circular import (pyfaceau ↔ pyclnf)
|
|
327
334
|
from pyclnf import CLNF
|
|
@@ -333,8 +340,12 @@ class FullPythonAUPipeline:
|
|
|
333
340
|
detector=CLNF_CONFIG['detector'], # Disable built-in PyMTCNN (pyfaceau handles detection)
|
|
334
341
|
use_eye_refinement=CLNF_CONFIG['use_eye_refinement'], # Enable hierarchical eye model refinement
|
|
335
342
|
convergence_profile=CLNF_CONFIG['convergence_profile'], # Enable video mode with template tracking + scale adaptation
|
|
336
|
-
sigma=CLNF_CONFIG['sigma'] # KDE kernel sigma matching C++ CECLM
|
|
343
|
+
sigma=CLNF_CONFIG['sigma'], # KDE kernel sigma matching C++ CECLM
|
|
344
|
+
use_gpu=CLNF_CONFIG.get('use_gpu', False), # GPU acceleration (10-20x speedup)
|
|
345
|
+
gpu_device=CLNF_CONFIG.get('gpu_device', 'auto'), # GPU device selection
|
|
346
|
+
use_validator=CLNF_CONFIG.get('use_validator', True) # Detection validator (disabled for speed)
|
|
337
347
|
)
|
|
348
|
+
|
|
338
349
|
if self.verbose:
|
|
339
350
|
print(f"CLNF detector loaded\n")
|
|
340
351
|
|
|
@@ -429,6 +440,18 @@ class FullPythonAUPipeline:
|
|
|
429
440
|
|
|
430
441
|
self._components_initialized = True
|
|
431
442
|
|
|
443
|
+
@property
|
|
444
|
+
def using_nnclnf(self) -> bool:
|
|
445
|
+
"""DEPRECATED: NNCLNF is defunct, always returns False."""
|
|
446
|
+
return False
|
|
447
|
+
|
|
448
|
+
@property
|
|
449
|
+
def landmark_detector_name(self) -> str:
|
|
450
|
+
"""Get the name of the landmark detector being used."""
|
|
451
|
+
if not self._components_initialized:
|
|
452
|
+
return "not initialized"
|
|
453
|
+
return "pyclnf"
|
|
454
|
+
|
|
432
455
|
def _initialize_landmarks_from_bbox(self, bbox):
|
|
433
456
|
"""
|
|
434
457
|
Initialize 2D landmarks from PDM mean shape scaled to fit bbox.
|
|
@@ -893,7 +916,9 @@ class FullPythonAUPipeline:
|
|
|
893
916
|
t0 = time.time() if debug_info is not None else None
|
|
894
917
|
if self.verbose and frame_idx < 3:
|
|
895
918
|
print(f"[Frame {frame_idx}] Step 7: Updating running median...")
|
|
896
|
-
|
|
919
|
+
# C++ increments frames_tracking BEFORE the check, so frame 0 → counter=1 → update
|
|
920
|
+
# To match: update on frames 0, 2, 4, 6... (even frames)
|
|
921
|
+
update_histogram = (frame_idx % 2 == 0) # Match C++ timing
|
|
897
922
|
self.running_median.update(hog_features, geom_features, update_histogram=update_histogram)
|
|
898
923
|
running_median = self.running_median.get_combined_median()
|
|
899
924
|
if self.verbose and frame_idx < 3:
|
|
@@ -1089,10 +1114,16 @@ class FullPythonAUPipeline:
|
|
|
1089
1114
|
if model_cutoff <= 0 or model_cutoff >= 1.0:
|
|
1090
1115
|
continue
|
|
1091
1116
|
|
|
1092
|
-
#
|
|
1093
|
-
# C++ FaceAnalyser.cpp
|
|
1117
|
+
# Match C++ - include ALL values from successful frames
|
|
1118
|
+
# C++ FaceAnalyser.cpp uses au_good which includes all values from frames
|
|
1119
|
+
# where successes[frame]==true, INCLUDING zeros
|
|
1094
1120
|
au_values = df[au_col].values
|
|
1095
|
-
|
|
1121
|
+
|
|
1122
|
+
# Filter by success flag if available, otherwise use all non-NaN values
|
|
1123
|
+
if 'success' in df.columns:
|
|
1124
|
+
valid_mask = df['success'].values == 1
|
|
1125
|
+
else:
|
|
1126
|
+
valid_mask = ~np.isnan(au_values)
|
|
1096
1127
|
valid_vals = au_values[valid_mask]
|
|
1097
1128
|
|
|
1098
1129
|
# Need enough valid values to compute meaningful percentile
|
|
@@ -302,7 +302,8 @@ class OpenFace22AUPredictor:
|
|
|
302
302
|
geom_feat = self._extract_geometric_features(csv_data.iloc[i])
|
|
303
303
|
|
|
304
304
|
# Update tracker (every 2nd frame)
|
|
305
|
-
|
|
305
|
+
# C++ increments frames_tracking BEFORE check, update on even frames
|
|
306
|
+
update_histogram = (i % 2 == 0)
|
|
306
307
|
median_tracker.update(hog_feat, geom_feat, update_histogram=update_histogram)
|
|
307
308
|
|
|
308
309
|
# Store running median
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/utils/cython_extensions/cython_histogram_median.pyx
RENAMED
|
File without changes
|
{pyfaceau-1.3.3 → pyfaceau-1.3.4}/pyfaceau/utils/cython_extensions/cython_rotation_update.pyx
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|