1 |
|
2 |
|
3 | print "FeatureTree demonstration"
|
4 | print "(graphic rendering done using PIL)"
|
5 |
|
6 | import Image, ImageDraw
|
7 | import random
|
8 | import numpy
|
9 | import sys
|
10 |
|
11 | import cv
|
12 |
|
13 | def FindFeatures( coords, k, tree_type ):
|
14 | |
15 | Construct a k-approximate-nearest-neighbour graph using either a kd-tree or
|
16 | a spilltree
|
17 |
|
18 | Parameters
|
19 | ----------
|
20 | coords : numpy array, each row is a point
|
21 | k : number of neighbours to search
|
22 | tree_type : either 'kdtree' or 'spilltree'
|
23 |
|
24 | Returns
|
25 | -------
|
26 | edges : numpy array of edges, each row is of the form
|
27 | [ point_1, point_2, distance ]
|
28 | """
|
29 | nb_points = len(coords)
|
30 | cv_coords = cv.fromarray(coords)
|
31 | if tree_type == "kdtree":
|
32 | tree = cv.CreateKDTree(cv_coords)
|
33 | elif tree_type == "spilltree":
|
34 | tree = cv.CreateSpillTree( cv_coords,
|
35 | 100,
|
36 | 0.7,
|
37 | 0.1 )
|
38 | else:
|
39 | print "Unkwnown tree_type '" + tree_type + "'"
|
40 | print "valid types are: 'kdtree' or 'spilltree'"
|
41 | sys.exit(1)
|
42 |
|
43 | res = cv.CreateMat(nb_points, k, cv.CV_32SC1)
|
44 | dist = cv.CreateMat(nb_points, k, cv.CV_64FC1)
|
45 | cv.FindFeatures(tree,cv_coords,res,dist,k)
|
46 | edges = []
|
47 | for i in range(0,nb_points):
|
48 | for n in range(0,k):
|
49 | edges.append([i,int(res[i,n]),dist[i,n]])
|
50 |
|
51 | return numpy.array(edges)
|
52 |
|
53 | def weight_color( w, wmin, wmax ):
|
54 |
|
55 |
|
56 | return ( int( (w-wmin) / (wmax-wmin) * 255 ),
|
57 | int( (wmax-w) / (wmax-wmin) * 255 ),
|
58 | 0 )
|
59 |
|
60 | def render(points,edges,filename,image_size=600,point_size=4,line_width=2):
|
61 | img = Image.new( "RGB", (size,size), (255,255,255) )
|
62 | draw = ImageDraw.Draw(img)
|
63 |
|
64 | wmin = min(edges[:,2])
|
65 | wmax = max(edges[:,2])
|
66 |
|
67 |
|
68 | for e in edges:
|
69 | draw.line( [ tuple(points[e[0]]), tuple(points[e[1]]) ],
|
70 | fill=weight_color( e[2], wmin, wmax ),
|
71 | width=line_width )
|
72 |
|
73 |
|
74 | for p in points:
|
75 | box = [(p[0]-point_size,p[1]-point_size),(p[0]+point_size,p[1]+point_size)]
|
76 | draw.ellipse(box, fill=(0,0,0) )
|
77 |
|
78 | img.save(filename)
|
79 | img.show()
|
80 |
|
81 | def FindBox( coords, box ):
|
82 | |
83 | Returns the points that approximately fall in the box
|
84 |
|
85 | Parameters
|
86 | ----------
|
87 | coords : numpy array, each row is a point
|
88 | box : a numpy array defining the box, for instance
|
89 | box = numpy.array([[[xmin,ymin]],[[xmax,ymax]]],dtype=float)
|
90 |
|
91 | Returns
|
92 | -------
|
93 | edges : numpy array of edges, each row is of the form
|
94 | [ point_1, point_2, distance ]
|
95 | """
|
96 | nb_points = len(coords)
|
97 | cv_coords = cv.fromarray(coords)
|
98 | tree = cv.CreateKDTree(cv_coords)
|
99 |
|
100 | bounds_min = cv.fromarray(box[0])
|
101 | bounds_max = cv.fromarray(box[1])
|
102 | res = cv.CreateMat(1,nb_points,cv.CV_32SC1)
|
103 | cv.Set(res, -1)
|
104 |
|
105 | nb_found = cv.FindFeaturesBoxed(tree, bounds_min,bounds_max,res)
|
106 |
|
107 | found = []
|
108 | for i in range(nb_found):
|
109 | found.append(coords[int(res[0,i])])
|
110 |
|
111 | return found
|
112 |
|
113 |
|
114 | def render_box(points,box, found,filename,image_size=600,point_size=4,line_width=2):
|
115 | img = Image.new( "RGB", (size,size), (255,255,255) )
|
116 | draw = ImageDraw.Draw(img)
|
117 |
|
118 |
|
119 | for p in points:
|
120 | pbox = [(p[0]-point_size,p[1]-point_size),(p[0]+point_size,p[1]+point_size)]
|
121 | draw.ellipse(pbox, fill=(0,0,0) )
|
122 |
|
123 |
|
124 | for p in found:
|
125 | pbox = [(p[0]-point_size,p[1]-point_size),(p[0]+point_size,p[1]+point_size)]
|
126 | draw.ellipse(pbox, fill=(255,0,0) )
|
127 |
|
128 |
|
129 | draw.rectangle( [ tuple(box[0][0]), tuple(box[1][0]) ],
|
130 | outline=(255,10,10) )
|
131 |
|
132 | img.save(filename)
|
133 | img.show()
|
134 |
|
135 | if __name__ == '__main__':
|
136 | nb_points = 800
|
137 | k = 5
|
138 | size = 600
|
139 |
|
140 | points = numpy.array( [ [ random.random()*float(size),
|
141 | random.random()*float(size) ] for i in range(nb_points) ],
|
142 | dtype=float )
|
143 |
|
144 | edges = FindFeatures(points,k, 'spilltree')
|
145 | render(points,edges,"spilltree_search.jpg",size)
|
146 |
|
147 | edges = FindFeatures(points,k, 'kdtree')
|
148 | render(points,edges,"kdtree_search.jpg",size)
|
149 |
|
150 | box = numpy.array([[[100,200]],[[400,400]]],dtype=float)
|
151 | found = FindBox(points,box)
|
152 | render_box(points,box,found,"box_search.jpg",size)
|