Skip to content

Commit b0a07e6

Browse files
author
Kevin George
committed
Modifications to get Particle Filter notebook working
1 parent 932927f commit b0a07e6

File tree

1 file changed

+148
-106
lines changed

1 file changed

+148
-106
lines changed

ipython/ParticleFilter.ipynb

Lines changed: 148 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -1,116 +1,158 @@
11
{
2-
"metadata": {},
3-
"nbformat": 3,
4-
"nbformat_minor": 0,
5-
"worksheets": [
2+
"cells": [
63
{
7-
"cells": [
8-
{
9-
"cell_type": "markdown",
10-
"metadata": {},
11-
"source": [
12-
"Particle filter\n",
13-
"===============\n",
14-
"\n",
15-
"A basic particle filter tracking algorithm, using a uniformly\n",
16-
"distributed step as motion model, and the initial target colour as\n",
17-
"determinant feature for the weighting function. This requires an\n",
18-
"approximately uniformly coloured object, which moves at a speed no\n",
19-
"larger than stepsize per frame.\n",
20-
"\n",
21-
"This implementation assumes that the video stream is a sequence of numpy\n",
22-
"arrays, an iterator pointing to such a sequence or a generator\n",
23-
"generating one. The particle filter itself is a generator to allow for\n",
24-
"operating on real-time video streams."
25-
]
26-
},
27-
{
28-
"cell_type": "code",
29-
"collapsed": false,
30-
"input": [
31-
"#!python\n",
32-
"from numpy import *\n",
33-
"from numpy.random import *\n",
34-
"\n",
35-
"\n",
36-
"def resample(weights):\n",
37-
" n = len(weights)\n",
38-
" indices = []\n",
39-
" C = [0.] + [sum(weights[:i+1]) for i in range(n)]\n",
40-
" u0, j = random(), 0\n",
41-
" for u in [(u0+i)/n for i in range(n)]:\n",
42-
" while u > C[j]:\n",
43-
" j+=1\n",
44-
" indices.append(j-1)\n",
45-
" return indices\n",
46-
"\n",
47-
"\n",
48-
"def particlefilter(sequence, pos, stepsize, n):\n",
49-
" seq = iter(sequence)\n",
50-
" x = ones((n, 2), int) * pos # Initial position\n",
51-
" f0 = seq.next()[tuple(pos)] * ones(n) # Target colour model\n",
52-
" yield pos, x, ones(n)/n # Return expected position, particles and weights\n",
53-
" for im in seq:\n",
54-
" x += uniform(-stepsize, stepsize, x.shape) # Particle motion model: uniform step\n",
55-
" x = x.clip(zeros(2), array(im.shape)-1).astype(int) # Clip out-of-bounds particles\n",
56-
" f = im[tuple(x.T)] # Measure particle colours\n",
57-
" w = 1./(1. + (f0-f)**2) # Weight~ inverse quadratic colour distance\n",
58-
" w /= sum(w) # Normalize w\n",
59-
" yield sum(x.T*w, axis=1), x, w # Return expected position, particles and weights\n",
60-
" if 1./sum(w**2) < n/2.: # If particle cloud degenerate:\n",
61-
" x = x[resample(w),:] # Resample particles according to weights"
62-
],
63-
"language": "python",
64-
"metadata": {},
65-
"outputs": []
66-
},
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"Particle filter\n",
8+
"===============\n",
9+
"\n",
10+
"A basic particle filter tracking algorithm, using a uniformly\n",
11+
"distributed step as motion model, and the initial target colour as\n",
12+
"determinant feature for the weighting function. This requires an\n",
13+
"approximately uniformly coloured object, which moves at a speed no\n",
14+
"larger than stepsize per frame.\n",
15+
"\n",
16+
"This implementation assumes that the video stream is a sequence of numpy\n",
17+
"arrays, an iterator pointing to such a sequence or a generator\n",
18+
"generating one. The particle filter itself is a generator to allow for\n",
19+
"operating on real-time video streams."
20+
]
21+
},
22+
{
23+
"cell_type": "code",
24+
"execution_count": 3,
25+
"metadata": {},
26+
"outputs": [],
27+
"source": [
28+
"#!python\n",
29+
"from numpy import *\n",
30+
"from numpy.random import *\n",
31+
"\n",
32+
"\n",
33+
"def resample(weights):\n",
34+
" n = len(weights)\n",
35+
" indices = []\n",
36+
" C = [0.] + [sum(weights[:i+1]) for i in range(n)]\n",
37+
" u0, j = random(), 0\n",
38+
" for u in [(u0+i)/n for i in range(n)]:\n",
39+
" while u > C[j]:\n",
40+
" j+=1\n",
41+
" indices.append(j-1)\n",
42+
" return indices\n",
43+
"\n",
44+
"\n",
45+
"def particlefilter(sequence, pos, stepsize, n):\n",
46+
" seq = iter(sequence)\n",
47+
" x = ones((n, 2), int) * pos # Initial position\n",
48+
" f0 = seq.next()[tuple(pos)] * ones(n) # Target colour model\n",
49+
" yield pos, x, ones(n)/n # Return expected position, particles and weights\n",
50+
" for im in seq:\n",
51+
" np.add(x, uniform(-stepsize, stepsize, x.shape), out=x, casting=\"unsafe\") # Particle motion model: uniform step\n",
52+
" x = x.clip(zeros(2), array(im.shape)-1).astype(int) # Clip out-of-bounds particles\n",
53+
" f = im[tuple(x.T)] # Measure particle colours\n",
54+
" w = 1./(1. + (f0-f)**2) # Weight~ inverse quadratic colour distance\n",
55+
" w /= sum(w) # Normalize w\n",
56+
" yield sum(x.T*w, axis=1), x, w # Return expected position, particles and weights\n",
57+
" if 1./sum(w**2) < n/2.: # If particle cloud degenerate:\n",
58+
" x = x[resample(w),:] # Resample particles according to weights"
59+
]
60+
},
61+
{
62+
"cell_type": "markdown",
63+
"metadata": {},
64+
"source": [
65+
"The following code shows the tracker operating on a test sequence\n",
66+
"featuring a moving square against a uniform background."
67+
]
68+
},
69+
{
70+
"cell_type": "code",
71+
"execution_count": 5,
72+
"metadata": {},
73+
"outputs": [
6774
{
68-
"cell_type": "markdown",
75+
"data": {
76+
"image/png": "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\nU5Iq/D/cl5yJGQxruAAAAABJRU5ErkJggg==\n",
77+
"text/plain": [
78+
"<matplotlib.figure.Figure at 0x10f5dbbd0>"
79+
]
80+
},
6981
"metadata": {},
70-
"source": [
71-
"The following code shows the tracker operating on a test sequence\n",
72-
"featuring a moving square against a uniform background."
73-
]
82+
"output_type": "display_data"
7483
},
7584
{
76-
"cell_type": "code",
77-
"collapsed": false,
78-
"input": [
79-
"#!python\n",
80-
"if __name__ == \"__main__\":\n",
81-
" from pylab import *\n",
82-
" from itertools import izip\n",
83-
" import time\n",
84-
" ion()\n",
85-
" seq = [ im for im in zeros((20,240,320), int)] # Create an image sequence of 20 frames long\n",
86-
" x0 = array([120, 160]) # Add a square with starting position x0 moving along trajectory xs\n",
87-
" xs = vstack((arange(20)*3, arange(20)*2)).T + x0\n",
88-
" for t, x in enumerate(xs):\n",
89-
" xslice = slice(x[0]-8, x[0]+8)\n",
90-
" yslice = slice(x[1]-8, x[1]+8)\n",
91-
" seq[t][xslice, yslice] = 255\n",
92-
"\n",
93-
" for im, p in izip(seq, particlefilter(seq, x0, 8, 100)): # Track the square through the sequence\n",
94-
" pos, xs, ws = p\n",
95-
" position_overlay = zeros_like(im)\n",
96-
" position_overlay[tuple(pos)] = 1\n",
97-
" particle_overlay = zeros_like(im)\n",
98-
" particle_overlay[tuple(xs.T)] = 1\n",
99-
" hold(True)\n",
100-
" draw()\n",
101-
" time.sleep(0.3)\n",
102-
" clf() # Causes flickering, but without the spy plots aren't overwritten\n",
103-
" imshow(im,cmap=cm.gray) # Plot the image\n",
104-
" spy(position_overlay, marker='.', color='b') # Plot the expected position\n",
105-
" spy(particle_overlay, marker=',', color='r') # Plot the particles\n",
106-
" show()"
107-
],
108-
"language": "python",
85+
"data": {
86+
"text/plain": [
87+
"None"
88+
]
89+
},
10990
"metadata": {},
110-
"outputs": []
91+
"output_type": "display_data"
11192
}
11293
],
113-
"metadata": {}
94+
"source": [
95+
"#!python\n",
96+
"if __name__ == \"__main__\":\n",
97+
" from pylab import *\n",
98+
" from itertools import izip\n",
99+
" import time\n",
100+
" from IPython import display\n",
101+
"\n",
102+
" ion()\n",
103+
" seq = [ im for im in zeros((20,240,320), int)] # Create an image sequence of 20 frames long\n",
104+
" x0 = array([120, 160]) # Add a square with starting position x0 moving along trajectory xs\n",
105+
" xs = vstack((arange(20)*3, arange(20)*2)).T + x0\n",
106+
" for t, x in enumerate(xs):\n",
107+
" xslice = slice(x[0]-8, x[0]+8)\n",
108+
" yslice = slice(x[1]-8, x[1]+8)\n",
109+
" seq[t][xslice, yslice] = 255\n",
110+
"\n",
111+
" for im, p in izip(seq, particlefilter(seq, x0, 8, 100)): # Track the square through the sequence\n",
112+
" pos, xs, ws = p\n",
113+
" position_overlay = zeros_like(im)\n",
114+
" position_overlay[np.array(pos).astype(int)] = 1\n",
115+
" particle_overlay = zeros_like(im)\n",
116+
" particle_overlay[tuple(xs.T)] = 1\n",
117+
" draw()\n",
118+
" time.sleep(0.3)\n",
119+
" clf() # Causes flickering, but without the spy plots aren't overwritten\n",
120+
" imshow(im,cmap=cm.gray) # Plot the image\n",
121+
" spy(position_overlay, marker='.', color='b') # Plot the expected position\n",
122+
" spy(particle_overlay, marker=',', color='r') # Plot the particles\n",
123+
" display.clear_output(wait=True)\n",
124+
" display.display(show())"
125+
]
126+
},
127+
{
128+
"cell_type": "code",
129+
"execution_count": null,
130+
"metadata": {
131+
"collapsed": true
132+
},
133+
"outputs": [],
134+
"source": []
135+
}
136+
],
137+
"metadata": {
138+
"kernelspec": {
139+
"display_name": "Python 2",
140+
"language": "python",
141+
"name": "python2"
142+
},
143+
"language_info": {
144+
"codemirror_mode": {
145+
"name": "ipython",
146+
"version": 2
147+
},
148+
"file_extension": ".py",
149+
"mimetype": "text/x-python",
150+
"name": "python",
151+
"nbconvert_exporter": "python",
152+
"pygments_lexer": "ipython2",
153+
"version": "2.7.10"
114154
}
115-
]
116-
}
155+
},
156+
"nbformat": 4,
157+
"nbformat_minor": 1
158+
}

0 commit comments

Comments
 (0)