peak extraction
[imago.git] / hough.py
1 from math import sin, cos, pi
2
3 from PIL import Image
4
5 from commons import clear
6
7 class Hough:
8     def __init__(self, size):
9         self.size = size
10         self.dt = pi / size[1]
11         self.initial_angle = (pi / 4) + (self.dt / 2)
12
13     def transform(self, image):
14         image_l = image.load()
15         size = image.size
16         
17         matrix = [[0]*size[1] for _ in xrange(size[0])]
18
19         dt = self.dt
20         initial_angle = self.initial_angle
21
22         for x in xrange(size[0]):
23             clear()
24             print "hough transform: {0:>3}/{1}".format(x + 1, size[0])
25             for y in xrange(size[1]):
26                 if image_l[x, y]:
27                     # for every angle:
28                     for a in xrange(size[1]):
29                         # find the distance:
30                         # distance is the dot product of vector (x, y) - centerpoint
31                         # and a unit vector orthogonal to the angle
32                         distance = (((x - (size[0] / 2)) * sin((dt * a) + initial_angle)) + 
33                                     ((y - (size[1] / 2)) * -cos((dt * a) + initial_angle)) +
34                                     size[0] / 2)
35                         # column of the matrix closest to the distance
36                         column = int(round(distance)) 
37                         if column >= 0 and column < size[0]:
38                             matrix[column][a] += 1
39
40         new_image = Image.new('L', size)
41         new_image_l = new_image.load()
42
43         minimum = min([min(m) for m in matrix])
44
45         maximum = max([max(m) for m in matrix]) - minimum
46
47         for y in xrange(size[1]):
48             for x in xrange(size[0]):
49                 new_image_l[x, y] = (float(matrix[x][y] - minimum) / maximum) * 255
50             
51         return new_image
52
53     def all_lines(self, image):
54         im_l = image.load()
55         lines = []
56         for x in xrange(image.size[0]):
57             for y in xrange(image.size[1]):
58                 if im_l[x, y]:
59                     lines.append(self.angle_distance((x, y)))
60         return lines
61     
62     def find_angle_distance(self, image):
63         image_l = image.load()
64
65         points = []
66
67         count = 0
68         point_x = 0
69         point_y = 0
70         for x in xrange(image.size[0] / 2):
71             for y in xrange(image.size[1] / 2, image.size[1]):
72                 if image_l[x, y]:
73                     count += 1
74                     point_x += x
75                     point_y += y
76         points.append((float(point_x) / count, float(point_y) / count))
77
78         count = 0
79         point_x = 0
80         point_y = 0
81         for x in xrange(image.size[0] / 2, image.size[0]):
82             for y in xrange(image.size[1] / 2, image.size[1]):
83                 if image_l[x, y]:
84                     count += 1
85                     point_x += x
86                     point_y += y
87         points.append((float(point_x) / count, float(point_y) / count))
88
89         return [self.angle_distance(p) for p in points]
90
91     def angle_distance(self, point):
92         return (self.dt * point[1] + self.initial_angle, point[0] - self.size[0] / 2)
93