lllyasviel/Fooocus · error · FaceWarpException
facial_pts.shape must be (K,2) or (2,K) and K>2
Error message
facial_pts.shape must be (K,2) or (2,K) and K>2
What it means
The mirror of the reference-points check: the detected facial_pts (source landmarks) must be shape (K,2) or (2,K) with K>2 so at least three 2-D correspondences exist for transform estimation. Malformed landmark arrays raise FaceWarpException before cv2/warpAffine run.
Source
Thrown at extras/facexlib/detection/align_trans.py:202
inner_padding_factor = 0
outer_padding = (0, 0)
output_size = crop_size
reference_pts = get_reference_facial_points(output_size, inner_padding_factor, outer_padding,
default_square)
ref_pts = np.float32(reference_pts)
ref_pts_shp = ref_pts.shape
if max(ref_pts_shp) < 3 or min(ref_pts_shp) != 2:
raise FaceWarpException('reference_pts.shape must be (K,2) or (2,K) and K>2')
if ref_pts_shp[0] == 2:
ref_pts = ref_pts.T
src_pts = np.float32(facial_pts)
src_pts_shp = src_pts.shape
if max(src_pts_shp) < 3 or min(src_pts_shp) != 2:
raise FaceWarpException('facial_pts.shape must be (K,2) or (2,K) and K>2')
if src_pts_shp[0] == 2:
src_pts = src_pts.T
if src_pts.shape != ref_pts.shape:
raise FaceWarpException('facial_pts and reference_pts must have the same shape')
if align_type == 'cv2_affine':
tfm = cv2.getAffineTransform(src_pts[0:3], ref_pts[0:3])
elif align_type == 'affine':
tfm = get_affine_transform_matrix(src_pts, ref_pts)
else:
tfm = get_similarity_transform_for_cv2(src_pts, ref_pts)
face_img = cv2.warpAffine(src_img, tfm, (crop_size[0], crop_size[1]))
return face_img
View on GitHub (pinned to ae05379cc9)
Solutions
- Reshape the landmarks to (5,2): np.asarray(pts, dtype=np.float32).reshape(-1,2)
- Drop any third column: pts = pts[:, :2]
- Check the detector returns 5 facial landmarks (eyes, nose, mouth corners) as expected by this alignment API
Example fix
// before face_img = warp_and_crop_face(img, landmarks.ravel()) // after face_img = warp_and_crop_face(img, np.asarray(landmarks, dtype=np.float32).reshape(5,2))
Defensive patterns
Strategy: type-guard
Validate before calling
import numpy as np
src = np.asarray(facial_pts, dtype=np.float32)
assert src.ndim == 2 and min(src.shape) == 2 and max(src.shape) >= 3, \
'facial_pts must be (K,2)/(2,K) with K>2'
if src.shape[0] == 2:
src = src.T Type guard
def is_valid_landmarks(pts) -> bool:
import numpy as np
a = np.asarray(pts)
return a.ndim == 2 and min(a.shape) == 2 and max(a.shape) >= 3 Prevention
- Reshape detector output to (5,2) immediately after detection
- Pin the detector's landmark format in a wrapper function
- Drop extra columns (K,3 -> K,2) before alignment
When it happens
Trigger: Passing the detector's raw output without reshaping (flat 10-vector for 5 landmarks), a single point, an empty array, or landmarks with a third coordinate column (K,3).
Common situations: Detector API changes (different landmark layout); passing bounding-box corners instead of landmarks; landmarks stored as dict values iterated incorrectly.
Related errors
- reference_pts.shape must be (K,2) or (2,K) and K>2
- facial_pts and reference_pts must have the same shape
- cp2tform:twoUniquePointsReq
- No paddings to do, output_size must be None or {}
- Not (0 <= inner_padding_factor <= 1.0)
AI-assisted analysis of lllyasviel/Fooocus@ae05379cc9 (2026-08-15).
Data as JSON: /api/errors/9f55719c83fc95b1.
Report an issue: GitHub.