def _find_blocks(self, array, trim_edges=False): array = sp.clip(array, a_min=0, a_max=1) temp = sp.pad(array, pad_width=1, mode='constant', constant_values=0) end_pts = sp.where(sp.ediff1d(temp) == -1)[0] # Find 1->0 transitions end_pts -= 1 # To adjust for 0 padding seg_len = sp.cumsum(array)[end_pts] seg_len[1:] = seg_len[1:] - seg_len[:-1] start_pts = end_pts - seg_len + 1 a = dict() a['start'] = start_pts a['end'] = end_pts a['length'] = seg_len if trim_edges: if (a['start'].size > 0) and (a['start'][0] == 0): [a.update({item: a[item][1:]}) for item in a] if (a['end'].size > 0) and (a['end'][-1] == sp.size(array)-1): [a.update({item: a[item][:-1]}) for item in a] return a
def _find_blocks(self, array, trim_edges=False): array = sp.clip(array, a_min=0, a_max=1) temp = sp.pad(array, pad_width=1, mode='constant', constant_values=0) end_pts = sp.where(sp.ediff1d(temp) == -1)[0] # Find 1->0 transitions end_pts -= 1 # To adjust for 0 padding seg_len = sp.cumsum(array)[end_pts] seg_len[1:] = seg_len[1:] - seg_len[:-1] start_pts = end_pts - seg_len + 1 a = dict() a['start'] = start_pts a['end'] = end_pts a['length'] = seg_len if trim_edges: if (a['start'].size > 0) and (a['start'][0] == 0): [a.update({item: a[item][1:]}) for item in a] if (a['end'].size > 0) and (a['end'][-1] == sp.size(array) - 1): [a.update({item: a[item][:-1]}) for item in a] return a
def segment(self, mol, threshold, end): """ takes a list whos values are some score of whether that specific coordinate is a linker. this is typically used on the lists returned from partition but does not have to be. All streches of elements whos threshold is above or below some value are then determined. and a list of regions and there corresponding label are returned. It also ignores the last "end" coordinates of mol. regeions = [(0,end),(start,end),...,(start,end),(start,len(mol))] labels = [1,0,...1,0] 1 for greater then threshold 0 for below. """ mask = mol > threshold breaks = scipy.concatenate( ([0], scipy.argwhere(scipy.ediff1d(mask[:-end]))[:, 0] + 1, [len(mol)])) regions = scipy.array([(s, e) for s, e in zip(breaks[:-1], breaks[1:])]) labels = scipy.array([int(mask[s]) for s, e in regions]) return (regions, labels)
def scan_receipt(img, clf): angle_to_rotate = detect_skew(img, quality='medium') print 'angle_to_rotate', angle_to_rotate img = rotate(img, angle_to_rotate, order=5, cval=1.0) thresh = threshold_otsu(img) img = img < thresh # plt.imshow(img, interpolation='nearest', cmap='gray') # plt.axis('image') # plt.xticks([]) # plt.yticks([]) # plt.show() # extract individual lines num_blacks = sp.sum(img, axis=1) has_characters = num_blacks > 0.01 * img.shape[1] line_diffs = sp.ediff1d(has_characters.astype(sp.int32)) line_starts = sp.nonzero(line_diffs == 1)[0] line_ends = sp.nonzero(line_diffs == -1)[0] + 2 line_heights = line_ends - line_starts normal_line_height = sp.median(line_heights) lines = [] for start, end, height in zip(line_starts, line_ends, line_heights): if height < normal_line_height * 1.2 and height > 5: lines.append(img[start:end]) receipt_content = '' # extract individual characters from lines for line in lines: line_content = '' num_blacks = sp.sum(line, axis=0) has_character = num_blacks > 0 col_diffs = sp.ediff1d(has_character.astype(sp.int32)) col_starts = sp.nonzero(col_diffs == 1)[0] col_ends = sp.nonzero(col_diffs == -1)[0] + 2 char_widths = col_ends - col_starts normal_char_width = sp.median(char_widths) min_char_width = normal_char_width * 0.8 max_char_width = normal_char_width * 1.2 # account for cases when 2 chars are merged, or if a single char is separated chars = [] i = 0 while i < len(col_starts): start = col_starts[i] end = col_ends[i] width = end - start if width < min_char_width: while i + 1 < len(col_starts): expanded_width = col_ends[i+1] - start if expanded_width < min_char_width: i += 1 elif expanded_width > max_char_width: break elif col_starts[i+1] - end >= 3: break else: i += 1 break chars.append(line[:, start:col_ends[i]]) elif width >= normal_char_width * 2: chars.append(line[:, start:start+width//2-1]) chars.append(line[:, start+width//2+1:end]) else: chars.append(line[:, start:end]) i += 1 # pad each char to a square and resize it to 24x24 padded_chars = [] for char in chars: height, width = char.shape if height > width: diff = height - width pad_left = diff // 2 padded_char = sp.zeros((height, height)) padded_char[:, pad_left:pad_left+width] = char elif width > height: diff = width - height pad_top = diff // 2 padded_char = sp.zeros((width, width)) padded_char[pad_top:pad_top+height, :] = char final_char = imresize(padded_char, (25, 25), 'bicubic') padded_chars.append(final_char) for char in padded_chars: plt.imshow(char, interpolation='nearest', cmap='gray') plt.axis('image') plt.xticks([]) plt.yticks([]) plt.show()