lllyasviel/Fooocus · error · Exception
cp2tform:twoUniquePointsReq
Error message
cp2tform:twoUniquePointsReq
What it means
In findNonreflectiveTransform (MATLAB cp2tform port), a similarity transform is solved from point correspondences via least squares; the system matrix X must have rank >= 2K (K=2 here, so rank >= 4), which requires the points to contain at least two distinct points. If all source points coincide (or are collinear in the degenerate sense that drops rank), the system is underdetermined and this Exception is raised.
Source
Thrown at extras/facexlib/detection/matlab_cp2tform.py:81
K = options['K']
M = xy.shape[0]
x = xy[:, 0].reshape((-1, 1)) # use reshape to keep a column vector
y = xy[:, 1].reshape((-1, 1)) # use reshape to keep a column vector
tmp1 = np.hstack((x, y, np.ones((M, 1)), np.zeros((M, 1))))
tmp2 = np.hstack((y, -x, np.zeros((M, 1)), np.ones((M, 1))))
X = np.vstack((tmp1, tmp2))
u = uv[:, 0].reshape((-1, 1)) # use reshape to keep a column vector
v = uv[:, 1].reshape((-1, 1)) # use reshape to keep a column vector
U = np.vstack((u, v))
# We know that X * r = U
if rank(X) >= 2 * K:
r, _, _, _ = lstsq(X, U, rcond=-1)
r = np.squeeze(r)
else:
raise Exception('cp2tform:twoUniquePointsReq')
sc = r[0]
ss = r[1]
tx = r[2]
ty = r[3]
Tinv = np.array([[sc, -ss, 0], [ss, sc, 0], [tx, ty, 1]])
T = inv(Tinv)
T[:, 2] = np.array([0, 0, 1])
return T, Tinv
def findSimilarity(uv, xy, options=None):
options = {'K': 2}
# uv = np.array(uv)
# xy = np.array(xy)
View on GitHub (pinned to ae05379cc9)
Solutions
- Validate landmarks before transform estimation: at least 2 unique points, e.g. len(np.unique(pts, axis=0)) >= 2
- Filter out detections with degenerate landmark sets (all-identical or zero coordinates) and skip/retry that frame
- Fix the upstream detector/parsing step if it emits repeated points
Example fix
// before
tfm = get_similarity_transform_for_cv2(src_pts, ref_pts) # src_pts all identical
// after
if len(np.unique(np.round(src_pts, 4), axis=0)) < 2:
raise ValueError('degenerate landmarks: need >=2 unique points')
tfm = get_similarity_transform_for_cv2(src_pts, ref_pts) Defensive patterns
Strategy: validation
Validate before calling
import numpy as np
def has_two_unique_points(pts, tol=4):
a = np.asarray(pts, dtype=np.float64)
return a.ndim == 2 and len(np.unique(np.round(a, tol), axis=0)) >= 2 Try / catch
try:
tfm = get_similarity_transform_for_cv2(src, ref)
except Exception as e:
if 'twoUniquePointsReq' in str(e):
handle_degenerate_detection() # skip frame / re-detect
else:
raise Prevention
- Filter degenerate detections (zero or repeated landmarks) before alignment
- Check detection score thresholds so garbage landmarks never reach cp2tform
- Round-check uniqueness with a small tolerance to catch float-duplicated points
When it happens
Trigger: Estimating a similarity transform where all src_pts are the same coordinate (detector returned garbage/zero landmarks), or fewer than 2 unique points were passed — the stacked linear system cannot determine sc, ss, tx, ty.
Common situations: Face detector confidence failure returning zeros or repeated points; landmark parsing bug filling every row with the same point; passing an empty/duplicated array into get_similarity_transform.
Related errors
- reference_pts.shape must be (K,2) or (2,K) and K>2
- facial_pts.shape must be (K,2) or (2,K) and K>2
- facial_pts and reference_pts must have the same shape
- 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/aa8fcbd45a047f3a.
Report an issue: GitHub.