Example #1
0
def solve_monkey(dist = False):
    path = 'screenshots/%s.png' % datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
    print('Taking screenshot')
    call(['monkeyrunner', 'monkeyscreen.py', path])
    print('Rotating')
    call(['convert', '-rotate',  '90', path, path])
    
    print('Starting image solver')
    val, xmarks, ymarks = solve_image(path, dist)
    
    print('Generating solution path')
    pathparts = splitext(path)
    pathsol = '%s.sol_path.txt' % pathparts[0]
    solfile = open(pathsol, 'w')
    
    level = Level()
    level.rows = len(val)
    level.cols = len(val[0]) 
    for x, y in product(range(level.cols), range(level.rows)):
        c, t = val[y][x][0]
        if t != 0:
            continue
        #print('Tracing color', c)
        # Found a dot, start
        cx, cy, ct = x, y, 0
        while True:
            # Print current
            #print(cx, cy, ct)
            solfile.write('%d %d\n' % (avg([xmarks[cx], xmarks[cx+1]]), avg([ymarks[cy], ymarks[cy+1]])))
            # Find next
            cx2, cy2, ct2 = -1, -1, -1
            for nx, ny in level.neighbors(cx, cy):
                nc, nt = val[ny][nx][0]
                if nc >= 0 and connects(cx, cy, ct, nx, ny, nt):
                    cx2 = nx
                    cy2 = ny
                    ct2 = nt
                    break
            # Found nothing - done
            if cx2 == -1:
                break
            # Delete current and replace with next
            val[cy][cx][0] = -1, -1
            cx = cx2
            cy = cy2
            ct = ct2
        # Delete last
        val[cy][cx][0] = -1, -1
        solfile.write('0 0\n')
    solfile.close()
    
    print('Solving on device')
    call(['monkeyrunner', 'monkeypath.py', pathsol])
    
    print('DONE')
Example #2
0
def parse_image(path, pathcrop):
    img = Image.open(path)
    pix = img.load()

    # TODO proper line detection instead of color matching
    #border_color = (131, 97, 66) # brown
    #border_color = (123, 125, 66) # green
    border_color = pix[2, 180]
    border_threshold = 128

    xbuckets = defaultdict(int)
    ybuckets = defaultdict(int)

    # Find borders
    for pos in product(xrange(img.size[0]), xrange(img.size[1])):
        col = pix[pos]
        dist2 = color_dist2(col, border_color)
        if dist2 < border_threshold:
            xbuckets[pos[0]] += 1
            ybuckets[pos[1]] += 1

    # Throw away below average (keeps the main lines)
    xbuckets = {k:v for k,v in xbuckets.items() if v > avg(xbuckets.values())}
    ybuckets = {k:v for k,v in ybuckets.items() if v > avg(ybuckets.values())}

    # Merge neighbor buckets
    xmarks = sorted(merge_buckets(xbuckets).keys())
    ymarks = sorted(merge_buckets(ybuckets).keys())

    #pprint(xmarks)
    #pprint(ymarks)

    # Figure out coordinates
    minx, miny, maxx, maxy = avg([xmarks[0], xmarks[1]]), avg([ymarks[0], ymarks[1]]), avg([xmarks[-1], xmarks[-2]]), avg([ymarks[-1], ymarks[-2]])
    xsize = len(xmarks) - 1
    ysize = len(ymarks) - 1

    level = Level()
    level.cols = xsize
    level.rows = ysize
    level.tiles = [[None for i in range(xsize)] for j in range(ysize)]

    circle_ratio = 0.4
    out_ratio = 0.8
    circle_threshold = 128
    out_threshold = 1024

    color_map = {}
    map_threshold = 32

    for i, j in product(range(xsize), range(ysize)):
        x, y = avg([xmarks[i], xmarks[i+1]]), avg([ymarks[j], ymarks[j+1]])
        w = min(xmarks[i+1] - xmarks[i], ymarks[j+1] - ymarks[j])

        # Ignore empty
        if pix[x, y] == (0, 0, 0):
            continue

        center = avg_color([pix[x+a, y+b] for a,b in product([-1, 0, 1], [-1, 0, 1])])

        inside = sample(pix, x, y, w*circle_ratio/2, 8)
        inside_dist2 = avg([color_dist2(center, ic) for ic in inside])

        if inside_dist2 > circle_threshold:
            #print('IN Rejecting ', i, j)
            #print(inside)
            #print(inside_dist2)
            continue

        outside = sample(pix, x, y, w*out_ratio/2, 8)
        outside_dist2 = avg([color_dist2(center, oc) for oc in outside])

        if outside_dist2 < out_threshold:
            #print('OUT Rejecting ', i, j)
            #print(outside)
            #print(outside_dist2)
            continue

        id = None
        for k, v in color_map.items():
            if color_dist2(k, center) < map_threshold:
                id = v
                #print(x,y, 'id=', v)

        if id is None:
            id = len(color_map)
            color_map[center] = id

        level.tiles[j][i] = id

        ImageDraw.Draw(img).ellipse((x-w/5-1, y-w/5-1, x+w/5+1, y+w/5+1), fill = 'black')
        ImageDraw.Draw(img).ellipse((x-w/5, y-w/5, x+w/5, y+w/5), fill = 'white')
        ImageDraw.Draw(img).text((x+1, y), str(id), fill = 'black')
        ImageDraw.Draw(img).text((x-1, y), str(id), fill = 'black')
        ImageDraw.Draw(img).text((x, y+1), str(id), fill = 'black')
        ImageDraw.Draw(img).text((x, y-1), str(id), fill = 'black')
        ImageDraw.Draw(img).text((x, y), str(id), fill = 'white')

    level.colors = len(color_map)

    img = img.crop((xmarks[0], ymarks[0], xmarks[-1], ymarks[-1]))
    img = img.resize((int(img.size[0]*0.75), int(img.size[1]*0.75)))
    img.show()
    img.save(pathcrop)

    return (level, {v:k for k,v in color_map.items()}, xmarks, ymarks)