def get_AH_lines(im): all_letters = algorithm.all_letters(im) # AH == average character height AH = algorithm.dominant_char_height(im, letters=all_letters) if lib.debug: print('AH =', AH) letters = algorithm.filter_size(AH, im, letters=all_letters) all_lines = collate.collate_lines(AH, letters) # From up to down all_lines.sort(key=lambda l: l[0].y) combined = algorithm.combine_underlined(AH, im, all_lines, all_letters) filtered = algorithm.remove_stroke_outliers(im, combined, k=2.0) # filtered = algorithm.filter_spacing_deviation(im, AH, filtered) lines = remove_outliers(im, AH, filtered) # lines = combined # if lib.debug: # debug = cv2.cvtColor(bw, cv2.COLOR_GRAY2BGR) # for l in all_lines: # for l1, l2 in zip(l, l[1:]): # cv2.line(debug, tuple(l1.base_point().astype(int)), # tuple(l2.base_point().astype(int)), RED, 2) # lib.debug_imwrite('all_lines.png', debug) return AH, lines, all_lines
def crop(im, bw, split=True): im_h, im_w = im.shape[:2] all_letters = algorithm.all_letters(bw) AH = algorithm.dominant_char_height(bw, letters=all_letters) letters = algorithm.filter_size(AH, bw, letters=all_letters) all_lines = collate.collate_lines(AH, letters) combined = algorithm.combine_underlined(AH, bw, all_lines, all_letters) lines = algorithm.remove_stroke_outliers(bw, combined) if not lines: print('WARNING: no lines in image.') return AH, [] lines = filter_position(AH, bw, lines, split) lines = [ line for line in lines if not np.all(line.crop().apply(bw) == 255) ] if not lines: print('WARNING: eliminated all lines.') return AH, [] if split and im_w > im_h: # two pages line_sets = split_lines(lines) else: line_sets = [lines] return AH, line_sets
def test(models_dir, image_path): im = cv2.imread(image_path, cv2.IMREAD_UNCHANGED) bw = binarize.binarize(im, algorithm=binarize.ntirogiannis2014) AH = algorithm.dominant_char_height(bw) print('AH =', AH) possible_AHs = np.array([int(d) for d in os.listdir(models_dir) if d.isdigit()]) size = possible_AHs[np.abs(possible_AHs - AH).argmin()] model_dir = os.path.join(models_dir, str(size)) P_l_T, P_h_T, pca, A_l_T, Q_T, A_h_T = load_model(model_dir)
assert np.all(segments[:, 0] < segments[:, 1]) theta_p = np.zeros((len(ellipses), )) s_p = np.full((len(ellipses), ), 5) def V_pq_sites(p1, p2, l1, l2): s_1, theta_1 = unpack_label(l1) s_2, theta_2 = unpack_label(l2) centroid_1, centroid_2 = centroids[(p1, p2), :] d_pq_sq = np.square(centroid_1 - centroid_2).sum() scale = np.exp(-k * d_pq_sq / (s_values[s_1]**2 + s_values[s_2]**2)) f_diff = abs(s_1 - s_2) + abs(theta_1 - theta_2) mu = 0 if l1 == l2 else (lam_1 if f_diff <= 3 else lam_2) return mu * scale # graph.set_smooth_cost_function(V_pq_sites) # graph.expansion() if __name__ == '__main__': lib.debug = True orig = cv2.imread(sys.argv[1]) bw = binarize.binarize(orig, algorithm=binarize.sauvola) lib.debug_imwrite('retinex.png', bw) AH = algorithm.dominant_char_height(bw) koo2010(bw, AH)
def upscale(path, data_dir, factor): assert factor == 2 im = cv2.imread(path, cv2.IMREAD_UNCHANGED) im_h, im_w = im.shape bw = binarize.binarize(im, algorithm=binarize.ntirogiannis2014) AH = dominant_char_height(bw) print('AH =', AH) possible_AHs = np.array( [int(d) for d in os.listdir(data_dir) if d.isdigit()]) size = possible_AHs[np.abs(possible_AHs - AH).argmin()] D_T_coupled = np.load(os.path.join(data_dir, str(size), 'dict.npy')) W_l = int(size / 3) | 1 W_h = 2 * W_l step = 3 assert D_T_coupled.shape[1] == W_l * W_l + W_h * W_h D_T = D_T_coupled[:, :W_l * W_l] K = D_T.shape[0] lam = 0.2 # weight of sparsity. TODO: confirm same as training data. lo_patches = patches(im, W_l, step) struct = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) gradient = cv2.morphologyEx(im, cv2.MORPH_GRADIENT, struct) gradient_means, _ = binarize.mean_std(gradient, W_l) patch_gradient = gradient_means[W_l // 2:-W_l // 2 + 1:step, W_l // 2:-W_l // 2 + 1:step] assert patch_gradient.shape == (lo_patches.shape[0], lo_patches.shape[1]) patch_mask = patch_gradient > np.percentile(patch_gradient, 50) good_patches = np.nonzero(patch_mask) cv2.imwrite('spp.png', -patch_mask.astype(np.uint8)) lo_patches_vec = lo_patches[good_patches].reshape(-1, W_l * W_l).astype( np.float64) means = lo_patches_vec.mean(axis=1) X_T = lo_patches_vec - means[:, newaxis] t = X_T.shape[0] Z_T = np.zeros((t, K), dtype=np.float64) last_objective = None while True: training.feature_sign_search_vec(X_T, Z_T, D_T, lam) objective = np.square(X_T - Z_T.dot(D_T)).sum() print('\ncurrent objective:', objective) if last_objective is not None: relative_err = abs(last_objective - objective) / last_objective print('relative error:', relative_err) if relative_err < 1e-4: break last_objective = objective hi_patches = Z_T.dot(D_T_coupled)[:, W_l * W_l:] + means[:, newaxis] hi_float = np.zeros((factor * im_h, factor * im_w), dtype=np.float64) dest_patches = patches(hi_float, W_h, 2 * step) patch_count = np.zeros((factor * im_h, factor * im_w), dtype=int) count_patches = patches(patch_count, W_h, 2 * step) for i, patch in enumerate(hi_patches): dest_patches[good_patches[i]] += patch count_patches[good_patches[i]] += 1 np.divide(hi_float, patch_count, hi_float, where=patch_count > 0) hi_lanczos = cv2.resize(im, (0, 0), None, 2., 2., interpolation=cv2.INTER_LANCZOS4) return np.where(patch_count > 0, hi_float, hi_lanczos).clip(0, 255).astype(np.uint8)