Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mean shift algorithm #235

Open
wants to merge 1 commit into
base: source
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
89 changes: 89 additions & 0 deletions docs/examples/image_segmentation/mean_shift.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# ---
# cover: assets/meanshift.gif
# title: Mean Shift Segmentation Algorithm
# description: This demo shows how to use the meanshift algorithm to segment an image.
# author: Ashwani Rathee
# date: 2021-09-18
# ---

# Mean Shift segmentation is a local homogenization technique that is very useful
# for damping shading or tonality differences in localized objects.
# It replaces each pixel with the mean of the pixels in a range-r neighborhood
# and whose value is within a distance d.

# K-means segmentation is another segmentation technique which is popular
# but has two main issues:
# - We have specify a prior on the number of clusters(Number of K which is no of
# segments).
Comment on lines +16 to +17
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# - We have specify a prior on the number of clusters(Number of K which is no of
# segments).
# - We have specify a prior on the number `K` of clusters (segments).

# - It can be sensitive to value of k-means parameter.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems not entirely surprising. Is it really worth making as a separate point?

It could also be stated that K-means tends to return clusters of approximately equal radius, which may not be how a human would do it.


# Meanshift mitigates the above two issues.
# Let's say below is the pixel feature distribution in an image when we take pixels
# and we map it in feature map.

# ![](assets/pixelf.png)

# Below example image shows x,y coordinates corresponds to features and 3rd column
# is the density of the feature.

# ![](assets/normalized.png)

# - Each hill represents a cluster
# - Peak(mode) of hill represents "center" of the cluster
# - Each pixel climbs the steepest hill within its neighborhood
# - Pixel assigned to the hill(cluster) it climbs. That's the idea behind meanshift.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# - Pixel assigned to the hill(cluster) it climbs. That's the idea behind meanshift.
# - A pixel is assigned to the hill(cluster) it climbs.

I think the "idea behind meanshift" encompasses all of these points.

# Those hills are then assigned labels and the image is segmented.

# ![](assets/coloredpfd.png)

# The Mean Shift takes usually 3 inputs:

# - A distance function for measuring distances between pixels. Usually the
# Euclidean distance, but any other well defined distance function could be used.
# The Manhattan Distance is another useful choice sometimes.
# - A radius. All pixels within this radius (measured according the above distance)
# will be accounted for the calculation.
# - A value difference. From all pixels inside radius r, we will take only those
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would "intensity" be clearer than "value"?

# whose values are within this difference for calculating the mean

# ## Mean Shift Algorithm

# Given: Distribution of N pixels in feature space.

# Task: Find modes(clusters) of distribution.

# Clustering:
# - Set $m_i = f_i$ as initial mean fro each pixel idea
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# - Set $m_i = f_i$ as initial mean fro each pixel idea
# - Set $m_i = f_i$ as initial mean for each pixel

# - Repeat the following for each mean mi:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the same notation. Is mi the same as $m_i$?

# - place window of size $w$ around $m_i$.
# - compute centroid m within the window set $mi = main$
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what main means

# - stop if shift in mean $m_i$ is less than a threshoold $\epsilon$, $m_i$ is the mode

# It's a very simple but computationally expensive method which doesn't require input of
# the number of clusters. Very robust to outliers and clustering depends on window size w.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically, one could say that it replaces specification of # of clusters with the size of the radius.


using Images
using ImageSegmentation, TestImages
using IndirectArrays

img = Gray.(testimage("blobs"))
img = imresize(img, (128, 128));


# Now let's segment images with mean shift clustering algorithm

segments = meanshift(img, 16, 8/255) # parameters are smoothing radii: spatial=16, intensity-wise=8/255
labels = labels_map(segments)
colored_labels = IndirectArray(labels, distinguishable_colors(maximum(labels)))
masked_colored_labels = colored_labels .* (1 .- img)

mosaic(img, colored_labels, masked_colored_labels; nrow=1)

# Here we use `IndirectArray` to store the indexed image, for more explaination on it please
# check the tutorial [Indexed image in 5 minutes](@ref demo_indexed_image).

# ## References:
# - [Mean Shift Clustering](https://en.wikipedia.org/wiki/Mean_shift)
# - http://vision.stanford.edu/teaching/cs131_fall1617/lectures/lecture13_kmeans_mean_shift_cs131_2016

save("assets/meanshift.gif", cat(img, colored_labels, masked_colored_labels; dims=3); fps=1) #src