PaddlePaddle/PaddleOCR · error · ValueError
degenerate text crop (zero width/height)
Error message
degenerate text crop (zero width/height)
What it means
Raised by the calibration-sample builder for the iOS ONNX demo when a perspective-crop of a detected text quadrilateral degenerates: the computed crop width or height (max of opposing edge lengths via np.linalg.norm) rounds down below 1 pixel. This means the detected box is collapsed, collinear, or so tiny that a valid crop rectangle cannot be formed.
Source
Thrown at deploy/ios_demo/scripts/build_onnx_calib_npy.py:143
else:
index_b, index_c = 3, 2
box = [pts[index_a], pts[index_b], pts[index_c], pts[index_d]]
pts4 = [np.array(p, dtype=np.float32) for p in box]
assert len(pts4) == 4, "shape of points must be 4*2"
img_crop_width = int(
max(
np.linalg.norm(pts4[0] - pts4[1]),
np.linalg.norm(pts4[2] - pts4[3]),
)
)
img_crop_height = int(
max(
np.linalg.norm(pts4[0] - pts4[3]),
np.linalg.norm(pts4[1] - pts4[2]),
)
)
if img_crop_width < 1 or img_crop_height < 1:
raise ValueError("degenerate text crop (zero width/height)")
pts_std = np.float32(
[
[0, 0],
[img_crop_width, 0],
[img_crop_width, img_crop_height],
[0, img_crop_height],
]
)
pstack = np.stack(pts4, axis=0)
m = cv2.getPerspectiveTransform(pstack, pts_std)
dst = cv2.warpPerspective(
img,
m,
(img_crop_width, img_crop_height),
borderMode=cv2.BORDER_REPLICATE,
flags=cv2.INTER_CUBIC,
)
dh, dw = dst.shape[0:2]View on GitHub (pinned to 2661c7c0ef)
Solutions
- Sanitize the input annotations: drop quads whose width or height norms are < 1px before running the script.
- Skip the degenerate crop instead of aborting: wrap the check in a filter and continue with remaining samples.
- If boxes should be valid, inspect the offending quad coordinates (print pts4) and fix the upstream detector/labels.
Example fix
# before
if img_crop_width < 1 or img_crop_height < 1:
raise ValueError("degenerate text crop (zero width/height)")
# after
if img_crop_width < 1 or img_crop_height < 1:
print(f"skip degenerate crop: {pts4.tolist()}")
continue Defensive patterns
Strategy: validation
Validate before calling
import numpy as np
def crop_is_valid(pts4: np.ndarray, min_px: float = 1.0) -> bool:
w = max(np.linalg.norm(pts4[0] - pts4[1]), np.linalg.norm(pts4[2] - pts4[3]))
h = max(np.linalg.norm(pts4[0] - pts4[3]), np.linalg.norm(pts4[1] - pts4[2]))
return w >= min_px and h >= min_px
# filter before cropping
samples = [s for s in samples if crop_is_valid(np.asarray(s["polygon"], np.float32))] Type guard
def is_valid_quad(pts) -> bool:
import numpy as np
p = np.asarray(pts, dtype=np.float32)
return p.shape == (4, 2) and np.all(np.isfinite(p)) and len(np.unique(p, axis=0)) >= 3 Try / catch
try:
crop = make_crop(img, pts4)
except ValueError as e:
if "degenerate" in str(e):
continue # skip this sample, keep processing the calibration set
raise Prevention
- Validate annotation quads (4 unique points, non-collinear, >=1px edges) before batch runs.
- Skip-and-log degenerate boxes instead of aborting long calibration jobs.
- Re-check annotations after regenerating labels with a new detector.
When it happens
Trigger: A detection quad whose opposing edges have length < 1.0 — e.g. all four points nearly identical, points collinear (zero height), or sub-pixel boxes produced by a downscaled/quantized detector during ONNX calibration-set generation.
Common situations: Running build_onnx_calib_npy.py over annotation files that contain degenerate or corrupted boxes; calibration images resized so small that legitimate boxes shrink below 1px; hand-edited label files with duplicated corner coordinates.
Related errors
- compare_ocr_json.py requires `pip install shapely`
- {path}: missing 'items' array
- [extract_xcresult_attachments] FAIL: `xcrun xcresulttool hel
- xcresulttool get test-results failed with exit {r.returncode
- Detection model session is not initialized.
AI-assisted analysis of PaddlePaddle/PaddleOCR@2661c7c0ef (2026-08-14).
Data as JSON: /api/errors/ffe5c7648431db8e.
Report an issue: GitHub.