deepfakes/faceswap · error · FaceswapError
Spatial smoothing only supports 68 point facial landmarks
Error message
Spatial smoothing only supports 68 point facial landmarks
What it means
The Alignments tool's 'spatial' smoothing method builds a (68, 2, N) landmark tensor, so it hard-requires 68-point landmarks. It samples the first aligned face in the file; if that landmark array's first dimension is not 68 (e.g. 4-point 2D landmarks from some detectors/masks), it aborts.
Source
Thrown at tools/alignments/jobs.py:610
# move back to the correct scale
shapes_centered = shapes_normalized * np.tile(scale_factors, [num_pts, num_dims, 1])
# move back to the correct location
shapes_im_coords = shapes_centered + np.tile(mean_coords, [num_pts, 1, 1])
logger.debug("Normalized to original: %s", shapes_im_coords)
return shapes_im_coords
def _normalize(self) -> None:
"""Compile all original and normalized alignments"""
logger.debug("Normalize")
count = sum(1 for val in self._alignments.data.values() if val.faces)
sample_lm = next((val.faces[0].landmarks_xy
for val in self._alignments.data.values() if val.faces), 68)
assert isinstance(sample_lm, np.ndarray)
lm_count = sample_lm.shape[0]
if lm_count != 68:
raise FaceswapError("Spatial smoothing only supports 68 point facial landmarks")
landmarks_all = np.zeros((lm_count, 2, int(count)))
end = 0
for key in tqdm(sorted(self._alignments.data.keys()), desc="Compiling", leave=False):
val = self._alignments.data[key].faces
if not val:
continue
# We should only be normalizing a single face, so just take
# the first landmarks found
landmarks = np.array(val[0].landmarks_xy).reshape((lm_count, 2, 1))
start = end
end = start + landmarks.shape[2]
# Store in one big array
landmarks_all[:, :, start:end] = landmarks
# Make sure we keep track of the mapping to the original frame
self._mappings[start] = key
View on GitHub (pinned to f530cb7508)
Solutions
- Re-extract the faces with a 68-point landmark configuration (standard FAN/dlib S3FD pipeline) so alignments contain 68-point landmarks, then retry spatial smoothing.
- Or use a smoothing method that does not depend on landmark count (e.g. temporal smoothing) if it fits your use case.
- Inspect the alignments file to confirm landmark shape before choosing the tool job.
Example fix
# before python tools.py alignments -j spatial -a alignments.fsa # faces have 4-point landmarks -> FaceswapError # after # re-extract with 68-point landmarks, then: python tools.py alignments -j spatial -a alignments.fsa
Defensive patterns
Strategy: validation
Validate before calling
import numpy as np
def landmarks_are_68(alignments_file: str) -> bool:
from lib.align import Alignments
al = Alignments(alignments_file)
face = next(v.faces[0] for v in al.data.values() if v.faces)
return np.asarray(face.landmarks_xy).shape[0] == 68 Prevention
- Before running -j spatial, sample one face from the alignments and assert 68 landmark rows.
- Standardize extraction settings across the project so landmark counts are uniform.
When it happens
Trigger: Running `python tools.py alignments -j spatial` on an alignments file whose faces were extracted with a landmark set other than 68-point (e.g. LM_2D_4 produced by certain mask/detector configurations), or where the first face's stored landmarks array has a different row count.
Common situations: Alignments produced with newer extraction defaults that store 4-point landmarks for some faces; mixing alignments files from different detector versions; legacy files converted from 81-point formats.
Related errors
- The images to be sorted do not contain alignment data. Image
- Landmark based masks cannot be created for {self._landmark_t
- There is a mismatch between the number of frames found in th
- Alignments file not found at {self._file}
- The given shape {shape} is not valid. Valid shapes: {list(sh
AI-assisted analysis of deepfakes/faceswap@f530cb7508 (2026-08-15).
Data as JSON: /api/errors/6ff1858b3daea088.
Report an issue: GitHub.