{"record":{"id":"0a0cbf941bf744c8","repo":"deepfakes/faceswap","slug":"68-point-facial-landmarks-are-required-for-warp-to","errorCode":null,"errorMessage":"68 Point facial Landmarks are required for Warp-to-landmarks. The face that failed was: '{filename}'","messagePattern":"68 Point facial Landmarks are required for Warp-to-landmarks\\. The face that failed was: '(.+?)'","errorType":"exception","errorClass":"FaceswapError","httpStatus":null,"severity":"error","filePath":"lib/training/data/collate.py","lineNumber":167,"sourceCode":"\n        Returns\n        -------\n        landmarks\n            The frame space landmarks for a face\n        filename\n            The name of the face image that we are loading landmarks for\n\n        Raises\n        ------\n        FaceswapError\n            If an invalid image is loaded or 68 point landmarks are not used\n        \"\"\"\n        if \"itxt\" not in meta or \"alignments\" not in meta[\"itxt\"]:\n            raise FaceswapError(f\"Invalid face image found. Aborting: '{filename}'\")\n\n        retval = np.array(meta[\"itxt\"][\"alignments\"][\"landmarks_xy\"], dtype=np.float32)\n        if LandmarkType.from_shape(retval.shape) != LandmarkType.LM_2D_68:\n            raise FaceswapError(\"68 Point facial Landmarks are required for Warp-to-\"\n                                f\"landmarks. The face that failed was: '{filename}'\")\n        return retval\n\n    def _align_points(self, points: npt.NDArray[np.float32]) -> npt.NDArray[np.float32]:\n        \"\"\"Normalize and align the landmarks to model input size/coverage/offset\n\n        points\n        ------\n        The (N, 68, 2) landmark points to align\n\n        Returns\n        -------\n        The landmark points aligned to model input\n        \"\"\"\n        mats = batch_umeyama(points[:, 17:], MEAN_FACE[LandmarkType.LM_2D_51], True)\n        norm_lms = batch_transform(mats, points)\n\n        rotation, translation = Batch3D.solve_pnp(norm_lms)","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/deepfakes/faceswap/blob/f530cb7508ae670f6474f8a7d9c4df94705cf96b/lib/training/data/collate.py#L149-L185","documentation":"Warp-to-landmarks requires exactly 68-point 2D landmarks; after loading landmarks_xy from the face's embedded metadata, the shape is checked via LandmarkType.from_shape. Faces produced by landmark models with different point counts (e.g. 81-point or mask-extended outputs) fail this check with the offending filename.","triggerScenarios":"Training warp-to-landmarks on faces extracted with a non-68-point landmark plugin or converted alignments from another pipeline; mixed datasets where some faces carry different landmark formats.","commonSituations":"Changing detector/aligner settings between extraction and training; importing alignments from external tools; faceswap versions with alternate landmark output.","solutions":["Re-extract faces with the default 68-point aligner before warp-to-landmarks training.","Remove non-conforming faces (named in the error) from the training set.","Or switch the trainer's mask/warp method that does not require warp-to-landmarks."],"exampleFix":"# before: faces extracted with non-68pt landmarks\n# FaceswapError: 68 Point facial Landmarks are required...\n\n# after: regenerate dataset with standard aligner\n$ python faceswap.py extract -i /frames -o /faces -df s3fd -af fan","handlingStrategy":"validation","validationCode":"from lib.image import read_image_meta\nfrom lib.align.alignments import LandmarkType\nimport numpy as np\n\nmeta = read_image_meta(face_path)\nlm = np.array(meta['itxt']['alignments']['landmarks_xy'])\nassert LandmarkType.from_shape(lm.shape) == LandmarkType.LM_2D_68, \\\n    f'{face_path} does not have 68-point landmarks'","typeGuard":"def has_68_landmarks(face_path: str) -> bool:\n    meta = read_image_meta(face_path)\n    lm = np.array(meta['itxt']['alignments']['landmarks_xy'])\n    return lm.shape[-2:] == (68, 2)","tryCatchPattern":"try:\n    train(warp_to_landmarks=True)\nexcept FaceswapError as err:\n    if '68 Point' in str(err):\n        drop_named_file_and_reindex_dataset()\n    else:\n        raise","preventionTips":["Extract with the default 68-point aligner when warp-to-landmarks is planned.","Do not mix alignments from different landmark models in one dataset.","Check landmark shapes at dataset load time, not mid-epoch."],"tags":["training","landmarks","alignments","dataset"],"backgroundTag":null,"analyzedSha":"f530cb7508ae670f6474f8a7d9c4df94705cf96b","analyzedAt":"2026-08-15T02:59:26.626Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}