Example #1
0
 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
Example #2
0
 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
Example #3
0
    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)
Example #4
0
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()