Ejemplo n.º 1
0
def firstAnalyse(binary):
    binaryary = morph.r_closing(binary.astype(bool), (1,1))
    labels,_ = morph.label(binaryary)
    objects = morph.find_objects(labels) ### <<<==== objects here
    bysize = sorted(range(len(objects)), key=lambda k: sl.area(objects[k]))
#     bysize = sorted(objects,key=sl.area)
    scalemap = zeros(binaryary.shape)
    smalldot = zeros(binaryary.shape, dtype=binary.dtype)
    for i in bysize:
        o = objects[i]
        if amax(scalemap[o])>0: 
#             mask = where(labels[o] != (i+1),uint8(255),uint8(0))
#             binary[o] = cv2.bitwise_and(binary[o],binary[o],mask=mask)
            continue
        scalemap[o] = sl.area(o)**0.5
    scale = median(scalemap[(scalemap>3)&(scalemap<100)]) ### <<<==== scale here

    for i,o in enumerate(objects):       
        if (sl.width(o) < scale/2) or (sl.height(o) < scale/2):
            smalldot[o] = binary[o]
        if sl.dim0(o) > 3*scale:
            mask = where(labels[o] != (i+1),uint8(255),uint8(0))
            binary[o] = cv2.bitwise_and(binary[o],binary[o],mask=mask)
            continue
    return objects, smalldot, scale
Ejemplo n.º 2
0
def calc_typo_metric(binline):
    labels,n = morph.label(binline)
    objects = morph.find_objects(labels)
    filtered = []
    max_h = 0
    for o in objects:
        h = sl.dim0(o)
        w = sl.dim1(o)
        if h > binline.shape[0]*0.98: continue
        if h < 3 or w < 3: continue
        if (h > binline.shape[0]*0.2 and w > binline.shape[0]*0.2) or \
                (o[0].start > binline.shape[0]/2 and o[1].stop > binline.shape[1]/4 and o[1].stop < 3*binline.shape[1]/4 and o[0].stop < binline.shape[0]*0.98):
            filtered.append(o)
            if h > max_h:
                max_h = h
    filtered.sort(key=lambda x:x[1].start)
    prech = None
    zoomforsee = 4
    infoheight=50
    info = np.zeros((infoheight*2+binline.shape[0]*zoomforsee,binline.shape[1]*zoomforsee))
    for ch in filtered:
        h = sl.dim0(ch)
        w = sl.dim1(ch)
        if prech is not None and ch[1].start < (prech[1].start + prech[1].stop)/2: continue
        cv2.putText(info,'{:3.2f}'.format(1.0*w/max_h),\
                    ((ch[1].start)*zoomforsee, int(infoheight*0.4)), cv2.FONT_HERSHEY_SIMPLEX, \
                    0.5,1.0,1)
        if prech is None:
            cv2.putText(info,'{:3d}'.format(max_h),\
                        ((ch[1].start)*zoomforsee, int(infoheight*0.9)), cv2.FONT_HERSHEY_SIMPLEX, \
                        0.5,1.0,1)           
        else:    
            space = ch[1].start - prech[1].stop
            dist = ch[1].stop - prech[1].stop
            cv2.putText(info,'{:3.2f}'.format(1.0*space/max_h),\
                        ((prech[1].stop)*zoomforsee, int(infoheight*0.9)), cv2.FONT_HERSHEY_SIMPLEX, \
                        0.5,1.0,1)
            cv2.putText(info,'({:3.2f})'.format(1.0*dist/max_h),\
                        ((prech[1].stop)*zoomforsee, int(infoheight*1.4)), cv2.FONT_HERSHEY_SIMPLEX, \
                        0.5,1.0,1)
        prech = ch
    info[infoheight*2:,:] = cv2.resize(binline, (zoomforsee*binline.shape[1], zoomforsee*binline.shape[0]))
    return (info*250).astype(np.uint8), filtered
Ejemplo n.º 3
0
def simplefirstAnalyse(binary):
    binaryary = morph.r_closing(binary.astype(bool), (1,1))
    labels,_ = morph.label(binaryary)
    objects = morph.find_objects(labels) ### <<<==== objects here
    smalldot = zeros(binaryary.shape, dtype=binary.dtype)
    scale = int(binary.shape[0]*0.7)
    for i,o in enumerate(objects):       
        if (sl.width(o) < scale/2) or (sl.height(o) < scale/2):
            smalldot[o] = binary[o]
        if sl.dim0(o) > 3*scale:
            mask = where(labels[o] != (i+1),uint8(255),uint8(0))
            binary[o] = cv2.bitwise_and(binary[o],binary[o],mask=mask)
            continue
    return objects, smalldot, scale
