{"record":{"id":"c2a446b22dd88fb0","repo":"SixLabors/ImageSharp","slug":"matrix-is-singular-and-cannot-be-solve","errorCode":null,"errorMessage":"Matrix is singular and cannot be solve","messagePattern":"Matrix is singular and cannot be solve","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"src/ImageSharp/Processing/Processors/Transforms/Linear/GaussianEliminationSolver.cs","lineNumber":50,"sourceCode":"        int rowCount = matrix[0].Length;\n        int pivotRow = 0;\n        for (int pivotCol = 0; pivotCol < colCount; pivotCol++)\n        {\n            double maxValue = double.Abs(matrix[pivotRow][pivotCol]);\n            int maxIndex = pivotRow;\n            for (int r = pivotRow + 1; r < rowCount; r++)\n            {\n                double value = double.Abs(matrix[r][pivotCol]);\n                if (value > maxValue)\n                {\n                    maxIndex = r;\n                    maxValue = value;\n                }\n            }\n\n            if (matrix[maxIndex][pivotCol] == 0)\n            {\n                throw new NotSupportedException(\"Matrix is singular and cannot be solve\");\n            }\n\n            (matrix[pivotRow], matrix[maxIndex]) = (matrix[maxIndex], matrix[pivotRow]);\n            (result[pivotRow], result[maxIndex]) = (result[maxIndex], result[pivotRow]);\n\n            for (int r = pivotRow + 1; r < rowCount; r++)\n            {\n                double fraction = matrix[r][pivotCol] / matrix[pivotRow][pivotCol];\n                for (int c = pivotCol + 1; c < colCount; c++)\n                {\n                    matrix[r][c] -= matrix[pivotRow][c] * fraction;\n                }\n\n                result[r] -= result[pivotRow] * fraction;\n                matrix[r][pivotCol] = 0;\n            }\n\n            pivotRow++;","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/SixLabors/ImageSharp/blob/59ce6af6fc29027cda277ef62d4d1694a8acce91/src/ImageSharp/Processing/Processors/Transforms/Linear/GaussianEliminationSolver.cs#L32-L68","documentation":"GaussianEliminationSolver.TransformToRowEchelonForm solves linear systems via Gaussian elimination; if it cannot find a nonzero pivot in a column, the matrix is singular and the system has no unique solution. Since NotSupportedException conveys 'this operation cannot proceed', the solver aborts rather than returning garbage.","triggerScenarios":"Calling Solve (used by ProjectiveTransformBuilder to derive projective matrices from point correspondences) with degenerate/ collinear control points so the elimination hits a zero pivot column.","commonSituations":"Using ProjectiveTransformBuilder with 4 coplanar/collinear source points; supplying duplicate destination points; computing transforms from auto-detected corner points that are degenerate (e.g. straight-line feature matches).","solutions":["Provide 4 non-degenerate (non-collinear, distinct) source/destination point pairs","Deduplicate and validate control points before building the transform","Catch NotSupportedException from Solve and fall back to an affine transform, which needs fewer points","If points come from feature detection, apply an epsilon check on the area of the quad formed by the points"],"exampleFix":"// before\nvar matrix = ProjectiveTransformBuilder.DefineQuad(sourcePoints, destPoints); // collinear points\n// after\nstatic bool IsValidQuad(PointF[] p) =>\n    Math.Abs(((p[1].X - p[0].X) * (p[2].Y - p[0].Y)) - ((p[2].X - p[0].X) * (p[1].Y - p[0].Y))) > float.Epsilon;\nif (!IsValidQuad(sourcePoints) || !IsValidQuad(destPoints))\n{\n    throw new InvalidOperationException(\"Projective transform requires non-collinear points.\");\n}\nvar matrix = ProjectiveTransformBuilder.DefineQuad(sourcePoints, destPoints);","handlingStrategy":"validation","validationCode":"static float QuadArea(PointF a, PointF b, PointF c, PointF d) =>\n    MathF.Abs((b.X - a.X) * (c.Y - a.Y) - (c.X - a.X) * (b.Y - a.Y))\n  + MathF.Abs((c.X - a.X) * (d.Y - a.Y) - (d.X - a.X) * (c.Y - a.Y));\nif (QuadArea(p0, p1, p2, p3) < 1e-3f) throw new InvalidOperationException(\"Points are degenerate/collinear.\");","typeGuard":"static bool ArePointsDistinctAndNonCollinear(PointF[] pts) =>\n    pts.Length == 4\n    && pts.Distinct().Count() == 4\n    && MathF.Abs((pts[1].X - pts[0].X) * (pts[2].Y - pts[0].Y) - (pts[2].X - pts[0].X) * (pts[1].Y - pts[0].Y)) > float.Epsilon;","tryCatchPattern":"try\n{\n    var m = ProjectiveTransformBuilder.DefineQuad(src, dst);\n}\ncatch (NotSupportedException ex) when (ex.Message.Contains(\"singular\"))\n{\n    // fall back to affine transform or request better point correspondences\n}","preventionTips":["Provide 4 distinct, non-collinear source and destination points","Deduplicate points before building projective transforms","When points come from feature detection, verify they form a quad with non-zero area","Consider falling back to affine transforms when only 3 reliable correspondences exist"],"tags":["gaussian-elimination","singular-matrix","projective-transform"],"backgroundTag":"invalid-argument-value","analyzedSha":"59ce6af6fc29027cda277ef62d4d1694a8acce91","analyzedAt":"2026-09-13T18:34:59.331Z","contentChangedAt":"2026-09-13T18:34:59.331Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}