import Image
import time
import math
import sys
sys.setrecursionlimit(20000)
class OCR:
def __init__(self, image_fn):
self.image_fn = image_fn
self.im = Image.open(image_fn)
self.pixels = self.im.load()
self.debug_im = Image.open(image_fn)
self.debug_pixels = self.debug_im.load()
def start(self):
self.done = []
#self.get_borders()
run = self.run_vector(FindBorder, (0,0), (1,1), True)
self.get_borders(run.cpixel)
self.im.save("/tmp/aa.png")
self.debug_im.save("/tmp/bb.png")
def run_vector(self, runner, *args, **kwargs):
run = runner(self.pixels, self.debug_pixels, *args, **kwargs)
return run
def similar_pixels_by_vector(self, run_vector, max_diff=30, max_distance=10):
pixel = run_vector.cpixel
def similar_pixels(self, pixel, max_diff=30):
similars = {}
color = self.pixels[pixel]
for pixel2 in self.around_pixels(pixel):
try:
color2 = self.pixels[pixel2]
except IndexError:
print pixel2, self.im.size
time.sleep(2)
continue
# the difference for each RGB values in the two pixels
diff = map(lambda a,b: abs(a-b), color, color2)
average_diff = (diff[0]+diff[1]+diff[2])/3
if average_diff < max_diff:
similars[pixel2] = average_diff
# order by most similar pixels first
similars_sorted = sorted(similars, key=similars.__getitem__)
return similars_sorted
def around_pixels(self, pixel):
around = []
for i in range(8):
# pixels start in the up left corner and go on clockwise
if i == 0: pixel2 = (pixel[0]-1, pixel[1]-1)
if i == 1: pixel2 = (pixel[0], pixel[1]-1)
if i == 2: pixel2 = (pixel[0]+1, pixel[1]-1)
if i == 3: pixel2 = (pixel[0]+1, pixel[1])
if i == 4: pixel2 = (pixel[0]+1, pixel[1]+1)
if i == 5: pixel2 = (pixel[0], pixel[1]+1)
if i == 6: pixel2 = (pixel[0]-1, pixel[1]+1)
if i == 7: pixel2 = (pixel[0]-1, pixel[1])
if pixel2[0] < 0 or pixel2[1] < 0 or \
pixel2[0] >= self.im.size[0] or pixel2[1] >= self.im.size[1]:
continue
else:
around.append(pixel2)
return around
def get_borders(self, pixel):
#run = self.run_vector(FindBorder, (self.im.size[0]-1,self.im.size[1]-1),(-1,-1), True)
#run = self.run_vector(FindBorder, (self.im.size[0]-1,0),(-1,1), True)
#run = self.run_vector(FindBorder, (0,self.im.size[1]-1),(1,-1), True)
self.debug_pixels[pixel] = (255,0,0)
self.done.append(pixel)
sim = self.similar_pixels(pixel, 40)
if not len(self.done)%1000:
print len(sim), len(self.done)
for x in sim:
if x not in self.done:
self.get_borders(x)
def fg_color(self):
pass
class RunVector:
def __init__(self, pixels, debug_pixels, start, vector, run_now=False, callback=None):
self.pixels = pixels
self.debug_pixels = debug_pixels
self.vector = vector
self.cpos = start # cpos->current position
self.cpixel = start # cpixel->current pixel
self.trace = [start]
if callback:
self.callback = callback
if run_now:
self.run()
def debug(self, msg, error=False):
out_msg = ""
if type(msg) in [list, tuple]:
for x in msg:
if type(x) != str: x = repr(x)
out_msg += x+" "
elif type(msg) != str:
out_msg = repr(msg)
else:
out_msg = msg
if error: error = "==ERROR== "
else: error = ""
print "%s<%s>: %s" % (error, self.__class__.__name__, out_msg)
def run(self):
if max([abs(x) for x in self.vector]) == abs(self.vector[0]):
maxv = "x"
diff = abs(float(self.vector[1]) / self.vector[0])
else:
maxv = "y"
diff = abs(float(self.vector[0]) / self.vector[1])
while 1:
if len(self.trace) > 1:
if maxv == "x":
self.cpos = self.cpos[0]+math.copysign(1, self.vector[0]),\
self.cpos[1]+math.copysign(diff,self.vector[1])
elif maxv == "y":
self.cpos=self.cpos[0]+math.copysign(diff,self.vector[0]),\
self.cpos[1]+math.copysign(1, self.vector[1])
self.cpixel = int(self.cpos[0]), int(self.cpos[1])
if self.callback():
return
else:
self.trace.append(self.cpixel)
def trace_colors(self):
return [self.pixels[x] for x in self.trace]
class FindBorder(RunVector):
def callback(self):
#self.debug((self.cpixel, self.pixels[self.cpixel]))
if self.pixels[self.cpixel] not in self.trace_colors():
self.debug(("Found a border", self.cpixel, self.pixels[self.cpixel]))
return 1
self.debug_pixels[self.cpixel] = (255,0,0)
a = OCR("getimage.png")
a.start()