Ejemplo n.º 4
0
def compute_lines(segmentation,scale):
    """Given a line segmentation map, computes a list
    of tuples consisting of 2D slices and masked images."""
    lobjects = morph.find_objects(segmentation)
    lines = []
    for i,o in enumerate(lobjects):
        if o is None: continue
        if sl.dim1(o)<2*scale or sl.dim0(o)<scale: continue
        mask = (segmentation[o]==i+1)
        if np.amax(mask)==0: continue
        result = record()
        result.label = i+1
        result.bounds = o
        result.mask = mask
        lines.append(result)
    return lines
Ejemplo n.º 5
0
def compute_lines(segmentation,scale):
    """Given a line segmentation map, computes a list
    of tuples consisting of 2D slices and masked images."""
    lobjects = morph.find_objects(segmentation)
    lines = []
    for i,o in enumerate(lobjects):
        if o is None: continue
        if sl.dim1(o)<2*scale or sl.dim0(o)<scale: continue
        mask = (segmentation[o]==i+1)
        if amax(mask)==0: continue
        result = record()
        result.label = i+1
        result.bounds = o
        result.mask = mask
        lines.append(result)
    return lines
Ejemplo n.º 6
0
def compute_boxmap(binary, scale, oriimg, threshold=(.5, 4), dtype='i'):
    labels, n = morph.label(binary)
    objects = morph.find_objects(labels)
    boxmap = zeros(binary.shape, dtype)
    for i, o in enumerate(objects):
        h = sl.dim0(o)
        w = sl.dim1(o)
        ratio = float(h) / w if h > w else float(w) / h
        if h > 2 * scale or h < scale / 3:
            continue
        if ratio > 8: continue
        #         if sl.area(o)**.5<threshold[0]*scale: continue
        #         if sl.area(o)**.5>threshold[1]*scale: continue

        boxmap[o] = 1
    return boxmap
Ejemplo n.º 7
0
def show_lines(image, lines, lsort):
    """Overlays the computed lines on top of the image, for debugging
    purposes."""
    ys, xs = [], []
    plt.clf()
    plt.cla()
    plt.imshow(image)
    for i in range(len(lines)):
        l = lines[lsort[i]]
        y, x = sl.center(l.bounds)
        xs.append(x)
        ys.append(y)
        o = l.bounds
        r = mpatches.Rectangle((o[1].start, o[0].start),
                               edgecolor='r',
                               fill=0,
                               width=sl.dim1(o),
                               height=sl.dim0(o))
        plt.gca().add_patch(r)
    h, w = image.shape
    plt.ylim(h, 0)
    plt.xlim(0, w)
    plt.plot(xs, ys)
