#! /usr/bin/python from PIL import Image import Image, ImageDraw import sys import numpy def PixelGood(pixel, threshold): #print str(pixel) return GreyScale(pixel) < threshold; #return (pixel[1] > (pixel[0] + pixel[2]) and pixel[1] > threshold) def rect_size(e): return (e[3] - e[1]) * (e[2] - e[0]) def GreyScale(pixel): greyscale = 0 for i in range(0, len(pixel)): greyscale += pixel[i] greyscale = greyscale / len(pixel) return greyscale def SubDivide(pix, bounds, fill_fraction=0.1, threshold=200, seperation=5, min_area=1000): rect = [] xStart = bounds[2] xEnd = bounds[0] yStart = bounds[3] yEnd = bounds[1] xLast = bounds[0] good = 0 for x in range(bounds[0], bounds[2]): for y in range(bounds[1], bounds[3]): if PixelGood(pix[x, y], threshold): if (x - xLast) > seperation: if ((xEnd - xStart) * (yEnd - yStart) > min_area): rect.append([xStart, yStart, xEnd, yEnd]) xStart = bounds[2] xEnd = bounds[0] yStart = bounds[3] yEnd = bounds[1] good = 0 if (x < xStart): xStart = x if (y < yStart): yStart = y if (x > xEnd): xEnd = x if (y > yEnd): yEnd = y xLast = x good += 1 return rect def Process(fileName, digits): results = [] image = Image.open(fileName) pix = image.load() rect = SubDivide(pix, (0, 0, image.size[0], image.size[1])) #print "Found " + str(len(rect)) + " rectangles" test = Image.new("RGB", image.size, "white") test.paste(image) draw1 = ImageDraw.Draw(test) for i in range(0, len(rect)): #draw1.rectangle(rect[i], fill=None, outline="red") #img.show() closest = PickClosest(pix, rect[i], digits) print("Best result is " + str(closest)) if (closest == None or closest[1] < 0.0): img = Image.new("RGB", (rect[i][2]-rect[i][0], rect[i][3]-rect[i][1]), "white") draw2 = ImageDraw.Draw(img) for x in range(rect[i][0], rect[i][2]): for y in range(rect[i][1], rect[i][3]): draw2.rectangle((x-rect[i][0], y-rect[i][1], x-rect[i][0], y-rect[i][1]), fill=pix[x, y], outline=None) img.show() sys.stdout.write("Enter digit: ") closest = (int(sys.stdin.readline().strip("\r\n ")), 1) img.save(str(closest[0])+".png") results.append(closest[0]) return results def PixToList(pix, bounds): a = [] for x in range(bounds[0], bounds[2]): a.append([]) for x in range(bounds[0], bounds[2]): for y in range(bounds[1], bounds[3]): a[x - bounds[0]].append(GreyScale(pix[x, y])) #print(str(x) + "," + str(y), len(fft[x - bounds[0]])) #print(str(fft[x - bounds[0]][y - bounds[1]])) return a def PickClosest(pix, bounds, digits, boxes): scores = [] a = numpy.array(PixToList(pix, bounds)) b = abs(numpy.fft.rfft2(a)) #Image.fromarray(b).show() for d in digits: score = 0 for x in range(0, len(b)): for y in range(0, len(b[x])): if (x >= len(d[1]) or y >= len(d[1][x])): score -= 1 else: score -= abs(b[x][y] - d[1][x][y]) scores.append([d[0], float(score)]) return sorted(scores, key = lambda e : e[1], reverse = False)[0] if __name__ == "__main__": if (len(sys.argv) != 2): print("Usage " + str(sys.argv[0]) + " input_image") digits = [] for i in range(0, 10): try: digit = Image.open(str(i)+".png") except: continue digits.append((i, digit.load(), digit.size)) #sys.exit(0) r = Process(sys.argv[1], digits) print(str(r[0]) + "." + str(r[1]) + str(r[2]) + "e-"+str(r[3])) sys.exit(0)