From b91b0e43b25e64b3516b9156ca42e7309665628b Mon Sep 17 00:00:00 2001 From: Tomas Musil Date: Thu, 8 Nov 2012 03:06:08 +0100 Subject: [PATCH] better grid optimization --- geometry.py | 39 +++++++++++++++++++ gridf.py | 109 +++++++++++------------------------------------------- gridf_analyzer.py | 50 +++++++++++++++++++++++++ imago.py | 5 ++- linef.py | 2 +- 5 files changed, 114 insertions(+), 91 deletions(-) create mode 100644 geometry.py create mode 100644 gridf_analyzer.py diff --git a/geometry.py b/geometry.py new file mode 100644 index 0000000..09b0199 --- /dev/null +++ b/geometry.py @@ -0,0 +1,39 @@ +"""Imago geometry module""" + +class V(object): + def __init__(self, x, y): + self.x = x + self.y = y + + def __add__(self, other): + return V(self.x + other.x, self.y + other.y) + + def __sub__(self, other): + return V(self.x - other.x, self.y - other.y) + + def __rmul__(self, other): + return V(other * self.x, other * self.y) + + def __len__(self): + return 2; + + def __getitem__(self, key): + if key == 0: + return self.x + elif key == 1: + return self.y + elif type(key) != int: + raise TypeError("V indices must be integers") + else: + raise KeyError("V index ({}) out of range".format(key)) + + def __iter__(self): + yield self.x + yield self.y + + @property + def normal(self): + return V(-self.y, self.x) + +def projection(point, line, vector): + return V(*intersection(g_line(point, point + vector.normal), g_line(*line))) diff --git a/gridf.py b/gridf.py index 406285c..6f044f1 100644 --- a/gridf.py +++ b/gridf.py @@ -2,6 +2,7 @@ import multiprocessing import Image, ImageDraw, ImageFilter +from geometry import V from manual import lines as g_grid, l2ad, intersection, line as g_line from intrsc import intersections_from_angl_dist from linef import line_from_angl_dist @@ -18,52 +19,9 @@ class MyGaussianBlur(ImageFilter.Filter): def filter(self, image): return image.gaussian_blur(self.radius) -class V(object): - def __init__(self, x, y): - self.x = x - self.y = y - - def __add__(self, other): - return V(self.x + other.x, self.y + other.y) - - def __sub__(self, other): - return V(self.x - other.x, self.y - other.y) - - def __rmul__(self, other): - return V(other * self.x, other * self.y) - - def __len__(self): - return 2; - - def __getitem__(self, key): - if key == 0: - return self.x - elif key == 1: - return self.y - elif type(key) != int: - raise TypeError("V indices must be integers") - else: - raise KeyError("V index ({}) out of range".format(key)) - - def __iter__(self): - yield self.x - yield self.y - - @property - def normal(self): - return V(-self.y, self.x) - def projection(point, line, vector): return V(*intersection(g_line(point, point + vector.normal), g_line(*line))) -def job(args): - X, Y, im_l, a, b, c, d, s, v1, k, hough, size = args - return [distance(im_l, - get_grid(a + X[y] * s * v1, - b + Y[y] * s * v1, - c, d, hough, size), - size) for y in range(2 * k)] - def job_br1(args): X, Y, im_l, a, b, c, d, s, v1, v2, k, hough, size = args return [(distance(im_l, @@ -80,43 +38,7 @@ def job_br2(args): hough, size), size), c + X[y] * s * v2, d + Y[y] * s * v2) for y in range(2 *k)] -def error_surface(im_l, a, b, c, d, hough, size, v1): - import matplotlib.pyplot as plt - from matplotlib import cm - import time - import sys - import pickle - - X = [] - Y = [] - Z = [] - s = 0.001 - k = 250 - for i in range(-k, k): - X.append(range(-k, k)) - Y.append(2*k*[i]) - - tasks = [(X[x], Y[x], im_l, a, b, c, d, s, v1, k, hough, size) for x in xrange(0, 2 * k)] - #everything is passed by value here; can it somehow be passed by reference? - - pool = multiprocessing.Pool(None) - - start = time.time() - Z = pool.map(job, tasks, 1) - print time.time() - start - - s_file = open('surface' + str(k), 'w') - pickle.dump((X, Y, Z), s_file) - s_file.close() - plt.imshow(Z, cmap=cm.jet, interpolation='bicubic', - origin='upper', extent=(-k, k, -k, k), aspect='equal') - plt.colorbar() - - plt.show() - - sys.exit() - -def find(lines, size, l1, l2, bounds, hough, do_something): +def find(lines, size, l1, l2, bounds, hough, do_something, im_h): a, b, c, d = [V(*a) for a in bounds] l1 = line_from_angl_dist(l1, size) l2 = line_from_angl_dist(l2, size) @@ -131,11 +53,13 @@ def find(lines, size, l1, l2, bounds, hough, do_something): dr_l = ImageDraw.Draw(im_l) for line in sum(lines, []): dr_l.line(line_from_angl_dist(line, size), width=1, fill=255) - im_l = im_l.filter(MyGaussianBlur(radius=30)) + #im_l = im_l.filter(MyGaussianBlur(radius=30)) #GaussianBlur is undocumented class, may not work in future versions of PIL - im_l = im_l.tostring() + #im_l = im_l.tostring() + im_l = im_h.tostring() # hocus pocus - #error_surface(im_l, a, b, c, d, hough, size, v1) + #from gridf_analyzer import error_surface + #error_surface(im_l, a, b, c, d, hough, size, v1 ,v2) grid = get_grid(a, b, c, d, hough, size) dist = distance(im_l, grid, size) @@ -148,10 +72,10 @@ def find(lines, size, l1, l2, bounds, hough, do_something): X.append(range(-k, k)) Y.append(2*k*[i]) + pool = multiprocessing.Pool(None) + tasks = [(X[x], Y[x], im_l, a, b, c, d, s, v1, v2, k, hough, size) for x in xrange(0, 2 * k)] - pool = multiprocessing.Pool(None) - #start = time.time() opt_ab = pool.map(job_br1, tasks, 1) opt_cd = pool.map(job_br2, tasks, 1) @@ -161,15 +85,15 @@ def find(lines, size, l1, l2, bounds, hough, do_something): for tpl in lst: if tpl[0] > d1: d1 = tpl[0] - an, bn = tpl[1], tpl[2] + a, b = tpl[1], tpl[2] d1 = 0 for lst in opt_cd: for tpl in lst: if tpl[0] > d1: d1 = tpl[0] - cn, dn = tpl[1], tpl[2] + c, d = tpl[1], tpl[2] #print time.time() - start - grid = get_grid(an, bn, cn, dn, hough, size) + grid = get_grid(a, b, c, d, hough, size) grid_lines = [[l2ad(l, size) for l in grid[0]], [l2ad(l, size) for l in grid[1]]] return grid, grid_lines @@ -242,11 +166,20 @@ def get_grid(a, b, c, d, hough, size): grid = g_grid(corners) return grid +def line_out(line, size): + for p in line: + if p[0] < 0 or p[0] > size[0] or p[1] < 0 or p[1] > size[1]: + return True + else: + return False + def distance(im_l, grid, size): im_g = Image.new('L', size) dr_g = ImageDraw.Draw(im_g) for line in grid[0] + grid[1]: dr_g.line(line, width=1, fill=255) + if line_out(line, size): + return 0 #im_g = im_g.filter(MyGaussianBlur(radius=3)) #GaussianBlur is undocumented class, may not work in future versions of PIL #im_d, distance = combine(im_l, im_g) diff --git a/gridf_analyzer.py b/gridf_analyzer.py new file mode 100644 index 0000000..feb1e25 --- /dev/null +++ b/gridf_analyzer.py @@ -0,0 +1,50 @@ +import matplotlib.pyplot as plt +from matplotlib import cm +import time +import sys +import pickle +import multiprocessing + +import gridf + +def job1(args): + X, Y, im_l, a, b, c, d, s, v1, k, hough, size = args + return [gridf.distance(im_l, + gridf.get_grid(a + X[y] * s * v1, + b + Y[y] * s * v1, + c, d, hough, size), + size) for y in range(2 * k)] +def job2(args): + X, Y, im_l, a, b, c, d, s, v1, v2, k, hough, size = args + return [gridf.distance(im_l, + gridf.get_grid(a, b, c+ X[y] * s * v2, + d + Y[y] * s * v2, + hough, size), + size) for y in range(2 * k)] + +def error_surface(im_l, a, b, c, d, hough, size, v1, v2): + X = [] + Y = [] + Z = [] + s = 0.001 + k = 250 + for i in range(-k, k): + X.append(range(-k, k)) + Y.append(2*k*[i]) + + tasks = [(X[x], Y[x], im_l, a, b, c, d, s, v1, v2, k, hough, size) for x in xrange(0, 2 * k)] + + pool = multiprocessing.Pool(None) + + start = time.time() + Z = pool.map(job2, tasks, 1) + print time.time() - start + + s_file = open('surface' + str(k), 'w') + pickle.dump((X, Y, Z), s_file) + s_file.close() + plt.imshow(Z, cmap=cm.jet, interpolation='bicubic', + origin='upper', extent=(-k, k, -k, k), aspect='equal') + plt.colorbar() + + plt.show() diff --git a/imago.py b/imago.py index 3fa4f6b..fcba0a4 100755 --- a/imago.py +++ b/imago.py @@ -63,8 +63,9 @@ def main(): #TODO ask user to try again return 1 else: - lines, l1, l2, bounds, hough = linef.find_lines(image, show_all, do_something, verbose) - grid, lines = gridf.find(lines, image.size, l1, l2, bounds, hough, do_something) + lines, l1, l2, bounds, hough, im_h = linef.find_lines(image, show_all, do_something, verbose) + grid, lines = gridf.find(lines, image.size, l1, l2, bounds, hough, + do_something, im_h) if show_all: im_g = image.copy() draw = ImageDraw.Draw(im_g) diff --git a/linef.py b/linef.py index 29ce2e3..dae08e3 100644 --- a/linef.py +++ b/linef.py @@ -109,7 +109,7 @@ def find_lines(image, show_all, do_something, verbose): if show_all: do_something(image_g, "lines") - return lines, lines_m[0][0], lines_m[1][0], bounds, hough1 + return lines, lines_m[0][0], lines_m[1][0], bounds, hough1, im_h def combine(image1, image2): im_l1 = image1.load() -- 2.4.2