PaddlePaddle/PaddleOCR · error · Exception

degree must be number or list with length 2

Error message

degree must be number or list with length 2

What it means

CVGaussianNoise's constructor validates var: a number is sampled via sample_asym, a 2-element tuple/list is sampled uniformly, and anything else raises Exception. The message says 'degree must be number or list with length 2', which is a copy-paste artifact — the failing parameter is `var`, the noise variance for np.random.normal.

Source

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

        cur_w, cur_h = self.base_w, self.base_h
        scale_img = cv2.resize(img, (cur_w, cur_h), interpolation=get_interpolation())
        for _ in range(self.factor):
            scale_img = cv2.pyrDown(scale_img)
        scale_img = cv2.resize(
            scale_img, (src_w, src_h), interpolation=get_interpolation()
        )
        return scale_img


class CVGaussianNoise(object):
    def __init__(self, mean=0, var=20):
        self.mean = mean
        if isinstance(var, numbers.Number):
            self.var = max(int(sample_asym(var)), 1)
        elif isinstance(var, (tuple, list)) and len(var) == 2:
            self.var = int(sample_uniform(var[0], var[1]))
        else:
            raise Exception("degree must be number or list with length 2")

    def __call__(self, img):
        noise = np.random.normal(self.mean, self.var**0.5, img.shape)
        img = np.clip(img + noise, 0, 255).astype(np.uint8)
        return img


class CVPossionNoise(object):
    def __init__(self, lam=20):
        self.lam = lam
        if isinstance(lam, numbers.Number):
            self.lam = max(int(sample_asym(lam)), 1)
        elif isinstance(lam, (tuple, list)) and len(lam) == 2:
            self.lam = int(sample_uniform(lam[0], lam[1]))
        else:
            raise Exception("lam must be number or list with length 2")

    def __call__(self, img):

View on GitHub (pinned to 2661c7c0ef)

Solutions

  1. Pass var as a number (e.g. var=20) or exact 2-element sequence like var=(10, 30).
  2. Cast config values: var=int(cfg['var']) for scalars.
  3. Ignore the word 'degree' in the message — it is the noise variance that is malformed.

Example fix

# before
CVGaussianNoise(var=cfg['var'])            # cfg['var'] == '20' -> Exception
# after
CVGaussianNoise(var=float(cfg['var']) if not isinstance(cfg['var'], (list, tuple)) else tuple(cfg['var']))
Defensive patterns

Strategy: validation

Validate before calling

import numbers

def valid_var(v) -> bool:
    return (isinstance(v, numbers.Number)
            or (isinstance(v, (tuple, list)) and len(v) == 2))

Type guard

import numbers

def is_valid_var(v) -> bool:
    return isinstance(v, numbers.Number) or (isinstance(v, (tuple, list)) and len(v) == 2)

Prevention

When it happens

Trigger: CVGaussianNoise(var=[10, 20, 30]) (length 3), var='20' (string from YAML), or var=None / dict.

Common situations: String-typed numbers from config files; confusion caused by the misleading 'degree' wording sending developers to inspect rotation params; three-element variance ranges.

Related errors


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