File size: 1,442 Bytes
618450b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import math
import numpy as np

def _percentiles(b: np.ndarray, qs=(0.02, 0.5, 0.98)) -> list[float]:
    """np.percentile(b, 100 * qs) (linear) of a uint8 array, from its histogram:
    no sort of the pixels."""
    n = b.size
    cum = np.cumsum(np.bincount(b.ravel(), minlength=256))
    out = []
    for q in qs:
        x = q * (n - 1)
        i = math.floor(x)
        g = x - i
        lo = float(np.searchsorted(cum, i, side="right"))
        hi = float(np.searchsorted(cum, min(i + 1, n - 1), side="right"))
        d = hi - lo
        # numpy's lerp: from the nearer end
        out.append(hi - d * (1 - g) if g >= 0.5 else lo + d * g)
    return out

def is_dark_line(gray: np.ndarray, box) -> bool:
    """Light text on a dark ground (a banner, a dark table head, a slide): the
    ground (the median of the line box) lies nearer the dark end than the text
    does, so the bright tail is the longer one.  A shadowed line keeps dark text
    on a dimmer ground.  The recognizers read dark text on light paper, so a
    light-on-dark line is read inverted."""
    H, W = gray.shape
    x0, y0, x1, y1 = (float(v) for v in box[:4])
    b = gray[
        max(0, int(y0)) : min(H, int(y1) + 1), max(0, int(x0)) : min(W, int(x1) + 1)
    ]
    if not b.size:
        return False
    lo, med, hi = (
        _percentiles(b) if b.dtype == np.uint8 else np.percentile(b, (2, 50, 98))
    )
    return bool(hi - med > 2 * (med - lo) + 8)