{"record":{"id":"9a903ab6cbe499eb","repo":"keras-team/keras","slug":"start-points-and-end-points-must-have-the-same-sha-9a903a","errorCode":null,"errorMessage":"start_points and end_points must have the same shape. Received start_points.shape={start_points.shape}, end_points.shape={end_points.shape}","messagePattern":"start_points and end_points must have the same shape\\. Received start_points\\.shape=(.+?), end_points\\.shape=(.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"keras/src/ops/image.py","lineNumber":2194,"sourceCode":"    def compute_output_spec(self, images, start_points, end_points):\n        if len(images.shape) not in (3, 4):\n            raise ValueError(\n                \"Invalid images rank: expected rank 3 (single image) \"\n                \"or rank 4 (batch of images). Received input with shape: \"\n                f\"images.shape={images.shape}\"\n            )\n        if start_points.shape[-2:] != (4, 2) or start_points.ndim not in (2, 3):\n            raise ValueError(\n                \"Invalid start_points shape: expected (4,2) for a single image\"\n                f\" or (N,4,2) for a batch. Received shape: {start_points.shape}\"\n            )\n        if end_points.shape[-2:] != (4, 2) or end_points.ndim not in (2, 3):\n            raise ValueError(\n                \"Invalid end_points shape: expected (4,2) for a single image\"\n                f\" or (N,4,2) for a batch. Received shape: {end_points.shape}\"\n            )\n        if start_points.shape != end_points.shape:\n            raise ValueError(\n                \"start_points and end_points must have the same shape.\"\n                f\" Received start_points.shape={start_points.shape}, \"\n                f\"end_points.shape={end_points.shape}\"\n            )\n        return KerasTensor(images.shape, dtype=images.dtype)\n\n\n@keras_export(\"keras.ops.image.perspective_transform\")\ndef perspective_transform(\n    images,\n    start_points,\n    end_points,\n    interpolation=\"bilinear\",\n    fill_value=0,\n    data_format=None,\n):\n    \"\"\"Applies a perspective transformation to the image(s).\n","sourceCodeStart":2176,"sourceCodeEnd":2212,"githubUrl":"https://github.com/keras-team/keras/blob/7a34a03db60bf60042242d6a556fc3be119046a5/keras/src/ops/image.py#L2176-L2212","documentation":"perspective requires start_points and end_points to have identical shapes so each source corner maps to one destination corner. Mismatched batch sizes, or one array batched while the other is single-image, triggers this.","triggerScenarios":"start_points.shape=(4,2) with end_points.shape=(8,4,2); a batch of N source corners but M != N destination corners.","commonSituations":"Broadcasting expectations carried over from NumPy conventions; per-image corners generated in a loop with an off-by-one; some images dropped from one list.","solutions":["Make both arrays the same shape: either both (4, 2) or both (N, 4, 2) with equal N.","Tile/repeat the single-image array to batch size when it is constant.","Assert start_points.shape == end_points.shape before the call."],"exampleFix":"# before\nperspective(imgs, starts, ends[:4])  # ends has 8 entries\n\n# after\nends = np.stack([base] * len(imgs))\nperspective(imgs, starts, ends)","handlingStrategy":"validation","validationCode":"import numpy as np\nsp, ep = np.asarray(start_points), np.asarray(end_points)\nif sp.ndim == 2 and ep.ndim == 3: sp = np.stack([sp] * ep.shape[0])\nassert sp.shape == ep.shape, (sp.shape, ep.shape)","typeGuard":"def matching_corner_points(sp, ep):\n    sp, ep = np.asarray(sp), np.asarray(ep)\n    return sp.shape == ep.shape and sp.shape[-2:] == (4, 2)","tryCatchPattern":null,"preventionTips":["Broadcast constant corners explicitly with np.stack.","Keep source and destination corner lists generated in the same loop."],"tags":["keras","image","perspective","shape-validation"],"backgroundTag":"tensor-shape-mismatch","analyzedSha":"7a34a03db60bf60042242d6a556fc3be119046a5","analyzedAt":"2026-08-25T21:25:25.994Z","schemaVersion":2},"datasetVersion":"2026-08-26T02:17:13.382Z"}