%pylab inline import os import matplotlib.pyplot as plt import matplotlib.image as mimg plt.set_cmap('gray') def scan_template(out_name, scanline_path='/Volumes/MediaStore/Software/scanline', out_dir=os.getcwd()): scanline_cmd = ' '.join([scanline_path, '-flatbed', '-bw', '-jpeg', '-res 600', '-dir', out_dir, '-name', out_name]) if os.system(scanline_cmd) == 0: scanpath = os.path.join(out_dir, out_name+'.jpg') return mimg.imread(scanpath) else: raise Exception def get_thresh(t, pct=30, preview=False): t_max = t.sum(axis=0).max() t_min = t.sum(axis=0).min() t_range = t_max - t_min thresh = t_range * pct/100 + t_min if preview: new_t = t.copy() plt.plot(t.sum(axis=0)) plt.axhline(y=thresh, color='red', zorder=1) return thresh def get_borders(spikes): line_pxs = np.flatnonzero(spikes) # Select non-zero x index borders = [] for ix,px in enumerate(line_pxs[0:-1]): if line_pxs[ix+1] > line_pxs[ix] + 1: border_pair = (px, line_pxs[ix+1]) borders.append(border_pair) return borders def get_horizontal_borders(t, thresh=None): if thresh is None: thresh = get_thresh(t) horizontal_spikes = t.sum(axis=0) < thresh horizontal_borders = get_borders(horizontal_spikes) return horizontal_borders def get_horizontal_crop(t, horizontal_borders=None, preview=False): if horizontal_borders is None: horizontal_borders = get_horizontal_borders(t, get_thresh(t)) hrange = (horizontal_borders[0][0], horizontal_borders[-1][1]) # get crop range from first and last borders horizontal_crop = t[:,hrange[0]:hrange[1]] # get from horizontal_borders if preview: plt.imshow(horizontal_crop) return horizontal_crop def get_vertical_optimum(horizontal_crop, preview=False): horizontal_sum = horizontal_crop.sum(axis=0) vertical_optimum = horizontal_sum.argmax() if preview: preview = horizontal_crop.copy() preview[:,vertical_optimum:vertical_optimum+5] = 0 plt.imshow(preview) return vertical_optimum def get_vertical_spikes(horizontal_crop, vertical_optimum=None): if vertical_optimum is None: vertical_optimum = get_vertical_optimum(horizontal_crop) vertical_spikes = horizontal_crop[:,vertical_optimum] == 0. # Spikes are black pixels on optimum line return vertical_spikes def get_vertical_borders(t, min_extent=300): horizontal_crop = get_horizontal_crop(t) vertical_spikes = get_vertical_spikes(horizontal_crop) vertical_borders = [border for i, border in enumerate(get_borders(vertical_spikes)) if (border[1]-border[0]) > min_extent] return vertical_borders def fudge_boders(borders, fudge): return [(b[0] + fudge[0], b[1] - fudge[1]) for b in borders] autotrace_lst = ['autotrace', '--output-file={0}.svg', '--color-count=2', '--despeckle-level=20', '--despeckle-tightness=2', '--corner-always-threshold=60', '--line-threshold=0.8', '--width-weight-factor=0.1', '--line-reversion-threshold=0.1', '--preserve-width', '--remove-adjacent-corners', '{0}.jpeg'] template_1 = [ ['A','B','C','D','E','F','G','H'], ['I','J','K','L','M','N','O','P'], ['Q','R','S','T','U','V','W','X'], ['Y','Z','_a','_b','_c','_d','_e','_f'], ['_g','_h','_i','_j','_k','_l','_m','_n'], ['_o','_p','_q','_r','_s','_t','_u','_v'], ['_w','_x','_y','_z','0','1','2','3'], ['4','5','6','7','8','9','_e1','_e2'] ] template_2 = [ ['_i^','_ae','_oe','_aa',], ['4','5','6','7','8','9','_00ardivide','_01colon'], ['_02semicolon','_03dot','_04comma','_05plus','_06minus','_07tilde','_08equal','_09half'], ['_10hash','_11at','_12dollar','_13pound','_14sqopen','_15sqclose','_16paranopen','_17paranclose'], ['_18curlyopen','_19curlyclosed','_20lt','_21gt','_22bslash','_23fslash','_24squote','_25dquote'], ['_26underscore','_27pipe','_28star','_29amp','_30pct','_31bang','_32question','_33pow'], ['_34backquote','_35euro','_36mdash','_37','_38','_39','_40','_41'], ['_42','_43','_44','_45','_46','_47','_48','_49'], ] # STEP1: Define scan settings SCAN_NAME = 'regular_pg01_003' PREFIX = 'regular_003' TEMPLATE = template_1 # STEP2: Perform and inspect scan t = scan_template(SCAN_NAME) ## Make sure t is a numpy array with scanned image plt.figure(figsize=(20,20)) plt.subplot(2,2,1) plt.imshow(t) plt.subplot(2,2,2) thresh = get_thresh(t, preview=True) # STEP3: Compute and preview glyph borders MIN_EXTENT = 300 FUDGE_H = (35,25) FUDGE_V = (45,55) h_borders = fudge_boders(get_horizontal_borders(t), FUDGE_H) v_borders = fudge_boders(get_vertical_borders(t), FUDGE_V) v_flat = [item for sublist in v_borders for item in sublist] h_flat = [item for sublist in h_borders for item in sublist] plt.figure(figsize=(20,20)) plt.imshow(t) plt.hlines(v_flat, xmin=0, xmax=t.shape[1], colors='red') plt.vlines(h_flat, ymin=0, ymax=t.shape[0], colors='green') # STEP4: Use template to name each glyph and save the raster and traced files if not os.path.exists(PREFIX): os.makedirs(PREFIX) flat_template = [item for sublist in TEMPLATE for item in sublist] plt.figure(figsize=(20,20)) plotno = 1 for i in v_borders: for j in h_borders: plt.subplot(8,8,plotno) plt.imshow(t[slice(*i),slice(*j)]) path = PREFIX + "/" + flat_template[plotno-1] imsave(path + '.jpeg', t[slice(*i),slice(*j)]) cmd = ' '.join(autotrace_lst).format(path) os.system(cmd) plotno += 1