featuretree.py

example for FeatureTree in Python - Kevin Keraudren, 2011-05-21 08:10 pm

Download (4.5 kB)

 
1
#!/usr/bin/env python
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,  # limit on the leaves to visit
36
                                   0.7,  # spilltree under this value
37
                                   0.1 ) # overlapping ratio
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
    # the closer, the greener
55
    # the further, the reder
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
    # draw the edges
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
    # draw the points
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
    # draw the black points
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
    # draw the points that are in the box
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
    # draw the box
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)