def create_screen_paper(self, resolution): # it seems value is useless, its zero... # why does this need to be four dimensional data = numpy.zeros((resolution[1], resolution[0], 4)) # data = numpy.zeros((200, 200, 4)) self.ptr = coordinate_functions.prime_ self.color_ptr = color_r_x_g_y_b_y for (x_coor, y_coor, z), value in numpy.ndenumerate(data): if self.ptr(x_coor, y_coor): data[x_coor, y_coor] = self.color_ptr(x_coor, y_coor) im = Image.fromarray(data.astype('uint8'), 'RGBA') ImageShow.register(Feh, -500) ImageShow.show(im) return im
def visualize(solution): print solution.solution image = Image.new('L', (len(solution.solution[0]) * SIDE_LENGTH, len(solution.solution) * SIDE_LENGTH)) pixels = image.load() for x in range(len(solution.solution[0])): for y in range(len(solution.solution)): for i in range(SIDE_LENGTH): for j in range(SIDE_LENGTH): curr_x = x * SIDE_LENGTH + i curr_y = y * SIDE_LENGTH + j if solution.solution[y][x] == 0: pixels[curr_x, curr_y] = 255 else: pixels[curr_x, curr_y] = 0 ImageShow.show(image, 'solution') image.save('fakesolution.jpg')
def find_numbers(puzzlegrid, skewless_picture, pic_name): positions = [] width, height = skewless_picture.size print "image size: ", width, height # traverse grid, determine min/max x and y coords min_x = int(puzzlegrid.grid[0][0]) max_x = int(puzzlegrid.grid[1][0]) min_y = int(puzzlegrid.grid[0][1]) max_y = int(puzzlegrid.grid[1][1]) # sort coordinates in ascending order puzzlegrid.x_coords = sorted(puzzlegrid.x_coords) puzzlegrid.y_coords = sorted(puzzlegrid.y_coords) print "min x, max x: ", min_x, max_x print "min_y, max_y: ", min_y, max_y # convert image to grayscale array grayscale_picture = skewless_picture.convert("L") pixels = grayscale_picture.load() # calculate average change in color per cell # compare to threshold, if greater, has number THRES_LOW = 2000 #?? THRES_HIGH = 10000 # top top = [] for x in puzzlegrid.x_coords: if x == max_x: continue x_list = [] for y in range(min_y - puzzlegrid.cell_height, 0, -puzzlegrid.cell_height): # calculate average average = 0 for k in range(puzzlegrid.cell_width): for l in range(puzzlegrid.cell_height): curr_x = x + k curr_y = y + l average += pixels[curr_x, curr_y] #?? average /= (puzzlegrid.cell_width * puzzlegrid.cell_height) # calculate variance variance = 0 for k in range(puzzlegrid.cell_width): for l in range(puzzlegrid.cell_height): curr_x = x + k curr_y = y + l variance += pow(pixels[curr_x, curr_y] - average, 2) #?? variance /= (puzzlegrid.cell_width * puzzlegrid.cell_height) # has number, save cell top-left corner in positions if variance > THRES_LOW and variance < THRES_HIGH: x_list.append((x, y)) positions.append((x, y)) else: break top.append(x_list) # left side = [] for y in puzzlegrid.y_coords: if y == max_y: continue y_list = [] for x in range(min_x - puzzlegrid.cell_width, 0, -puzzlegrid.cell_width): # calculate average average = 0 for k in range(puzzlegrid.cell_width): for l in range(puzzlegrid.cell_height): curr_x = x + k curr_y = y + l average += pixels[curr_x, curr_y] #?? average /= (puzzlegrid.cell_width * puzzlegrid.cell_height) # calculate variance variance = 0 for k in range(puzzlegrid.cell_width): for l in range(puzzlegrid.cell_height): curr_x = x + k curr_y = y + l variance += pow(pixels[curr_x, curr_y] - average, 2) #?? variance /= (puzzlegrid.cell_width * puzzlegrid.cell_height) # has number, save cell top-left corner in positions if variance > THRES_LOW and variance < THRES_HIGH: y_list.append((x, y)) positions.append((x, y)) else: break side.append(y_list) if DRAW: draw = ImageDraw.Draw(skewless_picture) BOXSIZE = 3 for point in positions: ptx = point[0] pty = point[1] draw.rectangle( [ptx - BOXSIZE, pty - BOXSIZE, ptx + BOXSIZE, pty + BOXSIZE], fill=128) del draw ImageShow.show(skewless_picture, 'with points') skewless_picture.save('./images/intermediate/' + pic_name + '_foundnumbers.jpg') # save training images if TRAIN: for point in positions: ptx = int(point[0]) pty = int(point[1]) picture = skewless_picture.crop([ ptx, pty, ptx + puzzlegrid.cell_width, pty + puzzlegrid.cell_height ]) picture.save("./images/train/{0}_{1}_{2}.jpg".format( pic_name, ptx, pty)) digits = Representations.DigitsRep(top, side) print "top" print digits.top print "side" print digits.side return digits # digits representation
def find_numbers(puzzlegrid, skewless_picture, pic_name): positions = [] width, height = skewless_picture.size print "image size: ", width, height # traverse grid, determine min/max x and y coords min_x = int(puzzlegrid.grid[0][0]) max_x = int(puzzlegrid.grid[1][0]) min_y = int(puzzlegrid.grid[0][1]) max_y = int(puzzlegrid.grid[1][1]) # sort coordinates in ascending order puzzlegrid.x_coords = sorted(puzzlegrid.x_coords) puzzlegrid.y_coords = sorted(puzzlegrid.y_coords) print "min x, max x: ", min_x, max_x print "min_y, max_y: ", min_y, max_y # convert image to grayscale array grayscale_picture = skewless_picture.convert("L") pixels = grayscale_picture.load() # calculate average change in color per cell # compare to threshold, if greater, has number THRES_LOW = 2000 #?? THRES_HIGH = 10000 # top top = [] for x in puzzlegrid.x_coords: if x == max_x: continue x_list = [] for y in range(min_y - puzzlegrid.cell_height, 0, -puzzlegrid.cell_height): # calculate average average = 0 for k in range(puzzlegrid.cell_width): for l in range(puzzlegrid.cell_height): curr_x = x + k curr_y = y + l average += pixels[curr_x, curr_y] #?? average /= (puzzlegrid.cell_width * puzzlegrid.cell_height) # calculate variance variance = 0 for k in range(puzzlegrid.cell_width): for l in range(puzzlegrid.cell_height): curr_x = x + k curr_y = y + l variance += pow(pixels[curr_x, curr_y] - average, 2) #?? variance /= (puzzlegrid.cell_width * puzzlegrid.cell_height) # has number, save cell top-left corner in positions if variance > THRES_LOW and variance < THRES_HIGH: x_list.append((x, y)) positions.append((x, y)) else: break top.append(x_list) # left side = [] for y in puzzlegrid.y_coords: if y == max_y: continue y_list = [] for x in range(min_x - puzzlegrid.cell_width, 0, -puzzlegrid.cell_width): # calculate average average = 0 for k in range(puzzlegrid.cell_width): for l in range(puzzlegrid.cell_height): curr_x = x + k curr_y = y + l average += pixels[curr_x, curr_y] #?? average /= (puzzlegrid.cell_width * puzzlegrid.cell_height) # calculate variance variance = 0 for k in range(puzzlegrid.cell_width): for l in range(puzzlegrid.cell_height): curr_x = x + k curr_y = y + l variance += pow(pixels[curr_x, curr_y] - average, 2) #?? variance /= (puzzlegrid.cell_width * puzzlegrid.cell_height) # has number, save cell top-left corner in positions if variance > THRES_LOW and variance < THRES_HIGH: y_list.append((x, y)) positions.append((x, y)) else: break side.append(y_list) if DRAW: draw = ImageDraw.Draw(skewless_picture) BOXSIZE = 3 for point in positions: ptx = point[0] pty = point[1] draw.rectangle([ptx-BOXSIZE, pty-BOXSIZE, ptx+BOXSIZE, pty+BOXSIZE], fill=128) del draw ImageShow.show(skewless_picture, 'with points') skewless_picture.save('./images/intermediate/' + pic_name + '_foundnumbers.jpg') # save training images if TRAIN: for point in positions: ptx = int(point[0]) pty = int(point[1]) picture = skewless_picture.crop([ptx, pty, ptx + puzzlegrid.cell_width, pty + puzzlegrid.cell_height]); picture.save("./images/train/{0}_{1}_{2}.jpg".format(pic_name, ptx, pty)) digits = Representations.DigitsRep(top, side) print "top" print digits.top print "side" print digits.side return digits # digits representation
def fix_skew(pic_name, picture): accumulator = {} # (theta, rho): num_votes found_points = {} rotation = 0; # convert image to grayscale array grayscale_picture = picture.convert("L") pixels = grayscale_picture.load() # traverse pixels in image to vote width, height = picture.size THRES_BLACK = 30 for x in range(width): for y in range(height): # check if pixel is "black" if pixels[x, y] < THRES_BLACK: # 180 lines through (x, y), vote THETA_RANGE = 10 for theta in range(-1 * THETA_RANGE, THETA_RANGE): rho = round(x * math.cos(theta) + y * math.sin(theta)) ac_key = (theta, rho) if ac_key not in accumulator: accumulator[ac_key] = 1 found_points[ac_key] = [] else: accumulator[ac_key] += 1 found_points[ac_key].append((x, y)) # find (theta, rho) with most votes max_votes = 0 max_key = (0,0) for key in accumulator: if accumulator[key] > max_votes: max_votes = accumulator[key] # num_votes max_key = key print "votes: ", max_votes print "key: ", max_key # draw points associated with max key # find min y value to crop if DRAW: draw = ImageDraw.Draw(picture) BOXSIZE = 3 min_y = 0 for point in found_points[max_key]: ptx = point[0] pty = point[1] if (pty > min_y): min_y = pty draw.rectangle([ptx-BOXSIZE, pty-BOXSIZE, ptx+BOXSIZE, pty+BOXSIZE], fill=128) del draw ImageShow.show(picture, 'with points') image.save('./images/intermediate/' + pic_name + '_getpicture_line.jpg') # perform rotation & composite to make bkg white # source: http://stackoverflow.com/questions/5252170/ # specify-image-filling-color-when-rotating-in-python-with-pil-and-setting-expand picture = picture.convert('RGBA') picture = picture.rotate(max_key[0], expand=True) white = Image.new('RGBA', picture.size, (255,)*4) picture = Image.composite(picture, white, picture) width, height = picture.size ImageShow.show(picture, 'anti-skewed') picture.save('./images/intermediate/' + pic_name + '_antiskewed.jpg') return picture # picture
min_y = pty draw.rectangle([ptx-BOXSIZE, pty-BOXSIZE, ptx+BOXSIZE, pty+BOXSIZE], fill=128) del draw ImageShow.show(picture, 'with points') image.save('./images/intermediate/' + pic_name + '_getpicture_line.jpg') # perform rotation & composite to make bkg white # source: http://stackoverflow.com/questions/5252170/ # specify-image-filling-color-when-rotating-in-python-with-pil-and-setting-expand picture = picture.convert('RGBA') picture = picture.rotate(max_key[0], expand=True) white = Image.new('RGBA', picture.size, (255,)*4) picture = Image.composite(picture, white, picture) width, height = picture.size ImageShow.show(picture, 'anti-skewed') picture.save('./images/intermediate/' + pic_name + '_antiskewed.jpg') return picture # picture # testing main if __name__=='__main__': pic_name = 'blue_9_crop' test_pic = './images/' + pic_name + '.jpg' image = Image.open(test_pic) fixed = fix_skew(pic_name, image) ImageShow.show(fixed, 'skew removed')
def picture(pic_name, test_pic): image = Image.open(test_pic) # flip along vertical axis image = image.transpose(Image.FLIP_LEFT_RIGHT) # preprocess: trim to game screen image = image.convert('L') pixels = image.load(); width, height = image.size center = (width/2, height/2) # center intensity should be in DS screen and therefore above some threshold cent_x = center[0] cent_y = center[1] screen_intensity = (pixels[center] + pixels[cent_x-1, cent_y-1] + pixels[cent_x-1, cent_y] + pixels[cent_x-1, cent_y+1] + pixels[cent_x, cent_y-1] + pixels[cent_x, cent_y+1] + pixels[cent_x+1, cent_y-1] + pixels[cent_x+1, cent_y] + pixels[cent_x+1, cent_y+1]) / 9. X_INC = width / 100 Y_INC = height / 100 THRES_DIFF = 40 NEIGH_SIZE = 5 # get max x of screen border prev_intensity = screen_intensity potential_border = width for x in range(center[0] + X_INC, width, X_INC): # get average of neighborhood average_intensity = 0 num_pixels = 0 for x_offset in range(-1 * NEIGH_SIZE, 1 * NEIGH_SIZE): neigh_x = x + x_offset # if within image, factor into average if neigh_x < 0 or neigh_x >= width: continue for y_offset in range(-1 * NEIGH_SIZE, 1 * NEIGH_SIZE): neigh_y = cent_y + y_offset # if within image, factor into average if neigh_y < 0 or neigh_y >= height: continue average_intensity += pixels[neigh_x, neigh_y] num_pixels += 1 average_intensity = average_intensity / num_pixels if abs(average_intensity - prev_intensity) > THRES_DIFF: if potential_border < width: break potential_border = x else: potential_border = width prev_intensity = average_intensity max_x = potential_border print max_x # get min x of screen border prev_intensity = screen_intensity potential_border = 0 for x in range(center[0] - X_INC, 0, -1 * X_INC): # get average of neighborhood average_intensity = 0 num_pixels = 0 for x_offset in range(-1 * NEIGH_SIZE, 1 * NEIGH_SIZE): neigh_x = x + x_offset # if within image, factor into average if neigh_x < 0 or neigh_x >= width: continue for y_offset in range(-1 * NEIGH_SIZE, 1 * NEIGH_SIZE): neigh_y = cent_y + y_offset # if within image, factor into average if neigh_y < 0 or neigh_y >= height: continue average_intensity += pixels[neigh_x, neigh_y] num_pixels += 1 average_intensity = average_intensity / num_pixels if abs(average_intensity - prev_intensity) > THRES_DIFF: if potential_border > 0: break potential_border = x else: potential_border = 0 prev_intensity = average_intensity min_x = potential_border print min_x # get max y of screen border prev_intensity = screen_intensity potential_border = height for y in range(center[1] + Y_INC, height, Y_INC): # get average of neighborhood average_intensity = 0 num_pixels = 0 for x_offset in range(-1 * NEIGH_SIZE, 1 * NEIGH_SIZE): neigh_x = cent_x + x_offset # if within image, factor into average if neigh_x < 0 or neigh_x >= width: continue for y_offset in range(-1 * NEIGH_SIZE, 1 * NEIGH_SIZE): neigh_y = y + y_offset # if within image, factor into average if neigh_y < 0 or neigh_y >= height: continue average_intensity += pixels[neigh_x, neigh_y] num_pixels += 1 average_intensity = average_intensity / num_pixels if abs(average_intensity - prev_intensity) > THRES_DIFF: if potential_border < height: break potential_border = y else: potential_border = height prev_intensity = average_intensity max_y = potential_border print max_y # get min y of screen border prev_intensity = screen_intensity potential_border = 0 for y in range(center[1] - Y_INC, 0, -1 * Y_INC): # get average of neighborhood average_intensity = 0 num_pixels = 0 for x_offset in range(-1 * NEIGH_SIZE, 1 * NEIGH_SIZE): neigh_x = cent_x + x_offset # if within image, factor into average if neigh_x < 0 or neigh_x >= width: continue for y_offset in range(-1 * NEIGH_SIZE, 1 * NEIGH_SIZE): neigh_y = y + y_offset # if within image, factor into average if neigh_y < 0 or neigh_y >= height: continue average_intensity += pixels[neigh_x, neigh_y] num_pixels += 1 average_intensity = average_intensity / num_pixels if abs(average_intensity - prev_intensity) > THRES_DIFF: if potential_border > 0: break potential_border = y else: potential_border = 0 prev_intensity = average_intensity min_y = potential_border print min_y """pixels = list(image.getdata()) width, height = image.size (both, hor_filt, vert_filt) = prewitt.prewitt(pixels, width, height) prewitt_pixels = both.load() # edge detect on "both" with very high threshold for intensity horiz = {} vert = {} # traverse pixels in a direction # if intensity greater than threshold, vote for value and neighborhood THRES_BLACK = 70 NEIGH_SIZE = 5 for x in range(width): for y in range(height): if prewitt_pixels[x, y] < THRES_BLACK: # pixel only votes if direct neighborhood is dark # check if average intensity of direct neighborhood over threshold average_intensity = 0 num_pixels = 0 for x_offset in range (-1, 1): neigh_x = x + x_offset # if within image, factor into average if neigh_x < 0 or neigh_x >= width: continue for y_offset in range (-1, 1): neigh_y = y + y_offset # if within image, factor into average if neigh_y < 0 or neigh_y >= height: continue average_intensity += prewitt_pixels[x + x_offset, y+y_offset] num_pixels += 1 average_intensity = average_intensity / num_pixels if average_intensity >= THRES_BLACK: continue # if neighborhood dark enough # pixel votes for everything in neighborhood # horizontal: x voting for x_offset in range (-1 * NEIGH_SIZE, NEIGH_SIZE): neigh_x = x + x_offset # if within image, increment if neigh_x < 0 or neigh_x >= width: continue if neigh_x not in horiz: horiz[neigh_x] = 1 else: horiz[neigh_x] += 1 # vertical: y voting for y_offset in range (-1 * NEIGH_SIZE, NEIGH_SIZE): neigh_y = y + y_offset # if within image, increment if neigh_y < 0 or neigh_y >= height: continue if neigh_y not in vert: vert[neigh_y] = 1 else: vert[neigh_y] += 1 # look in appropriate dictionaries for max/min x/y values horiz = sorted(horiz.iteritems(), key=lambda (k,v): (v,k)) vert = sorted(vert.iteritems(), key=lambda (k,v): (v,k)) x1 = horiz[len(horiz)-1][0] x2 = x1 y1 = vert[len(vert)-1][0] y2 = y1 FRACTION = .2 MIN_DIST_X = FRACTION * width x_index = len(horiz)-1 while abs(x2 - x1) < MIN_DIST_X: x2 = horiz[x_index][0] x_index -= 1 MIN_DIST_Y = FRACTION * height y_index = len(vert)-1 while abs(y2 - y1) < MIN_DIST_Y: y2 = vert[y_index][0] y_index -=1 min_x = min(x1, x2) max_x = max(x1, x2) min_y = min(y1, y2) max_y = max(y1, y2)""" if DRAW: draw = ImageDraw.Draw(image) draw.line((min_x, 0, min_x, height), fill=128) draw.line((max_x, 0, max_x, height), fill=128) draw.line((0, min_y, width, min_y), fill=128) draw.line((0, max_y, width, max_y), fill=128) del draw ImageShow.show(image, 'with points') image.save('./images/intermediate/' + pic_name + '_getpicture_precrop.jpg') # crop image BUFFER = 5 min_x = max(0, min_x - BUFFER) max_x = min(width - 1, max_x + BUFFER) min_y = max(0, min_y - BUFFER) max_y = min(height - 1, max_y + BUFFER) image = image.crop([min_x, min_y, max_x, max_y]); image.save('./images/intermediate/' + pic_name + '_getpicture_cropped.jpg') return image # picture
if DRAW: draw = ImageDraw.Draw(image) draw.line((min_x, 0, min_x, height), fill=128) draw.line((max_x, 0, max_x, height), fill=128) draw.line((0, min_y, width, min_y), fill=128) draw.line((0, max_y, width, max_y), fill=128) del draw ImageShow.show(image, 'with points') image.save('./images/intermediate/' + pic_name + '_getpicture_precrop.jpg') # crop image BUFFER = 5 min_x = max(0, min_x - BUFFER) max_x = min(width - 1, max_x + BUFFER) min_y = max(0, min_y - BUFFER) max_y = min(height - 1, max_y + BUFFER) image = image.crop([min_x, min_y, max_x, max_y]); image.save('./images/intermediate/' + pic_name + '_getpicture_cropped.jpg') return image # picture if __name__=='__main__': result = picture('webcam', './images/webcam.jpg') ImageShow.show(result, "window title")
def detect_lines(picture, name): if picture.mode != 'L' : picture = picture.convert('L') pixels = list(picture.getdata()) width, height = picture.size (both, hor_filt, vert_filt) = prewitt.prewitt(pixels, width, height) picture.save("./images/original.jpg") v = "vertical" h = "horizontal" (saved, xcoords) = detect_hv_lines(hor_filt,h) (savedy, ycoords) = detect_hv_lines(vert_filt,v) paint_lines(hor_filt,saved,h).save("./images/saveda.jpg") paint_lines(vert_filt,savedy,v).save("./images/savedv.jpg") # we'll trust the max coordinates as those are near the edge of the image # and are unlikely to be mistaken compared to the min coordinates max_x = max(xcoords) max_y = max(ycoords) min_x = min(xcoords) min_y = min(ycoords) projected_avg_x = (max_x-min_x)/global_board_size projected_avg_y = (max_y-min_y)/global_board_size avg_x = vote_avg_diff(xcoords) avg_y = vote_avg_diff(ycoords) #avg = (avg_x+avg_y)/2 print "avg x diff: ", projected_avg_x print "avg y diff: ", projected_avg_y print "voted x df: ", avg_x print "voted y df: ", avg_y # get an evenly spaced set of lines xcoords = extrapolate_coords(max_x, projected_avg_x) ycoords = extrapolate_coords(max_y, projected_avg_y) #xcoords = extrapolate_coords(max_x, avg_x) #ycoords = extrapolate_coords(max_y, avg_y) paintedh = paint_lines(hor_filt,xcoords,h) paintedh.save("./images/painted_lines_hor_"+name+".jpg") paintedv = paint_lines(vert_filt, ycoords,v) paintedv.save("./images/painted_lines_vert_"+name+".jpg") combined = Image.blend(paintedv, paintedh, 0.5) grid_coords = [] max_x = max(xcoords) min_x = min(xcoords) max_y = max(ycoords) min_y = min(ycoords) grid_coords.append((min_y,min_x)) grid_coords.append((max_y,max_x)) print "grid_coords:" print grid_coords if DRAW: draw = ImageDraw.Draw(combined) draw.rectangle(grid_coords,outline=128) del draw combined.save("./images/painted_lines_both_"+name+".jpg") ImageShow.show(combined,"blah") # return a Grid Representation of this solution cell_width = max(1, projected_avg_x) cell_height = max(1, projected_avg_y) gr = Representations.GridRep(grid_coords, ycoords, xcoords, cell_height, cell_width) return gr