示例#1
0
def lu2010(im):
    im_h, im_w = im.shape

    # im_bg_row = polynomial_background_easy(im)  # TODO: implement full
    # im_bg = polynomial_background_easy(im_bg_row.T).T
    # im_bg = im_bg.clip(0.1, 255)
    IM = cv2.erode(niblack(im, window_size=61, k=0.2), rect33)
    inpainted, modified = inpaint.inpaint_ng14(im, -IM)
    im_bg = (inpainted & ~IM) | (modified & IM)
    im_bg = im_bg.astype(np.float32).clip(0.1, 255)
    debug_imwrite('bg.png', im_bg)

    C = np.percentile(im, 30)
    I_bar = clip_u8(C / im_bg * im)
    debug_imwrite('ibar.png', I_bar)
    I_bar_padded = np.pad(I_bar, (1, 1), 'edge')

    V_h = cv2.absdiff(I_bar_padded[2:, 1:-1], I_bar_padded[:-2, 1:-1])
    V_v = cv2.absdiff(I_bar_padded[1:-1, 2:], I_bar_padded[1:-1, :-2])
    V = V_h + V_v
    V[V < V_h] = 255  # clip overflow
    _, stroke_edges = cv2.threshold(V, 0, 255,
                                    cv2.THRESH_BINARY | cv2.THRESH_OTSU)
    # 1 if high contrast, 0 otherwise.
    E_inv = stroke_edges & 1
    E_inv_255 = E_inv * 255
    debug_imwrite('e_inv.png', E_inv_255)
    im_high = im & E_inv_255
    debug_imwrite('im_high.png', im_high)

    # calculate stroke width
    H, _ = np.histogram(nonzero_distances_row(E_inv), np.arange(im_h / 100))
    H[1] = 0  # don't use adjacent pix
    W = H.argmax()
    print('stroke width:', W)
    size = 2 * W
    N_min = W

    if size >= 16:
        E_inv = E_inv.astype(np.uint16)
    window = (size | 1, size | 1)
    N_e = cv2.boxFilter(E_inv, -1, window, normalize=False)
    debug_imwrite('n_e.png', bool_to_u8(N_e >= N_min))

    E_mean = cv2.boxFilter(im_high, cv2.CV_32S, window,
                           normalize=False) / (N_e.astype(np.float64) + 0.1)
    debug_imwrite('i_bar_e_mean.png', bool_to_u8(I_bar <= E_mean))

    out = ~bool_to_u8((N_e >= N_min) & (I_bar <= E_mean))
    debug_imwrite('lu2010.png', out)
    return out
示例#2
0
def gradient2(im):
    im_inv = ~im
    mins = erode_square(im_inv, 15)
    maxes = dilate_square(im_inv, 15)

    diff = maxes - mins

    return bool_to_u8(diff < 50)
示例#3
0
def remove_stroke_outliers(im, lines, k=1.0):
    stroke_widths = fast_stroke_width(im)
    if lib.debug:
        lib.debug_imwrite('strokes.png',
                          lib.normalize_u8(stroke_widths.clip(0, 10)))

    mask = np.zeros(im.shape, dtype=np.uint8)
    for line in lines:
        for letter in line:
            sliced = letter.crop().apply(mask)
            sliced |= letter.raster()

    lib.debug_imwrite('letter_mask.png', -mask)

    masked_strokes = stroke_widths.copy()
    masked_strokes &= -mask

    strokes_mean, strokes_std = masked_mean_std(masked_strokes, mask)
    if lib.debug:
        print('overall: mean:', strokes_mean, 'std:', strokes_std)

    debug = cv2.cvtColor(im, cv2.COLOR_GRAY2RGB)
    new_lines = []
    for line in lines:
        if len(line) <= 1: continue
        good_letters = []
        for letter in line:
            crop = letter.crop()
            if not crop.nonempty(): continue

            raster = letter.raster()
            sliced_strokes = crop.apply(stroke_widths).copy()
            sliced_strokes &= lib.bool_to_u8(raster)

            mean, std = masked_mean_std(sliced_strokes, raster)
            if mean < strokes_mean - k * strokes_std:
                if lib.debug:
                    print('skipping {:4d} {:4d} {:.03f} {:.03f}'.format(
                        letter.x,
                        letter.y,
                        mean,
                        std,
                    ))
                    letter.box(debug, color=lib.RED)
            else:
                if lib.debug: letter.box(debug, color=lib.GREEN)
                good_letters.append(letter)

        if good_letters:
            new_lines.append(TextLine(good_letters,
                                      underlines=line.underlines))

    lib.debug_imwrite("stroke_filter.png", debug)

    return new_lines
示例#4
0
def retinex(im, mu_1=0.9, mu_2=25, sigma=5):
    G = cv2.GaussianBlur(im, (0, 0), sigma)
    debug_imwrite('G.png', G)
    bools = (im < mu_1 * G) & (cv2.absdiff(im, G) > mu_2)
    return bool_to_u8(bools)
示例#5
0
def roth(im, s=51, t=0.8):
    im_h, im_w = im.shape
    means = cv2.blur(im, (s, s))
    ints = cv2.bitwise_not(bool_to_u8(im > means * t))
    debug_imwrite('roth.png', ints)
    return ints
示例#6
0
def sauvola(im, window_size=61, k=0.2):
    assert im.dtype == np.uint8
    means, stds = mean_std(im, window_size)
    thresh = means * (1 + k * ((stds / 127) - 1))

    return bool_to_u8(im > thresh)
示例#7
0
def niblack(im, window_size=61, k=0.2):
    means, stds = mean_std(im, window_size)
    thresh = means + k * stds

    return bool_to_u8(im > thresh)