{"record":{"id":"aa8fcbd45a047f3a","repo":"lllyasviel/Fooocus","slug":"cp2tform-twouniquepointsreq","errorCode":null,"errorMessage":"cp2tform:twoUniquePointsReq","messagePattern":"cp2tform:twoUniquePointsReq","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"extras/facexlib/detection/matlab_cp2tform.py","lineNumber":81,"sourceCode":"    K = options['K']\n    M = xy.shape[0]\n    x = xy[:, 0].reshape((-1, 1))  # use reshape to keep a column vector\n    y = xy[:, 1].reshape((-1, 1))  # use reshape to keep a column vector\n\n    tmp1 = np.hstack((x, y, np.ones((M, 1)), np.zeros((M, 1))))\n    tmp2 = np.hstack((y, -x, np.zeros((M, 1)), np.ones((M, 1))))\n    X = np.vstack((tmp1, tmp2))\n\n    u = uv[:, 0].reshape((-1, 1))  # use reshape to keep a column vector\n    v = uv[:, 1].reshape((-1, 1))  # use reshape to keep a column vector\n    U = np.vstack((u, v))\n\n    # We know that X * r = U\n    if rank(X) >= 2 * K:\n        r, _, _, _ = lstsq(X, U, rcond=-1)\n        r = np.squeeze(r)\n    else:\n        raise Exception('cp2tform:twoUniquePointsReq')\n    sc = r[0]\n    ss = r[1]\n    tx = r[2]\n    ty = r[3]\n\n    Tinv = np.array([[sc, -ss, 0], [ss, sc, 0], [tx, ty, 1]])\n    T = inv(Tinv)\n    T[:, 2] = np.array([0, 0, 1])\n\n    return T, Tinv\n\n\ndef findSimilarity(uv, xy, options=None):\n    options = {'K': 2}\n\n    #    uv = np.array(uv)\n    #    xy = np.array(xy)\n","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/lllyasviel/Fooocus/blob/ae05379cc97bc4361ec8b4ec90193dab21be763f/extras/facexlib/detection/matlab_cp2tform.py#L63-L99","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\ntfm = get_similarity_transform_for_cv2(src_pts, ref_pts)  # src_pts all identical\n\n// after\nif len(np.unique(np.round(src_pts, 4), axis=0)) < 2:\n    raise ValueError('degenerate landmarks: need >=2 unique points')\ntfm = get_similarity_transform_for_cv2(src_pts, ref_pts)","handlingStrategy":"validation","validationCode":"import numpy as np\ndef has_two_unique_points(pts, tol=4):\n    a = np.asarray(pts, dtype=np.float64)\n    return a.ndim == 2 and len(np.unique(np.round(a, tol), axis=0)) >= 2","typeGuard":null,"tryCatchPattern":"try:\n    tfm = get_similarity_transform_for_cv2(src, ref)\nexcept Exception as e:\n    if 'twoUniquePointsReq' in str(e):\n        handle_degenerate_detection()  # skip frame / re-detect\n    else:\n        raise","preventionTips":["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"],"tags":["facexlib","face-alignment","linear-algebra","degenerate-input","landmarks"],"backgroundTag":null,"analyzedSha":"ae05379cc97bc4361ec8b4ec90193dab21be763f","analyzedAt":"2026-08-15T04:23:59.533Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}