def extractLines(imgpath, param):
    img_grey = ocrolib.read_image_gray(imgpath)
    (h, w) = img_grey.shape[:2]
    img00 = cv2.resize(img_grey[h / 4:3 * h / 4, w / 4:3 * w / 4],
                       None,
                       fx=0.5,
                       fy=0.5)
    angle = estimate_skew_angle(img00, linspace(-5, 5, 42))
    print 'goc', angle

    rotM = cv2.getRotationMatrix2D((w / 2, h / 2), angle, 1)
    img_grey = cv2.warpAffine(img_grey, rotM, (w, h))

    h, w = img_grey.shape
    img_grey = cv2.normalize(img_grey.astype(float32), None, 0.0, 0.999,
                             cv2.NORM_MINMAX)
    binary = sauvola(img_grey,
                     w=param.w,
                     k=param.k,
                     scaledown=0.2,
                     reverse=True)  ### PARAM
    binary = morph.r_closing(binary.astype(bool), (args.connect, 1))
    binaryary = binary[h / 4:3 * h / 4, w / 4:3 * w / 4]
    binary = binary.astype(np.uint8)
    labels, n = morph.label(binaryary)
    objects = morph.find_objects(labels)

    bysize = sorted(objects, key=sl.area)
    scalemap = zeros(binaryary.shape)
    for o in bysize:
        if amax(scalemap[o]) > 0: continue
        scalemap[o] = sl.area(o)**0.5
    scale = median(scalemap[(scalemap > 3) & (scalemap < 100)])
    objects = psegutils.binary_objects(binary)
    boxmap = zeros(binary.shape, dtype=np.uint8)

    imgwidth = binary.shape[1]
    imgheight = binary.shape[0]
    cellwidth = 6 * scale
    cellheight = 2.5 * scale
    N_x = int(round(imgwidth / cellwidth))
    cellwidth = int(round(imgwidth / N_x))
    N_y = int(round(imgheight / cellheight))
    cellheight = int(round(imgheight / N_y))
    cells_list = [{}, {}, {}, {}]

    def pixel2cell2id(pixel_x, pixel_y, CELLTYPE):
        dx = 0
        dy = 0
        if CELLTYPE == 3:
            pixel_x -= cellwidth / 2
            pixel_y -= cellheight / 2
            dx = cellwidth / 2
            dy = cellheight / 2
        if CELLTYPE == 2:
            pixel_x -= cellwidth / 2
            dx = cellwidth / 2
        if CELLTYPE == 1:
            pixel_y -= cellheight / 2
            dy = cellheight / 2
        if pixel_x <= 0 or pixel_y <= 0: return None, None
        cellcoord = (pixel_x / cellwidth, pixel_y / cellheight)
        cellid = cellcoord[0] + cellcoord[1] * N_x
        cellcoord = (cellcoord[0] * cellwidth + dx,
                     cellcoord[1] * cellheight + dy)
        return cellcoord, cellid

    def id2cell2pixel(cellid, x, y, CELLTYPE):
        cellcoord = (cellid % N_x, cellid / N_x)
        pixel_x = cellcoord[0] * cellwidth + x
        pixel_y = cellcoord[1] * cellheight + y
        if CELLTYPE == 3:
            pixel_x += cellwidth / 2
            pixel_y += cellheight / 2
        return cellcoord, pixel_x, pixel_y

    img_grey = (cv2.cvtColor(img_grey, cv2.COLOR_GRAY2BGR) * 255).astype(
        np.uint8)

    for o in objects:
        h = sl.dim0(o)
        w = sl.dim1(o)
        ratio = float(w) / h
        ### Dirty cheat
        if ratio > 1 and ratio < 6:
            recommended_width = max(int(0.6 * (o[0].stop - o[0].start)),
                                    int(scale * 0.6), 5)
            for pos in range(o[1].start + recommended_width, o[1].stop,
                             recommended_width):
                binary[o[0].start:o[0].stop, pos:pos + 1] = np.uint8(0)
    objects = psegutils.binary_objects(binary)

    for o in objects:
        h = sl.dim0(o)
        w = sl.dim1(o)
        a = h * w
        #         black = float(sum(binary[o]))/a
        #         if sl.area(o)**.5<threshold[0]*scale: continue
        #         if sl.area(o)**.5>threshold[1]*scale: continue
        if h > 5 * scale: continue
        #         if h < 0.4*scale: continue
        if w > 4 * scale and (h > 2 * scale or h < 0.5 * scale): continue
        if a < 0.25 * scale * scale: continue
        if float(h) / w > 10: continue
        ratio = float(w) / h
        if ratio > 10: continue

        ### Add object as candidate character
        pixel_x, pixel_y = (o[1].start + o[1].stop) / 2, o[0].stop
        for celltype in range(4):
            cellcoord, cellid = pixel2cell2id(pixel_x,
                                              pixel_y,
                                              CELLTYPE=celltype)
            if cellcoord is None or cellid is None: continue
            cellbound = slice(cellcoord[1], cellcoord[1] + cellheight,
                              None), slice(cellcoord[0],
                                           cellcoord[0] + cellwidth, None)
            if cellid not in cells_list[celltype]:
                cells_list[celltype][cellid] = SubLineFinder(
                    window_size=max(3, scale / 6),
                    cellbound=cellbound,
                    initChar=o)
            else:
                cells_list[celltype][cellid].addChar(o)

        y0 = o[0].start
        y1 = o[0].stop - 3 if o[0].stop - o[0].start > 8 else o[0].start + 5
        x0 = o[1].start
        x1 = o[1].stop - 3 if o[1].stop - o[1].start > 8 else o[1].start + 5
        boxmap[y0:y1, x0:x1] = 1

    for celltype in range(4):
        if celltype == 0: col = (255, 0, 0)
        if celltype == 1: col = (0, 255, 0)
        if celltype == 2: col = (255, 255, 0)
        if celltype == 3: col = (0, 0, 255)
        for cellid, subline in cells_list[celltype].iteritems():
            #             cv2.rectangle(img_grey, (subline.cellbound[1].start+celltype, subline.cellbound[0].start+celltype), (subline.cellbound[1].stop+celltype, subline.cellbound[0].stop+celltype), col,1)
            line = subline.subline()
            if line is not None:
                pos1 = (int(line[0][0]), int(line[0][1]))
                pos2 = (int(line[1][0]), int(line[1][1]))
                #                 print cellid, pos1, pos2
                cv2.line(img_grey, pos1, pos2, col, 1)
    ### illustrate/debug first round

    return binary, cv2.add(img_grey, (boxmap[:, :, np.newaxis] *
                                      np.array([0, 50, 50])).astype(np.uint8))