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
def ng2014_normalize(im): IM = niblack(im, window_size=61, k=-0.2) debug_imwrite('niblack.png', IM) IM = cv2.erode(IM, rect33) debug_imwrite('dilated.png', IM) inpainted_min, inpainted_avg, modified = inpaint.inpaint_ng14(im, -IM) debug_imwrite('inpainted_min.png', inpainted_min) debug_imwrite('inpainted_avg.png', inpainted_avg) bg = (inpainted_min & ~IM) | (modified & IM) debug_imwrite('bg.png', bg) bgp = (inpainted_avg & ~IM) | (modified & IM) debug_imwrite('bgp.png', bg) im_f = im.astype(float) + 1 bg_f = bg.astype(float) + 1 F = im_f / bg_f N = clip_u8(255 * (F - F.min())) debug_imwrite('N.png', N) return N, bgp