PaddlePaddle/PaddleOCR · error · ValueError

Shear should be a single value or a tuple/list containing tw

Error message

Shear should be a single value or a tuple/list containing two values. Got {}

What it means

CVRandomAffine._get_inverse_affine_matrix raises ValueError when the shear parameter handed to the matrix computation is neither a number nor a 2-length tuple/list. Note the guard itself has a logic bug — `if not isinstance(shear, (tuple, list)) and len(shear) == 2` — so a number is widened to [shear, 0] first and tuples of length != 2 raise via len() failing or the condition passing; in practice a malformed shear value from construction reaches here.

Source

Thrown at ppocr/data/imaug/abinet_aug.py:133

                    )
                self.shear = [shear]
            else:
                assert isinstance(shear, (tuple, list)) and (
                    len(shear) == 2
                ), "shear should be a list or tuple and it must be of length 2."
                self.shear = shear
        else:
            self.shear = shear

    def _get_inverse_affine_matrix(self, center, angle, translate, scale, shear):
        # https://github.com/pytorch/vision/blob/v0.4.0/torchvision/transforms/functional.py#L717
        from numpy import sin, cos, tan

        if isinstance(shear, numbers.Number):
            shear = [shear, 0]

        if not isinstance(shear, (tuple, list)) and len(shear) == 2:
            raise ValueError(
                "Shear should be a single value or a tuple/list containing "
                + "two values. Got {}".format(shear)
            )

        rot = math.radians(angle)
        sx, sy = [math.radians(s) for s in shear]

        cx, cy = center
        tx, ty = translate

        # RSS without scaling
        a = cos(rot - sy) / cos(sy)
        b = -cos(rot - sy) * tan(sx) / cos(sy) - sin(rot)
        c = sin(rot - sy) / cos(sy)
        d = -sin(rot - sy) * tan(sx) / cos(sy) + cos(rot)

        # Inverted rotation matrix with scale and shear
        # det([[a, b], [c, d]]) == 1, since det(rotation) = 1 and det(shear) = 1

View on GitHub (pinned to 2661c7c0ef)

Solutions

  1. Always set shear through the constructor so it is normalized to a list of one or two numbers.
  2. Normalize before use: shear = [shear, 0] if isinstance(shear, numbers.Number) else list(shear); assert len(shear) == 2.
  3. Fix the upstream condition if you control the code: `if not (isinstance(shear, (tuple, list)) and len(shear) == 2): raise ...`.

Example fix

# before (patched/derived class sets shear directly)
aff.shear = [10, 0, 5]  # later: ValueError in _get_inverse_affine_matrix
# after
aff.shear = [10, 0]     # exactly two degree values
Defensive patterns

Strategy: type-guard

Validate before calling

import numbers

def normalize_shear(shear):
    if isinstance(shear, numbers.Number):
        return [shear, 0]
    shear = list(shear)
    if len(shear) == 1:
        return [shear[0], 0]
    if len(shear) != 2:
        raise ValueError(f'shear must be number or 2-sequence, got {shear!r}')
    return shear

Type guard

import numbers

def is_normalized_shear(v) -> bool:
    return (isinstance(v, (tuple, list)) and len(v) == 2
            and all(isinstance(x, numbers.Number) for x in v))

Prevention

When it happens

Trigger: Calling _get_inverse_affine_matrix (or CVRandomAffine.__call__ which forwards self.shear) with shear as a 3-element list, a string, or a tuple whose length is not 2. Constructing with a properly-validated shear normally avoids this path.

Common situations: Subclassing or monkey-patching CVRandomAffine and setting self.shear directly; feeding shear from config without the constructor's validation; passing numpy scalars that fail isinstance checks.

Related errors


AI-assisted analysis of PaddlePaddle/PaddleOCR@2661c7c0ef (2026-08-14). Data as JSON: /api/errors/444cc9d07383eb0e. Report an issue: GitHub.