-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmean-shift.html
More file actions
444 lines (385 loc) · 34.2 KB
/
Copy pathmean-shift.html
File metadata and controls
444 lines (385 loc) · 34.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="author" content="Damien RJ" />
<meta property="og:type" content="article" />
<meta name="twitter:card" content="summary">
<meta name="keywords" content=", Methods, Theory, " />
<meta property="og:title" content="The mean shift clustering algorithm "/>
<meta property="og:url" content="./mean-shift" />
<meta property="og:description" content="Mean shift clustering Mean shift clustering is a general non-parametric cluster finding procedure — introduced by Fukunaga and Hostetler [1], and popular within the computer vision field. Nicely, and in contrast to the more-well-known K-means clustering algorithm, the output of mean shift does not depend on any explicit assumptions on the …" />
<meta property="og:site_name" content="EFAVDB" />
<meta property="og:article:author" content="Damien RJ" />
<meta property="og:article:published_time" content="2015-04-21T09:17:00-07:00" />
<meta name="twitter:title" content="The mean shift clustering algorithm ">
<meta name="twitter:description" content="Mean shift clustering Mean shift clustering is a general non-parametric cluster finding procedure — introduced by Fukunaga and Hostetler [1], and popular within the computer vision field. Nicely, and in contrast to the more-well-known K-means clustering algorithm, the output of mean shift does not depend on any explicit assumptions on the …">
<title>The mean shift clustering algorithm · EFAVDB
</title>
<link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Fira+Sans:300,400,700" rel="stylesheet" type='text/css' />
<link href="https://fonts.googleapis.com/css?family=Cardo:400,700" rel="stylesheet" type='text/css' />
<link rel="stylesheet" type="text/css" href="./theme/css/elegant.prod.css" media="screen">
<link rel="stylesheet" type="text/css" href="./theme/css/custom.css" media="screen">
<link rel="apple-touch-icon" sizes="180x180" href="./images/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="./images/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="./images/favicon-16x16.png">
<link rel="manifest" href="./images/site.webmanifest">
<link rel="mask-icon" href="./images/safari-pinned-tab.svg" color="#5bbad5">
<meta name="msapplication-TileColor" content="#da532c">
<meta name="theme-color" content="#ffffff">
</head>
<body>
<div id="content">
<div class="navbar navbar-static-top">
<div class="navbar-inner">
<div class="container-fluid">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<a class="brand" href="./"><span class=site-name>EFAVDB</span></a>
<div class="nav-collapse collapse">
<ul class="nav pull-right top-menu">
<li >
<a href=
.
>Home</a>
</li>
<li ><a href="./pages/authors.html">Authors</a></li>
<li ><a href="./categories.html">Categories</a></li>
<li ><a href="./tags.html">Tags</a></li>
<li ><a href="./archives.html">Archives</a></li>
<li><form class="navbar-search" action="./search.html" onsubmit="return validateForm(this.elements['q'].value);"> <input type="text" class="search-query" placeholder="Search" name="q" id="tipue_search_input"></form></li>
</ul>
</div>
</div>
</div>
</div>
<div class="container-fluid">
<div class="row-fluid">
<div class="span1"></div>
<div class="span10">
<article itemscope>
<div class="row-fluid">
<header class="page-header span8 offset2">
<h1>
<a href="./mean-shift">
The mean shift clustering algorithm
</a>
</h1>
</header>
<div class="span2"></div>
</div>
<div class="row-fluid">
<div class="span8 offset2 article-content">
<h3>Mean shift clustering</h3>
<p>Mean shift clustering is a general non-parametric cluster finding procedure — introduced by Fukunaga and Hostetler [<a href="#1">1</a>], and popular within the computer vision field. Nicely, and in contrast to the more-well-known K-means clustering algorithm, the output of mean shift does not depend on any explicit assumptions on the shape of the point distribution, the number of clusters, or any form of random initialization.</p>
<p>We describe the mean shift algorithm in some detail in the <a href="#Tech">technical background section</a> at the end of this post. However, its essence is readily explained in a few words: Essentially, mean shift treats the clustering problem by supposing that all points given represent samples from some underlying probability density function, with regions of high sample density corresponding to the local maxima of this distribution. To find these local maxima, the algorithm works by allowing the points to attract each other, via what might be considered a short-ranged “gravitational” force. Allowing the points to gravitate towards areas of higher density, one can show that they will eventually coalesce at a series of points, close to the local maxima of the distribution. Those data points that converge to the same local maxima are considered to be members of the same cluster.</p>
<p>In the next couple of sections, we illustrate application of the algorithm to a couple of problems. We make use of the python package <a href="http://scikit-learn.org/stable/">SkLearn</a>, which contains a mean shift implementation. Following this, we provide a quick discussion and an appendix on technical details.</p>
<h3>Mean shift clustering in action</h3>
<p>In today’s post we will have two examples. First, we will show how to use mean shift clustering to identify clusters of data in a 2D data set. Second, we will use the algorithm to segment a picture based on the colors in the image. To do this we need a handful of libraries from sklearn, numpy, matplotlib, and the Python Imaging Library (<span class="caps">PIL</span>) to handle reading in a jpeg image.</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>
<span class="kn">from</span> <span class="nn">sklearn.cluster</span> <span class="kn">import</span> <span class="n">MeanShift</span><span class="p">,</span> <span class="n">estimate_bandwidth</span>
<span class="kn">from</span> <span class="nn">sklearn.datasets.samples_generator</span> <span class="kn">import</span> <span class="n">make_blobs</span>
<span class="kn">import</span> <span class="nn">matplotlib.pyplot</span> <span class="k">as</span> <span class="nn">plt</span>
<span class="kn">from</span> <span class="nn">itertools</span> <span class="kn">import</span> <span class="n">cycle</span>
<span class="kn">from</span> <span class="nn">PIL</span> <span class="kn">import</span> <span class="n">Image</span>
</code></pre></div>
<h4>Finding clusters in a 2D data set</h4>
<p>This first example is based off of the sklearn <a href="http://scikit-learn.org/stable/auto_examples/cluster/plot_mean_shift.html">tutorial</a> for mean shift clustering: We generate data points centered at 4 locations, making use of sklearn’s make_blobs library. To apply the clustering algorithm to the points generated, we must first set the attractive interaction length between examples, also know as the algorithm’s bandwidth. Sklearn’s implementation contains a built-in function that allows it to automatically estimate a reasonable value for this, based upon the typical distance between examples. We make use of that below, carry out the clustering, and then plot the results.</p>
<div class="highlight"><pre><span></span><code><span class="err">#</span><span class="o">%%</span><span class="w"> </span><span class="n">Generate</span><span class="w"> </span><span class="n">sample</span><span class="w"> </span><span class="k">data</span>
<span class="n">centers</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">[</span><span class="n">[1, 1</span><span class="o">]</span><span class="p">,</span><span class="w"> </span><span class="o">[</span><span class="n">-.75, -1</span><span class="o">]</span><span class="p">,</span><span class="w"> </span><span class="o">[</span><span class="n">1, -1</span><span class="o">]</span><span class="p">,</span><span class="w"> </span><span class="o">[</span><span class="n">-3, 2</span><span class="o">]</span><span class="err">]</span>
<span class="n">X</span><span class="p">,</span><span class="w"> </span><span class="n">_</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">make_blobs</span><span class="p">(</span><span class="n">n_samples</span><span class="o">=</span><span class="mi">10000</span><span class="p">,</span><span class="w"> </span><span class="n">centers</span><span class="o">=</span><span class="n">centers</span><span class="p">,</span><span class="w"> </span><span class="n">cluster_std</span><span class="o">=</span><span class="mf">0.6</span><span class="p">)</span>
<span class="err">#</span><span class="o">%%</span><span class="w"> </span><span class="k">Compute</span><span class="w"> </span><span class="n">clustering</span><span class="w"> </span><span class="k">with</span><span class="w"> </span><span class="n">MeanShift</span>
<span class="err">#</span><span class="w"> </span><span class="n">The</span><span class="w"> </span><span class="n">bandwidth</span><span class="w"> </span><span class="n">can</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="n">automatically</span><span class="w"> </span><span class="n">estimated</span>
<span class="n">bandwidth</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">estimate_bandwidth</span><span class="p">(</span><span class="n">X</span><span class="p">,</span><span class="w"> </span><span class="n">quantile</span><span class="o">=</span><span class="mf">.1</span><span class="p">,</span>
<span class="n">n_samples</span><span class="o">=</span><span class="mi">500</span><span class="p">)</span>
<span class="n">ms</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MeanShift</span><span class="p">(</span><span class="n">bandwidth</span><span class="o">=</span><span class="n">bandwidth</span><span class="p">,</span><span class="w"> </span><span class="n">bin_seeding</span><span class="o">=</span><span class="k">True</span><span class="p">)</span>
<span class="n">ms</span><span class="p">.</span><span class="n">fit</span><span class="p">(</span><span class="n">X</span><span class="p">)</span>
<span class="n">labels</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ms</span><span class="p">.</span><span class="n">labels_</span>
<span class="n">cluster_centers</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ms</span><span class="p">.</span><span class="n">cluster_centers_</span>
<span class="n">n_clusters_</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">labels</span><span class="p">.</span><span class="nf">max</span><span class="p">()</span><span class="o">+</span><span class="mi">1</span>
<span class="err">#</span><span class="o">%%</span><span class="w"> </span><span class="n">Plot</span><span class="w"> </span><span class="k">result</span>
<span class="n">plt</span><span class="p">.</span><span class="n">figure</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="n">clf</span><span class="p">()</span>
<span class="n">colors</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">cycle</span><span class="p">(</span><span class="s1">'bgrcmykbgrcmykbgrcmykbgrcmyk'</span><span class="p">)</span>
<span class="k">for</span><span class="w"> </span><span class="n">k</span><span class="p">,</span><span class="w"> </span><span class="n">col</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">zip</span><span class="p">(</span><span class="k">range</span><span class="p">(</span><span class="n">n_clusters_</span><span class="p">),</span><span class="w"> </span><span class="n">colors</span><span class="p">)</span><span class="err">:</span>
<span class="w"> </span><span class="n">my_members</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">labels</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">k</span>
<span class="w"> </span><span class="n">cluster_center</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cluster_centers</span><span class="o">[</span><span class="n">k</span><span class="o">]</span>
<span class="w"> </span><span class="n">plt</span><span class="p">.</span><span class="n">plot</span><span class="p">(</span><span class="n">X</span><span class="o">[</span><span class="n">my_members, 0</span><span class="o">]</span><span class="p">,</span><span class="w"> </span><span class="n">X</span><span class="o">[</span><span class="n">my_members, 1</span><span class="o">]</span><span class="p">,</span><span class="w"> </span><span class="n">col</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s1">'.'</span><span class="p">)</span>
<span class="w"> </span><span class="n">plt</span><span class="p">.</span><span class="n">plot</span><span class="p">(</span><span class="n">cluster_center</span><span class="o">[</span><span class="n">0</span><span class="o">]</span><span class="p">,</span><span class="w"> </span><span class="n">cluster_center</span><span class="o">[</span><span class="n">1</span><span class="o">]</span><span class="p">,</span>
<span class="w"> </span><span class="s1">'o'</span><span class="p">,</span><span class="w"> </span><span class="n">markerfacecolor</span><span class="o">=</span><span class="n">col</span><span class="p">,</span>
<span class="w"> </span><span class="n">markeredgecolor</span><span class="o">=</span><span class="s1">'k'</span><span class="p">,</span><span class="w"> </span><span class="n">markersize</span><span class="o">=</span><span class="mi">14</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="n">title</span><span class="p">(</span><span class="s1">'Estimated number of clusters: %d'</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="n">n_clusters_</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</code></pre></div>
<p>As you can see below, the algorithm has found clusters centered on each of the blobs we generated.</p>
<p><a href="./wp-content/uploads/2015/03/plot1.png"><img alt="Plot 1" src="./wp-content/uploads/2015/03/plot1.png"></a></p>
<h4>Segmenting a color photo</h4>
<p>In the first example, we were using mean shift clustering to look for spatial clusters. In our second example, we will instead explore 3D color space, <span class="caps">RGB</span>, by considering pixel values taken from an image of a toy car. The procedure is similar — here, we cluster points in 3d, but instead of having data(x,y) we have data(r,g,b) taken from the image’s <span class="caps">RGB</span> pixel values. Clustering these color values in this 3d space returns a series of clusters, where the pixels in those clusters are similar in <span class="caps">RGB</span> space. Recoloring pixels according to their cluster, we obtain a segmentation of the original image.</p>
<div class="highlight"><pre><span></span><code>#%% Part 2: Color image segmentation using mean shift
image = Image.open('toy.jpg')
image = np.array(image)
#Need to convert image into feature array based
#on rgb intensities
flat_image=np.reshape(image, [-1, 3])
#Estimate bandwidth
bandwidth2 = estimate_bandwidth(flat_image,
quantile=.2, n_samples=500)
ms = MeanShift(bandwidth2, bin_seeding=True)
ms.fit(flat_image)
labels=ms.labels_
# Plot image vs segmented image
plt.figure(2)
plt.subplot(2, 1, 1)
plt.imshow(image)
plt.axis('off')
plt.subplot(2, 1, 2)
plt.imshow(np.reshape(labels, [851,1280]))
plt.axis('off')
</code></pre></div>
<p>The bottom image below illustrates that one can effectively use this approach to identify the key shapes within an image, all without doing any image processing to get rid of glare or background — pretty great!
<a href="./wp-content/uploads/2015/03/test-e1428358370930.png"><img alt="" src="./wp-content/uploads/2015/03/test-e1428358370930.png"></a></p>
<h3>Discussion</h3>
<p>Although mean shift is a reasonably versatile algorithm, it has primarily been applied to problems in computer vision, where it has been used for image segmentation, clustering, and video tracking. Application to big data problems can be challenging due to the fact the algorithm can become relatively slow in this limit. However, research is presently underway to speed up its convergence, which should enable its application to larger data sets.</p>
<p>Mean shift pros:</p>
<ol>
<li>No assumptions on the shape or number of data clusters.</li>
<li>The procedure only has one parameter, the bandwidth.</li>
<li>Output doesn’t depend on initializations.</li>
</ol>
<p>Mean shift cons:</p>
<ol>
<li>Output does depend on bandwidth: too small and convergence is slow, too large and some clusters may be missed.</li>
<li>Computationally expensive for large feature spaces.</li>
<li>Often slower than K-Means clustering</li>
</ol>
<p>Technical details follow.</p>
<h3 id="Tech">Technical background</h3>
<h4>Kernel density estimation</h4>
<p>A general formulation of the mean shift algorithm can be developed through consideration of density kernels. These effectively work by smearing out each point example in space over some small window. Summing up the mass from each of these smeared units gives an estimate for the probability density at every point in space (by smearing, we are able to obtain estimates at locations that do not sit exactly atop any example). This approach is often referred to as <a href="http://en.wikipedia.org/wiki/Kernel_density_estimation">kernel density estimation</a> — a method for density estimation that often converges more quickly than binning, or histogramming, and one that also nicely returns a continuous estimate for the density function.</p>
<p>To illustrate, suppose we are given a data set <span class="math">\(\{\textbf{u}_i\}\)</span> of points in d-dimensional space, sampled from some larger population, and that we have chosen a kernel <span class="math">\(K\)</span> having bandwidth parameter <span class="math">\(h\)</span>. Together, these data and kernel function return the following kernel density estimator for the full population’s density function
</p>
<div class="math">\begin{eqnarray}
f_K(\textbf{u}) = \frac{1}{nh^d}\sum\limits_{i=1}^n K(\frac{\textbf{u}-\textbf{u}_i}{h})
\end{eqnarray}</div>
<p>
The kernel (smearing) function here is required to satisfy the following two conditions:</p>
<ol>
<li><span class="math">\(\int K(\textbf{u})d\textbf{u} = 1\)</span></li>
<li><span class="math">\(K(\textbf{u})=K(\vert \textbf{u} \vert)\)</span> for all values of <span class="math">\(\textbf{u}\)</span></li>
</ol>
<p>The first requirement is needed to ensure that our estimate is normalized, and the second is associated with the symmetry of our space. Two popular kernel functions that satisfy these conditions are given by</p>
<ol>
<li>Flat/Uniform <span class="math">\(<div class="math">\begin{align}
K(\textbf{u}) = \frac{1}{2}\left\{
\begin{array}{lr}
1 & -1 \le \vert \textbf{u} \vert \le 1\
0 & else
\end{array}
\right.
\end{align}</div>\)</span></li>
<li>Gaussian = <span class="math">\(K(\textbf{u}) = \frac{1}{\left(2\pi\right)^{d/2}} e^{-\frac{1}{2} \vert \textbf{u} \vert^2}\)</span></li>
</ol>
<p>Below we plot an example in 1-d using the gaussian kernel to estimate the density of some population along the x-axis. You can see that each sample point adds a small Gaussian to our estimate, centered about it: The equations above may look a bit intimidating, but the graphic here should clarify that the concept is pretty straightforward.</p>
<p><a href="./wp-content/uploads/2015/03/KDE-plot.png"><img alt="" src="./wp-content/uploads/2015/03/KDE-plot.png"></a>
Example of a kernel density estimation using a gaussian kernel for each data point: Adding up small Gaussians about each example returns our net estimate for the total density, the black curve.</p>
<h4>Mean shift algorithm</h4>
<p>Recall that the basic goal of the mean shift algorithm is to move particles in the direction of local increasing density. To obtain an estimate for this direction, a gradient is applied to the kernel density estimate discussed above. Assuming an angularly symmetric kernel function, <span class="math">\(K(\textbf{u}) = K(\vert \textbf{u} \vert)\)</span>, one can show that this gradient takes the form
</p>
<div class="math">\begin{eqnarray}
\nabla f_K(\textbf{u}) = \frac{2}{nh^{d+2}} \left ( \sum\limits_{i=1}^n g(\left \vert \frac{\textbf{u}-\textbf{u}_i}{h} \right \vert) \right ) \textbf{m}(\textbf{u}).
\end{eqnarray}</div>
<p>
where
</p>
<div class="math">\begin{eqnarray} \textbf{m}(\textbf{u}) = \left ( \frac{\sum\limits_{i=1}^n \textbf{u}_i g(\left \vert \frac{\textbf{u}-\textbf{u}_i}{h} \right \vert)}{\sum\limits_{i=1}^n g(\left \vert \frac{\textbf{u}-\textbf{u}_i}{h} \right \vert)}-\textbf{u} \right ),
\end{eqnarray}</div>
<p>
and <span class="math">\(g(\vert \textbf{u} \vert ) = -K'(\vert \textbf{u} \vert)\)</span> is the derivative of the selected kernel profile. The vector <span class="math">\(\textbf{m}(\textbf{u})\)</span> here, called the mean shift vector, points in the direction of increasing density — the direction we must move our example. With this estimate, then, the mean shift algorithm protocol becomes</p>
<ul>
<li>Compute the mean shift vector <span class="math">\(\textbf{m}(\textbf{u}_i)\)</span>, evaluated at the location of each training example <span class="math">\(\textbf{u}_i\)</span></li>
<li>Move each example from <span class="math">\(\textbf{u}_i \to \textbf{u}_i + \textbf{m}(\textbf{u}_i)\)</span></li>
<li>Repeat until convergence — ie, until the particles have reached equilibrium.</li>
</ul>
<p>As a final step, one determines which examples have ended up at the same points, marking them as members of the same cluster.</p>
<p>For a proof of convergence and further mathematical details, see <a href="https://courses.csail.mit.edu/6.869/handouts/PAMIMeanshift.pdf">Comaniciu <span class="amp">&</span> Meer (2002)</a> [<a href="#2">2</a>].</p>
<p>1. Fukunaga and Hostetler, “The Estimation of the Gradient of a Density Function, with Applications in Pattern Recognition”, <span class="caps">IEEE</span> Transactions on Information Theory vol 21 , pp 32-40 ,1975
2. Dorin Comaniciu and Peter Meer, Mean Shift : A Robust approach towards feature space analysis, <span class="caps">IEEE</span> Transactions on Pattern Analysis and Machine Intelligence vol 24 No 5 May 2002.</p>
<script type="text/javascript">if (!document.getElementById('mathjaxscript_pelican_#%@#$@#')) {
var align = "center",
indent = "0em",
linebreak = "false";
if (false) {
align = (screen.width < 768) ? "left" : align;
indent = (screen.width < 768) ? "0em" : indent;
linebreak = (screen.width < 768) ? 'true' : linebreak;
}
var mathjaxscript = document.createElement('script');
mathjaxscript.id = 'mathjaxscript_pelican_#%@#$@#';
mathjaxscript.type = 'text/javascript';
mathjaxscript.src = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.3/latest.js?config=TeX-AMS-MML_HTMLorMML';
var configscript = document.createElement('script');
configscript.type = 'text/x-mathjax-config';
configscript[(window.opera ? "innerHTML" : "text")] =
"MathJax.Hub.Config({" +
" config: ['MMLorHTML.js']," +
" TeX: { extensions: ['AMSmath.js','AMSsymbols.js','noErrors.js','noUndefined.js'], equationNumbers: { autoNumber: 'none' } }," +
" jax: ['input/TeX','input/MathML','output/HTML-CSS']," +
" extensions: ['tex2jax.js','mml2jax.js','MathMenu.js','MathZoom.js']," +
" displayAlign: '"+ align +"'," +
" displayIndent: '"+ indent +"'," +
" showMathMenu: true," +
" messageStyle: 'normal'," +
" tex2jax: { " +
" inlineMath: [ ['\\\\(','\\\\)'] ], " +
" displayMath: [ ['$$','$$'] ]," +
" processEscapes: true," +
" preview: 'TeX'," +
" }, " +
" 'HTML-CSS': { " +
" availableFonts: ['STIX', 'TeX']," +
" preferredFont: 'STIX'," +
" styles: { '.MathJax_Display, .MathJax .mo, .MathJax .mi, .MathJax .mn': {color: 'inherit ! important'} }," +
" linebreaks: { automatic: "+ linebreak +", width: '90% container' }," +
" }, " +
"}); " +
"if ('default' !== 'default') {" +
"MathJax.Hub.Register.StartupHook('HTML-CSS Jax Ready',function () {" +
"var VARIANT = MathJax.OutputJax['HTML-CSS'].FONTDATA.VARIANT;" +
"VARIANT['normal'].fonts.unshift('MathJax_default');" +
"VARIANT['bold'].fonts.unshift('MathJax_default-bold');" +
"VARIANT['italic'].fonts.unshift('MathJax_default-italic');" +
"VARIANT['-tex-mathit'].fonts.unshift('MathJax_default-italic');" +
"});" +
"MathJax.Hub.Register.StartupHook('SVG Jax Ready',function () {" +
"var VARIANT = MathJax.OutputJax.SVG.FONTDATA.VARIANT;" +
"VARIANT['normal'].fonts.unshift('MathJax_default');" +
"VARIANT['bold'].fonts.unshift('MathJax_default-bold');" +
"VARIANT['italic'].fonts.unshift('MathJax_default-italic');" +
"VARIANT['-tex-mathit'].fonts.unshift('MathJax_default-italic');" +
"});" +
"}";
(document.body || document.getElementsByTagName('head')[0]).appendChild(configscript);
(document.body || document.getElementsByTagName('head')[0]).appendChild(mathjaxscript);
}
</script>
<p id="post-share-links">
Like this post? Share on:
<a href="https://twitter.com/intent/tweet?text=The%20mean%20shift%20clustering%C2%A0algorithm&url=/mean-shift" target="_blank" rel="nofollow noopener noreferrer" title="Share on Twitter">Twitter</a>
|
<a href="https://www.facebook.com/sharer/sharer.php?u=/mean-shift" target="_blank" rel="nofollow noopener noreferrer" title="Share on Facebook">Facebook</a>
|
<a href="mailto:?subject=The%20mean%20shift%20clustering%C2%A0algorithm&body=/mean-shift" target="_blank" rel="nofollow noopener noreferrer" title="Share via Email">Email</a>
</p>
<hr />
<div class="author_blurb">
<a href="" target="_blank" rel="nofollow noopener noreferrer">
<img src=/wp-content/uploads/2014/12/headshot.jpg alt="Damien RJ Avatar" title="Damien RJ">
<span class="author_name">Damien RJ</span>
</a>
Damien is a highly experienced researcher with a background in clinical and applied research. Like JSL, he got his PhD at UCLA. He has many years of experience working with imaging, and has a particularly strong background in image segmentation, registration, detection, data analysis, and more recently machine learning. He now works as a data-scientist at Square in San Francisco.
</div>
<hr/>
<aside>
<nav>
<ul class="articles-timeline">
<li class="previous-article">« <a href="./nba-week-22-results-nba-season-review-mlb-week-1" title="Previous: NBA week 22 results, NBA season review, MLB week 1">NBA week 22 results, NBA season review, MLB week 1</a></li>
<li class="next-article"><a href="./mlb-week-2-review-week-3-predictions" title="Next: MLB week 2 review, week 3 predictions">MLB week 2 review, week 3 predictions</a> »</li>
</ul>
</nav>
</aside>
</div>
<section id="article-sidebar" class="span2">
<h4>Published</h4>
<time itemprop="dateCreated" datetime="2015-04-21T09:17:00-07:00">Apr 21, 2015</time>
<h4>Category</h4>
<a class="category-link" href="./categories.html#methods-theory-ref">Methods, Theory</a>
<h4>Contact</h4>
<div id="sidebar-social-link">
<a href="https://twitter.com/efavdb" title="" target="_blank" rel="nofollow noopener noreferrer">
<svg xmlns="http://www.w3.org/2000/svg" aria-label="Twitter" role="img" viewBox="0 0 512 512"><rect width="512" height="512" rx="15%" fill="#1da1f3"/><path fill="#fff" d="M437 152a72 72 0 0 1-40 12 72 72 0 0 0 32-40 72 72 0 0 1-45 17 72 72 0 0 0-122 65 200 200 0 0 1-145-74 72 72 0 0 0 22 94 72 72 0 0 1-32-7 72 72 0 0 0 56 69 72 72 0 0 1-32 1 72 72 0 0 0 67 50 200 200 0 0 1-105 29 200 200 0 0 0 309-179 200 200 0 0 0 35-37"/></svg>
</a>
<a href="https://github.com/efavdb" title="" target="_blank" rel="nofollow noopener noreferrer">
<svg xmlns="http://www.w3.org/2000/svg" aria-label="GitHub" role="img" viewBox="0 0 512 512"><rect width="512" height="512" rx="15%" fill="#1B1817"/><path fill="#fff" d="M335 499c14 0 12 17 12 17H165s-2-17 12-17c13 0 16-6 16-12l-1-50c-71 16-86-28-86-28-12-30-28-37-28-37-24-16 1-16 1-16 26 2 40 26 40 26 22 39 59 28 74 22 2-17 9-28 16-35-57-6-116-28-116-126 0-28 10-51 26-69-3-6-11-32 3-67 0 0 21-7 70 26 42-12 86-12 128 0 49-33 70-26 70-26 14 35 6 61 3 67 16 18 26 41 26 69 0 98-60 120-117 126 10 8 18 24 18 48l-1 70c0 6 3 12 16 12z"/></svg>
</a>
<a href="https://www.youtube.com/channel/UClfvjoSiu0VvWOh5OpnuusA" title="" target="_blank" rel="nofollow noopener noreferrer">
<svg xmlns="http://www.w3.org/2000/svg" aria-label="YouTube" role="img" viewBox="0 0 512 512" fill="#ed1d24"><rect width="512" height="512" rx="15%"/><path d="m427 169c-4-15-17-27-32-31-34-9-239-10-278 0-15 4-28 16-32 31-9 38-10 135 0 174 4 15 17 27 32 31 36 10 241 10 278 0 15-4 28-16 32-31 9-36 9-137 0-174" fill="#fff"/><path d="m220 203v106l93-53"/></svg>
</a>
</div>
</section>
</div>
</article>
<button onclick="topFunction()" id="myBtn" title="Go to top">▲</button>
</div>
<div class="span1"></div>
</div>
</div>
</div>
<footer>
<div>
<span class="site-name"><a href= .>EFAVDB</span> - Everybody's Favorite Data Blog</a>
</div>
<!-- <div id="fpowered"> -->
<!-- Powered by: <a href="http://getpelican.com/" title="Pelican Home Page" target="_blank" rel="nofollow noopener noreferrer">Pelican</a> -->
<!-- Theme: <a href="https://elegant.oncrashreboot.com/" title="Theme Elegant Home Page" target="_blank" rel="nofollow noopener noreferrer">Elegant</a> -->
<!-- -->
<!-- </div> -->
</footer> <script src="//code.jquery.com/jquery.min.js"></script>
<script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>
<script>
function validateForm(query)
{
return (query.length > 0);
}
</script>
<script>
//** Scroll to top button **
//Get the button:
mybutton = document.getElementById("myBtn");
// When the user scrolls down 30px from the top of the document, show the button
window.onscroll = function() {scrollFunction()};
function scrollFunction() {
if (document.body.scrollTop > 30 || document.documentElement.scrollTop > 30) {
mybutton.style.display = "block";
} else {
mybutton.style.display = "none";
}
}
// When the user clicks on the button, scroll to the top of the document
function topFunction() {
document.body.scrollTop = 0; // For Safari
document.documentElement.scrollTop = 0; // For Chrome, Firefox, IE and Opera
}
</script>
<script>
(function () {
if (window.location.hash.match(/^#comment-\d+$/)) {
$('#comment_thread').collapse('show');
}
})();
window.onhashchange=function(){
if (window.location.hash.match(/^#comment-\d+$/))
window.location.reload(true);
}
$('#comment_thread').on('shown', function () {
var link = document.getElementById('comment-accordion-toggle');
var old_innerHTML = link.innerHTML;
$(link).fadeOut(200, function() {
$(this).text('Click here to hide comments').fadeIn(200);
});
$('#comment_thread').on('hidden', function () {
$(link).fadeOut(200, function() {
$(this).text(old_innerHTML).fadeIn(200);
});
})
})
</script>
</body>
<!-- Theme: Elegant built for Pelican
License : MIT -->
</html>