mirror of
https://github.com/wassname/scikit-image.git
synced 2026-07-31 12:41:20 +08:00
Added sections to gallery of examples
Modified travis_script.sh to account for the new structure of the gallery Added README.txt files in directories of gallery examples Fixed references to gallery images in user guide pages Fixed broken links
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
Segmentation of objects
|
||||
-----------------------
|
||||
@@ -0,0 +1,62 @@
|
||||
"""
|
||||
==========================================
|
||||
Find the intersection of two segmentations
|
||||
==========================================
|
||||
|
||||
When segmenting an image, you may want to combine multiple alternative
|
||||
segmentations. The `skimage.segmentation.join_segmentations` function
|
||||
computes the join of two segmentations, in which a pixel is placed in
|
||||
the same segment if and only if it is in the same segment in _both_
|
||||
segmentations.
|
||||
|
||||
"""
|
||||
import numpy as np
|
||||
from scipy import ndimage as ndi
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
from skimage.filters import sobel
|
||||
from skimage.segmentation import slic, join_segmentations
|
||||
from skimage.morphology import watershed
|
||||
from skimage.color import label2rgb
|
||||
from skimage import data, img_as_float
|
||||
|
||||
coins = img_as_float(data.coins())
|
||||
|
||||
# make segmentation using edge-detection and watershed
|
||||
edges = sobel(coins)
|
||||
markers = np.zeros_like(coins)
|
||||
foreground, background = 1, 2
|
||||
markers[coins < 30.0 / 255] = background
|
||||
markers[coins > 150.0 / 255] = foreground
|
||||
|
||||
ws = watershed(edges, markers)
|
||||
seg1 = ndi.label(ws == foreground)[0]
|
||||
|
||||
# make segmentation using SLIC superpixels
|
||||
seg2 = slic(coins, n_segments=117, max_iter=160, sigma=1, compactness=0.75,
|
||||
multichannel=False)
|
||||
|
||||
# combine the two
|
||||
segj = join_segmentations(seg1, seg2)
|
||||
|
||||
# show the segmentations
|
||||
fig, axes = plt.subplots(ncols=4, figsize=(9, 2.5), sharex=True, sharey=True, subplot_kw={'adjustable':'box-forced'})
|
||||
axes[0].imshow(coins, cmap=plt.cm.gray, interpolation='nearest')
|
||||
axes[0].set_title('Image')
|
||||
|
||||
color1 = label2rgb(seg1, image=coins, bg_label=0)
|
||||
axes[1].imshow(color1, interpolation='nearest')
|
||||
axes[1].set_title('Sobel+Watershed')
|
||||
|
||||
color2 = label2rgb(seg2, image=coins, image_alpha=0.5)
|
||||
axes[2].imshow(color2, interpolation='nearest')
|
||||
axes[2].set_title('SLIC superpixels')
|
||||
|
||||
color3 = label2rgb(segj, image=coins, image_alpha=0.5)
|
||||
axes[3].imshow(color3, interpolation='nearest')
|
||||
axes[3].set_title('Join')
|
||||
|
||||
for ax in axes:
|
||||
ax.axis('off')
|
||||
fig.subplots_adjust(hspace=0.01, wspace=0.01, top=1, bottom=0, left=0, right=1)
|
||||
plt.show()
|
||||
@@ -0,0 +1,59 @@
|
||||
"""
|
||||
===================
|
||||
Label image regions
|
||||
===================
|
||||
|
||||
This example shows how to segment an image with image labelling. The following
|
||||
steps are applied:
|
||||
|
||||
1. Thresholding with automatic Otsu method
|
||||
2. Close small holes with binary closing
|
||||
3. Remove artifacts touching image border
|
||||
4. Measure image regions to filter small objects
|
||||
|
||||
"""
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
import matplotlib.patches as mpatches
|
||||
|
||||
from skimage import data
|
||||
from skimage.filters import threshold_otsu
|
||||
from skimage.segmentation import clear_border
|
||||
from skimage.measure import label
|
||||
from skimage.morphology import closing, square
|
||||
from skimage.measure import regionprops
|
||||
from skimage.color import label2rgb
|
||||
|
||||
|
||||
image = data.coins()[50:-50, 50:-50]
|
||||
|
||||
# apply threshold
|
||||
thresh = threshold_otsu(image)
|
||||
bw = closing(image > thresh, square(3))
|
||||
|
||||
# remove artifacts connected to image border
|
||||
cleared = bw.copy()
|
||||
clear_border(cleared)
|
||||
|
||||
# label image regions
|
||||
label_image = label(cleared)
|
||||
borders = np.logical_xor(bw, cleared)
|
||||
label_image[borders] = -1
|
||||
image_label_overlay = label2rgb(label_image, image=image)
|
||||
|
||||
fig, ax = plt.subplots(ncols=1, nrows=1, figsize=(6, 6))
|
||||
ax.imshow(image_label_overlay)
|
||||
|
||||
for region in regionprops(label_image):
|
||||
|
||||
# skip small images
|
||||
if region.area < 100:
|
||||
continue
|
||||
|
||||
# draw rectangle around segmented coins
|
||||
minr, minc, maxr, maxc = region.bbox
|
||||
rect = mpatches.Rectangle((minc, minr), maxc - minc, maxr - minr,
|
||||
fill=False, edgecolor='red', linewidth=2)
|
||||
ax.add_patch(rect)
|
||||
|
||||
plt.show()
|
||||
@@ -0,0 +1,61 @@
|
||||
"""
|
||||
====================
|
||||
Local Otsu Threshold
|
||||
====================
|
||||
|
||||
This example shows how Otsu's threshold [1]_ method can be applied locally. For
|
||||
each pixel, an "optimal" threshold is determined by maximizing the variance
|
||||
between two classes of pixels of the local neighborhood defined by a
|
||||
structuring element.
|
||||
|
||||
The example compares the local threshold with the global threshold.
|
||||
|
||||
.. note: local is much slower than global thresholding
|
||||
|
||||
.. [1] http://en.wikipedia.org/wiki/Otsu's_method
|
||||
|
||||
"""
|
||||
import matplotlib
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
from skimage import data
|
||||
from skimage.morphology import disk
|
||||
from skimage.filters import threshold_otsu, rank
|
||||
from skimage.util import img_as_ubyte
|
||||
|
||||
|
||||
matplotlib.rcParams['font.size'] = 9
|
||||
|
||||
|
||||
img = img_as_ubyte(data.page())
|
||||
|
||||
radius = 15
|
||||
selem = disk(radius)
|
||||
|
||||
local_otsu = rank.otsu(img, selem)
|
||||
threshold_global_otsu = threshold_otsu(img)
|
||||
global_otsu = img >= threshold_global_otsu
|
||||
|
||||
|
||||
fig, ax = plt.subplots(2, 2, figsize=(8, 5), sharex=True, sharey=True, subplot_kw={'adjustable':'box-forced'})
|
||||
ax1, ax2, ax3, ax4 = ax.ravel()
|
||||
|
||||
fig.colorbar(ax1.imshow(img, cmap=plt.cm.gray),
|
||||
ax=ax1, orientation='horizontal')
|
||||
ax1.set_title('Original')
|
||||
ax1.axis('off')
|
||||
|
||||
fig.colorbar(ax2.imshow(local_otsu, cmap=plt.cm.gray),
|
||||
ax=ax2, orientation='horizontal')
|
||||
ax2.set_title('Local Otsu (radius=%d)' % radius)
|
||||
ax2.axis('off')
|
||||
|
||||
ax3.imshow(img >= local_otsu, cmap=plt.cm.gray)
|
||||
ax3.set_title('Original >= Local Otsu' % threshold_global_otsu)
|
||||
ax3.axis('off')
|
||||
|
||||
ax4.imshow(global_otsu, cmap=plt.cm.gray)
|
||||
ax4.set_title('Global Otsu (threshold = %d)' % threshold_global_otsu)
|
||||
ax4.axis('off')
|
||||
|
||||
plt.show()
|
||||
@@ -0,0 +1,66 @@
|
||||
"""
|
||||
===============================
|
||||
Markers for watershed transform
|
||||
===============================
|
||||
|
||||
The watershed is a classical algorithm used for **segmentation**, that
|
||||
is, for separating different objects in an image.
|
||||
|
||||
Here a marker image is built from the region of low gradient inside the image.
|
||||
In a gradient image, the areas of high values provide barriers that help to
|
||||
segment the image.
|
||||
Using markers on the lower values will ensure that the segmented objects are
|
||||
found.
|
||||
|
||||
See Wikipedia_ for more details on the algorithm.
|
||||
|
||||
.. _Wikipedia: http://en.wikipedia.org/wiki/Watershed_(image_processing)
|
||||
|
||||
"""
|
||||
|
||||
from scipy import ndimage as ndi
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
from skimage.morphology import watershed, disk
|
||||
from skimage import data
|
||||
from skimage.filters import rank
|
||||
from skimage.util import img_as_ubyte
|
||||
|
||||
|
||||
image = img_as_ubyte(data.camera())
|
||||
|
||||
# denoise image
|
||||
denoised = rank.median(image, disk(2))
|
||||
|
||||
# find continuous region (low gradient -
|
||||
# where less than 10 for this image) --> markers
|
||||
# disk(5) is used here to get a more smooth image
|
||||
markers = rank.gradient(denoised, disk(5)) < 10
|
||||
markers = ndi.label(markers)[0]
|
||||
|
||||
# local gradient (disk(2) is used to keep edges thin)
|
||||
gradient = rank.gradient(denoised, disk(2))
|
||||
|
||||
# process the watershed
|
||||
labels = watershed(gradient, markers)
|
||||
|
||||
# display results
|
||||
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(8, 8), sharex=True, sharey=True, subplot_kw={'adjustable':'box-forced'})
|
||||
axes = axes.ravel()
|
||||
ax0, ax1, ax2, ax3 = axes
|
||||
|
||||
ax0.imshow(image, cmap=plt.cm.gray, interpolation='nearest')
|
||||
ax0.set_title("Original")
|
||||
ax1.imshow(gradient, cmap=plt.cm.spectral, interpolation='nearest')
|
||||
ax1.set_title("Local Gradient")
|
||||
ax2.imshow(markers, cmap=plt.cm.spectral, interpolation='nearest')
|
||||
ax2.set_title("Markers")
|
||||
ax3.imshow(image, cmap=plt.cm.gray, interpolation='nearest')
|
||||
ax3.imshow(labels, cmap=plt.cm.spectral, interpolation='nearest', alpha=.7)
|
||||
ax3.set_title("Segmented")
|
||||
|
||||
for ax in axes:
|
||||
ax.axis('off')
|
||||
|
||||
fig.tight_layout()
|
||||
plt.show()
|
||||
@@ -0,0 +1,33 @@
|
||||
"""
|
||||
==============
|
||||
Normalized Cut
|
||||
==============
|
||||
|
||||
This example constructs a Region Adjacency Graph (RAG) and recursively performs
|
||||
a Normalized Cut on it.
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] Shi, J.; Malik, J., "Normalized cuts and image segmentation",
|
||||
Pattern Analysis and Machine Intelligence,
|
||||
IEEE Transactions on, vol. 22, no. 8, pp. 888-905, August 2000.
|
||||
"""
|
||||
from skimage import data, io, segmentation, color
|
||||
from skimage.future import graph
|
||||
from matplotlib import pyplot as plt
|
||||
|
||||
|
||||
img = data.coffee()
|
||||
|
||||
labels1 = segmentation.slic(img, compactness=30, n_segments=400)
|
||||
out1 = color.label2rgb(labels1, img, kind='avg')
|
||||
|
||||
g = graph.rag_mean_color(img, labels1, mode='similarity')
|
||||
labels2 = graph.cut_normalized(labels1, g)
|
||||
out2 = color.label2rgb(labels2, img, kind='avg')
|
||||
|
||||
plt.figure()
|
||||
io.imshow(out1)
|
||||
plt.figure()
|
||||
io.imshow(out2)
|
||||
io.show()
|
||||
@@ -0,0 +1,49 @@
|
||||
"""
|
||||
============
|
||||
Thresholding
|
||||
============
|
||||
|
||||
Thresholding is used to create a binary image. This example uses Otsu's method
|
||||
to calculate the threshold value.
|
||||
|
||||
Otsu's method calculates an "optimal" threshold (marked by a red line in the
|
||||
histogram below) by maximizing the variance between two classes of pixels,
|
||||
which are separated by the threshold. Equivalently, this threshold minimizes
|
||||
the intra-class variance.
|
||||
|
||||
.. [1] http://en.wikipedia.org/wiki/Otsu's_method
|
||||
|
||||
"""
|
||||
import matplotlib
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
from skimage.data import camera
|
||||
from skimage.filters import threshold_otsu
|
||||
|
||||
|
||||
matplotlib.rcParams['font.size'] = 9
|
||||
|
||||
|
||||
image = camera()
|
||||
thresh = threshold_otsu(image)
|
||||
binary = image > thresh
|
||||
|
||||
#fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(8, 2.5))
|
||||
fig = plt.figure(figsize=(8, 2.5))
|
||||
ax1 = plt.subplot(1, 3, 1, adjustable='box-forced')
|
||||
ax2 = plt.subplot(1, 3, 2)
|
||||
ax3 = plt.subplot(1, 3, 3, sharex=ax1, sharey=ax1, adjustable='box-forced')
|
||||
|
||||
ax1.imshow(image, cmap=plt.cm.gray)
|
||||
ax1.set_title('Original')
|
||||
ax1.axis('off')
|
||||
|
||||
ax2.hist(image)
|
||||
ax2.set_title('Histogram')
|
||||
ax2.axvline(thresh, color='r')
|
||||
|
||||
ax3.imshow(binary, cmap=plt.cm.gray)
|
||||
ax3.set_title('Thresholded')
|
||||
ax3.axis('off')
|
||||
|
||||
plt.show()
|
||||
@@ -0,0 +1,47 @@
|
||||
"""
|
||||
====================
|
||||
Finding local maxima
|
||||
====================
|
||||
|
||||
The ``peak_local_max`` function returns the coordinates of local peaks (maxima)
|
||||
in an image. A maximum filter is used for finding local maxima. This operation
|
||||
dilates the original image and merges neighboring local maxima closer than the
|
||||
size of the dilation. Locations where the original image is equal to the
|
||||
dilated image are returned as local maxima.
|
||||
|
||||
"""
|
||||
from scipy import ndimage as ndi
|
||||
import matplotlib.pyplot as plt
|
||||
from skimage.feature import peak_local_max
|
||||
from skimage import data, img_as_float
|
||||
|
||||
im = img_as_float(data.coins())
|
||||
|
||||
# image_max is the dilation of im with a 20*20 structuring element
|
||||
# It is used within peak_local_max function
|
||||
image_max = ndi.maximum_filter(im, size=20, mode='constant')
|
||||
|
||||
# Comparison between image_max and im to find the coordinates of local maxima
|
||||
coordinates = peak_local_max(im, min_distance=20)
|
||||
|
||||
# display results
|
||||
fig, ax = plt.subplots(1, 3, figsize=(8, 3), sharex=True, sharey=True, subplot_kw={'adjustable':'box-forced'})
|
||||
ax1, ax2, ax3 = ax.ravel()
|
||||
ax1.imshow(im, cmap=plt.cm.gray)
|
||||
ax1.axis('off')
|
||||
ax1.set_title('Original')
|
||||
|
||||
ax2.imshow(image_max, cmap=plt.cm.gray)
|
||||
ax2.axis('off')
|
||||
ax2.set_title('Maximum filter')
|
||||
|
||||
ax3.imshow(im, cmap=plt.cm.gray)
|
||||
ax3.autoscale(False)
|
||||
ax3.plot(coordinates[:, 1], coordinates[:, 0], 'r.')
|
||||
ax3.axis('off')
|
||||
ax3.set_title('Peak local max')
|
||||
|
||||
fig.subplots_adjust(wspace=0.02, hspace=0.02, top=0.9,
|
||||
bottom=0.02, left=0.02, right=0.98)
|
||||
|
||||
plt.show()
|
||||
@@ -0,0 +1,81 @@
|
||||
"""
|
||||
=======================
|
||||
Region Adjacency Graphs
|
||||
=======================
|
||||
|
||||
This example demonstrates the use of the `merge_nodes` function of a Region
|
||||
Adjacency Graph (RAG). The `RAG` class represents a undirected weighted graph
|
||||
which inherits from `networkx.graph` class. When a new node is formed by
|
||||
merging two nodes, the edge weight of all the edges incident on the resulting
|
||||
node can be updated by a user defined function `weight_func`.
|
||||
|
||||
The default behaviour is to use the smaller edge weight in case of a conflict.
|
||||
The example below also shows how to use a custom function to select the larger
|
||||
weight instead.
|
||||
|
||||
"""
|
||||
from skimage.future.graph import rag
|
||||
import networkx as nx
|
||||
from matplotlib import pyplot as plt
|
||||
import numpy as np
|
||||
|
||||
|
||||
def max_edge(g, src, dst, n):
|
||||
"""Callback to handle merging nodes by choosing maximum weight.
|
||||
|
||||
Returns either the weight between (`src`, `n`) or (`dst`, `n`)
|
||||
in `g` or the maximum of the two when both exist.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
g : RAG
|
||||
The graph under consideration.
|
||||
src, dst : int
|
||||
The vertices in `g` to be merged.
|
||||
n : int
|
||||
A neighbor of `src` or `dst` or both.
|
||||
|
||||
Returns
|
||||
-------
|
||||
weight : float
|
||||
The weight between (`src`, `n`) or (`dst`, `n`) in `g` or the
|
||||
maximum of the two when both exist.
|
||||
|
||||
"""
|
||||
|
||||
w1 = g[n].get(src, {'weight': -np.inf})['weight']
|
||||
w2 = g[n].get(dst, {'weight': -np.inf})['weight']
|
||||
return max(w1, w2)
|
||||
|
||||
|
||||
def display(g, title):
|
||||
"""Displays a graph with the given title."""
|
||||
pos = nx.circular_layout(g)
|
||||
plt.figure()
|
||||
plt.title(title)
|
||||
nx.draw(g, pos)
|
||||
nx.draw_networkx_edge_labels(g, pos, font_size=20)
|
||||
|
||||
|
||||
g = rag.RAG()
|
||||
g.add_edge(1, 2, weight=10)
|
||||
g.add_edge(2, 3, weight=20)
|
||||
g.add_edge(3, 4, weight=30)
|
||||
g.add_edge(4, 1, weight=40)
|
||||
g.add_edge(1, 3, weight=50)
|
||||
|
||||
# Assigning dummy labels.
|
||||
for n in g.nodes():
|
||||
g.node[n]['labels'] = [n]
|
||||
|
||||
gc = g.copy()
|
||||
|
||||
display(g, "Original Graph")
|
||||
|
||||
g.merge_nodes(1, 3)
|
||||
display(g, "Merged with default (min)")
|
||||
|
||||
gc.merge_nodes(1, 3, weight_func=max_edge, in_place=False)
|
||||
display(gc, "Merged with max without in_place")
|
||||
|
||||
plt.show()
|
||||
@@ -0,0 +1,40 @@
|
||||
"""
|
||||
======================================
|
||||
Drawing Region Adjacency Graphs (RAGs)
|
||||
======================================
|
||||
|
||||
This example constructs a Region Adjacency Graph (RAG) and draws it with
|
||||
the `rag_draw` method.
|
||||
"""
|
||||
from skimage import data, segmentation
|
||||
from skimage.future import graph
|
||||
from skimage.util.colormap import viridis
|
||||
from matplotlib import pyplot as plt, colors
|
||||
|
||||
|
||||
img = data.coffee()
|
||||
labels = segmentation.slic(img, compactness=30, n_segments=400)
|
||||
g = graph.rag_mean_color(img, labels)
|
||||
|
||||
out = graph.draw_rag(labels, g, img)
|
||||
plt.figure()
|
||||
plt.title("RAG with all edges shown in green.")
|
||||
plt.imshow(out)
|
||||
|
||||
# The color palette used was taken from
|
||||
# http://www.colorcombos.com/color-schemes/2/ColorCombo2.html
|
||||
cmap = colors.ListedColormap(['#6599FF', '#ff9900'])
|
||||
out = graph.draw_rag(labels, g, img, node_color="#ffde00", colormap=cmap,
|
||||
thresh=30, desaturate=True)
|
||||
plt.figure()
|
||||
plt.title("RAG with edge weights less than 30, color "
|
||||
"mapped between blue and orange.")
|
||||
plt.imshow(out)
|
||||
|
||||
plt.figure()
|
||||
plt.title("All edges drawn with viridis colormap")
|
||||
out = graph.draw_rag(labels, g, img, colormap=viridis,
|
||||
desaturate=True)
|
||||
|
||||
plt.imshow(out)
|
||||
plt.show()
|
||||
@@ -0,0 +1,30 @@
|
||||
"""
|
||||
================
|
||||
RAG Thresholding
|
||||
================
|
||||
|
||||
This example constructs a Region Adjacency Graph (RAG) and merges regions
|
||||
which are similar in color. We construct a RAG and define edges as the
|
||||
difference in mean color. We then join regions with similar mean color.
|
||||
|
||||
"""
|
||||
|
||||
from skimage import data, io, segmentation, color
|
||||
from skimage.future import graph
|
||||
from matplotlib import pyplot as plt
|
||||
|
||||
|
||||
img = data.coffee()
|
||||
|
||||
labels1 = segmentation.slic(img, compactness=30, n_segments=400)
|
||||
out1 = color.label2rgb(labels1, img, kind='avg')
|
||||
|
||||
g = graph.rag_mean_color(img, labels1)
|
||||
labels2 = graph.cut_threshold(labels1, g, 29)
|
||||
out2 = color.label2rgb(labels2, img, kind='avg')
|
||||
|
||||
plt.figure()
|
||||
io.imshow(out1)
|
||||
plt.figure()
|
||||
io.imshow(out2)
|
||||
io.show()
|
||||
@@ -0,0 +1,75 @@
|
||||
"""
|
||||
===========
|
||||
RAG Merging
|
||||
===========
|
||||
|
||||
This example constructs a Region Adjacency Graph (RAG) and progressively merges
|
||||
regions that are similar in color. Merging two adjacent regions produces
|
||||
a new region with all the pixels from the merged regions. Regions are merged
|
||||
until no highly similar region pairs remain.
|
||||
|
||||
"""
|
||||
|
||||
from skimage import data, io, segmentation, color
|
||||
from skimage.future import graph
|
||||
import numpy as np
|
||||
|
||||
|
||||
def _weight_mean_color(graph, src, dst, n):
|
||||
"""Callback to handle merging nodes by recomputing mean color.
|
||||
|
||||
The method expects that the mean color of `dst` is already computed.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
graph : RAG
|
||||
The graph under consideration.
|
||||
src, dst : int
|
||||
The vertices in `graph` to be merged.
|
||||
n : int
|
||||
A neighbor of `src` or `dst` or both.
|
||||
|
||||
Returns
|
||||
-------
|
||||
weight : float
|
||||
The absolute difference of the mean color between node `dst` and `n`.
|
||||
"""
|
||||
|
||||
diff = graph.node[dst]['mean color'] - graph.node[n]['mean color']
|
||||
diff = np.linalg.norm(diff)
|
||||
return diff
|
||||
|
||||
|
||||
def merge_mean_color(graph, src, dst):
|
||||
"""Callback called before merging two nodes of a mean color distance graph.
|
||||
|
||||
This method computes the mean color of `dst`.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
graph : RAG
|
||||
The graph under consideration.
|
||||
src, dst : int
|
||||
The vertices in `graph` to be merged.
|
||||
"""
|
||||
graph.node[dst]['total color'] += graph.node[src]['total color']
|
||||
graph.node[dst]['pixel count'] += graph.node[src]['pixel count']
|
||||
graph.node[dst]['mean color'] = (graph.node[dst]['total color'] /
|
||||
graph.node[dst]['pixel count'])
|
||||
|
||||
|
||||
img = data.coffee()
|
||||
labels = segmentation.slic(img, compactness=30, n_segments=400)
|
||||
g = graph.rag_mean_color(img, labels)
|
||||
|
||||
labels2 = graph.merge_hierarchical(labels, g, thresh=40, rag_copy=False,
|
||||
in_place_merge=True,
|
||||
merge_func=merge_mean_color,
|
||||
weight_func=_weight_mean_color)
|
||||
|
||||
g2 = graph.rag_mean_color(img, labels2)
|
||||
|
||||
out = color.label2rgb(labels2, img, kind='avg')
|
||||
out = segmentation.mark_boundaries(out, labels2, (0, 0, 0))
|
||||
io.imshow(out)
|
||||
io.show()
|
||||
@@ -0,0 +1,57 @@
|
||||
"""
|
||||
==========================
|
||||
Random walker segmentation
|
||||
==========================
|
||||
|
||||
The random walker algorithm [1]_ determines the segmentation of an image from
|
||||
a set of markers labeling several phases (2 or more). An anisotropic diffusion
|
||||
equation is solved with tracers initiated at the markers' position. The local
|
||||
diffusivity coefficient is greater if neighboring pixels have similar values,
|
||||
so that diffusion is difficult across high gradients. The label of each unknown
|
||||
pixel is attributed to the label of the known marker that has the highest
|
||||
probability to be reached first during this diffusion process.
|
||||
|
||||
In this example, two phases are clearly visible, but the data are too
|
||||
noisy to perform the segmentation from the histogram only. We determine
|
||||
markers of the two phases from the extreme tails of the histogram of gray
|
||||
values, and use the random walker for the segmentation.
|
||||
|
||||
.. [1] *Random walks for image segmentation*, Leo Grady, IEEE Trans. Pattern
|
||||
Anal. Mach. Intell. 2006 Nov; 28(11):1768-83
|
||||
|
||||
"""
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
from skimage.segmentation import random_walker
|
||||
from skimage.data import binary_blobs
|
||||
import skimage
|
||||
|
||||
# Generate noisy synthetic data
|
||||
data = skimage.img_as_float(binary_blobs(length=128, seed=1))
|
||||
data += 0.35 * np.random.randn(*data.shape)
|
||||
markers = np.zeros(data.shape, dtype=np.uint)
|
||||
markers[data < -0.3] = 1
|
||||
markers[data > 1.3] = 2
|
||||
|
||||
# Run random walker algorithm
|
||||
labels = random_walker(data, markers, beta=10, mode='bf')
|
||||
|
||||
# Plot results
|
||||
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(8, 3.2), sharex=True, sharey=True)
|
||||
ax1.imshow(data, cmap='gray', interpolation='nearest')
|
||||
ax1.axis('off')
|
||||
ax1.set_adjustable('box-forced')
|
||||
ax1.set_title('Noisy data')
|
||||
ax2.imshow(markers, cmap='hot', interpolation='nearest')
|
||||
ax2.axis('off')
|
||||
ax2.set_adjustable('box-forced')
|
||||
ax2.set_title('Markers')
|
||||
ax3.imshow(labels, cmap='gray', interpolation='nearest')
|
||||
ax3.axis('off')
|
||||
ax3.set_adjustable('box-forced')
|
||||
ax3.set_title('Segmentation')
|
||||
|
||||
fig.subplots_adjust(hspace=0.01, wspace=0.01, top=1, bottom=0, left=0,
|
||||
right=1)
|
||||
plt.show()
|
||||
@@ -0,0 +1,49 @@
|
||||
"""
|
||||
=========================
|
||||
Measure region properties
|
||||
=========================
|
||||
|
||||
This example shows how to measure properties of labelled image regions.
|
||||
|
||||
"""
|
||||
import math
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
|
||||
from skimage.draw import ellipse
|
||||
from skimage.measure import label, regionprops
|
||||
from skimage.transform import rotate
|
||||
|
||||
|
||||
image = np.zeros((600, 600))
|
||||
|
||||
rr, cc = ellipse(300, 350, 100, 220)
|
||||
image[rr, cc] = 1
|
||||
|
||||
image = rotate(image, angle=15, order=0)
|
||||
|
||||
label_img = label(image)
|
||||
regions = regionprops(label_img)
|
||||
|
||||
fig, ax = plt.subplots()
|
||||
ax.imshow(image, cmap=plt.cm.gray)
|
||||
|
||||
for props in regions:
|
||||
y0, x0 = props.centroid
|
||||
orientation = props.orientation
|
||||
x1 = x0 + math.cos(orientation) * 0.5 * props.major_axis_length
|
||||
y1 = y0 - math.sin(orientation) * 0.5 * props.major_axis_length
|
||||
x2 = x0 - math.sin(orientation) * 0.5 * props.minor_axis_length
|
||||
y2 = y0 - math.cos(orientation) * 0.5 * props.minor_axis_length
|
||||
|
||||
ax.plot((x0, x1), (y0, y1), '-r', linewidth=2.5)
|
||||
ax.plot((x0, x2), (y0, y2), '-r', linewidth=2.5)
|
||||
ax.plot(x0, y0, '.g', markersize=15)
|
||||
|
||||
minr, minc, maxr, maxc = props.bbox
|
||||
bx = (minc, maxc, maxc, minc, minc)
|
||||
by = (minr, minr, maxr, maxr, minr)
|
||||
ax.plot(bx, by, '-b', linewidth=2.5)
|
||||
|
||||
ax.axis((0, 600, 600, 0))
|
||||
plt.show()
|
||||
@@ -0,0 +1,95 @@
|
||||
"""
|
||||
====================================================
|
||||
Comparison of segmentation and superpixel algorithms
|
||||
====================================================
|
||||
|
||||
This example compares three popular low-level image segmentation methods. As
|
||||
it is difficult to obtain good segmentations, and the definition of "good"
|
||||
often depends on the application, these methods are usually used for obtaining
|
||||
an oversegmentation, also known as superpixels. These superpixels then serve as
|
||||
a basis for more sophisticated algorithms such as conditional random fields
|
||||
(CRF).
|
||||
|
||||
|
||||
Felzenszwalb's efficient graph based segmentation
|
||||
-------------------------------------------------
|
||||
This fast 2D image segmentation algorithm, proposed in [1]_ is popular in the
|
||||
computer vision community.
|
||||
The algorithm has a single ``scale`` parameter that influences the segment
|
||||
size. The actual size and number of segments can vary greatly, depending on
|
||||
local contrast.
|
||||
|
||||
.. [1] Efficient graph-based image segmentation, Felzenszwalb, P.F. and
|
||||
Huttenlocher, D.P. International Journal of Computer Vision, 2004
|
||||
|
||||
|
||||
Quickshift image segmentation
|
||||
-----------------------------
|
||||
|
||||
Quickshift is a relatively recent 2D image segmentation algorithm, based on an
|
||||
approximation of kernelized mean-shift. Therefore it belongs to the family of
|
||||
local mode-seeking algorithms and is applied to the 5D space consisting of
|
||||
color information and image location [2]_.
|
||||
|
||||
One of the benefits of quickshift is that it actually computes a
|
||||
hierarchical segmentation on multiple scales simultaneously.
|
||||
|
||||
Quickshift has two main parameters: ``sigma`` controls the scale of the local
|
||||
density approximation, ``max_dist`` selects a level in the hierarchical
|
||||
segmentation that is produced. There is also a trade-off between distance in
|
||||
color-space and distance in image-space, given by ``ratio``.
|
||||
|
||||
.. [2] Quick shift and kernel methods for mode seeking,
|
||||
Vedaldi, A. and Soatto, S.
|
||||
European Conference on Computer Vision, 2008
|
||||
|
||||
|
||||
SLIC - K-Means based image segmentation
|
||||
---------------------------------------
|
||||
|
||||
This algorithm simply performs K-means in the 5d space of color information and
|
||||
image location and is therefore closely related to quickshift. As the
|
||||
clustering method is simpler, it is very efficient. It is essential for this
|
||||
algorithm to work in Lab color space to obtain good results. The algorithm
|
||||
quickly gained momentum and is now widely used. See [3] for details. The
|
||||
``compactness`` parameter trades off color-similarity and proximity, as in the
|
||||
case of Quickshift, while ``n_segments`` chooses the number of centers for
|
||||
kmeans.
|
||||
|
||||
.. [3] Radhakrishna Achanta, Appu Shaji, Kevin Smith, Aurelien Lucchi,
|
||||
Pascal Fua, and Sabine Suesstrunk, SLIC Superpixels Compared to
|
||||
State-of-the-art Superpixel Methods, TPAMI, May 2012.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
|
||||
from skimage.data import astronaut
|
||||
from skimage.segmentation import felzenszwalb, slic, quickshift
|
||||
from skimage.segmentation import mark_boundaries
|
||||
from skimage.util import img_as_float
|
||||
|
||||
img = img_as_float(astronaut()[::2, ::2])
|
||||
segments_fz = felzenszwalb(img, scale=100, sigma=0.5, min_size=50)
|
||||
segments_slic = slic(img, n_segments=250, compactness=10, sigma=1)
|
||||
segments_quick = quickshift(img, kernel_size=3, max_dist=6, ratio=0.5)
|
||||
|
||||
print("Felzenszwalb's number of segments: %d" % len(np.unique(segments_fz)))
|
||||
print("Slic number of segments: %d" % len(np.unique(segments_slic)))
|
||||
print("Quickshift number of segments: %d" % len(np.unique(segments_quick)))
|
||||
|
||||
fig, ax = plt.subplots(1, 3, sharex=True, sharey=True, subplot_kw={'adjustable':'box-forced'})
|
||||
fig.set_size_inches(8, 3, forward=True)
|
||||
fig.subplots_adjust(0.05, 0.05, 0.95, 0.95, 0.05, 0.05)
|
||||
|
||||
ax[0].imshow(mark_boundaries(img, segments_fz))
|
||||
ax[0].set_title("Felzenszwalbs's method")
|
||||
ax[1].imshow(mark_boundaries(img, segments_slic))
|
||||
ax[1].set_title("SLIC")
|
||||
ax[2].imshow(mark_boundaries(img, segments_quick))
|
||||
ax[2].set_title("Quickshift")
|
||||
for a in ax:
|
||||
a.set_xticks(())
|
||||
a.set_yticks(())
|
||||
plt.show()
|
||||
@@ -0,0 +1,48 @@
|
||||
"""
|
||||
=====================
|
||||
Adaptive Thresholding
|
||||
=====================
|
||||
|
||||
Thresholding is the simplest way to segment objects from a background. If that
|
||||
background is relatively uniform, then you can use a global threshold value to
|
||||
binarize the image by pixel-intensity. If there's large variation in the
|
||||
background intensity, however, adaptive thresholding (a.k.a. local or dynamic
|
||||
thresholding) may produce better results.
|
||||
|
||||
Here, we binarize an image using the `threshold_adaptive` function, which
|
||||
calculates thresholds in regions of size `block_size` surrounding each pixel
|
||||
(i.e. local neighborhoods). Each threshold value is the weighted mean of the
|
||||
local neighborhood minus an offset value.
|
||||
|
||||
"""
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
from skimage import data
|
||||
from skimage.filters import threshold_otsu, threshold_adaptive
|
||||
|
||||
|
||||
image = data.page()
|
||||
|
||||
global_thresh = threshold_otsu(image)
|
||||
binary_global = image > global_thresh
|
||||
|
||||
block_size = 40
|
||||
binary_adaptive = threshold_adaptive(image, block_size, offset=10)
|
||||
|
||||
fig, axes = plt.subplots(nrows=3, figsize=(7, 8))
|
||||
ax0, ax1, ax2 = axes
|
||||
plt.gray()
|
||||
|
||||
ax0.imshow(image)
|
||||
ax0.set_title('Image')
|
||||
|
||||
ax1.imshow(binary_global)
|
||||
ax1.set_title('Global thresholding')
|
||||
|
||||
ax2.imshow(binary_adaptive)
|
||||
ax2.set_title('Adaptive thresholding')
|
||||
|
||||
for ax in axes:
|
||||
ax.axis('off')
|
||||
|
||||
plt.show()
|
||||
@@ -0,0 +1,66 @@
|
||||
"""
|
||||
======================
|
||||
Watershed segmentation
|
||||
======================
|
||||
|
||||
The watershed is a classical algorithm used for **segmentation**, that
|
||||
is, for separating different objects in an image.
|
||||
|
||||
Starting from user-defined markers, the watershed algorithm treats
|
||||
pixels values as a local topography (elevation). The algorithm floods
|
||||
basins from the markers, until basins attributed to different markers
|
||||
meet on watershed lines. In many cases, markers are chosen as local
|
||||
minima of the image, from which basins are flooded.
|
||||
|
||||
In the example below, two overlapping circles are to be separated. To
|
||||
do so, one computes an image that is the distance to the
|
||||
background. The maxima of this distance (i.e., the minima of the
|
||||
opposite of the distance) are chosen as markers, and the flooding of
|
||||
basins from such markers separates the two circles along a watershed
|
||||
line.
|
||||
|
||||
See Wikipedia_ for more details on the algorithm.
|
||||
|
||||
.. _Wikipedia: http://en.wikipedia.org/wiki/Watershed_(image_processing)
|
||||
|
||||
"""
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
from scipy import ndimage as ndi
|
||||
|
||||
from skimage.morphology import watershed
|
||||
from skimage.feature import peak_local_max
|
||||
|
||||
|
||||
# Generate an initial image with two overlapping circles
|
||||
x, y = np.indices((80, 80))
|
||||
x1, y1, x2, y2 = 28, 28, 44, 52
|
||||
r1, r2 = 16, 20
|
||||
mask_circle1 = (x - x1)**2 + (y - y1)**2 < r1**2
|
||||
mask_circle2 = (x - x2)**2 + (y - y2)**2 < r2**2
|
||||
image = np.logical_or(mask_circle1, mask_circle2)
|
||||
|
||||
# Now we want to separate the two objects in image
|
||||
# Generate the markers as local maxima of the distance to the background
|
||||
distance = ndi.distance_transform_edt(image)
|
||||
local_maxi = peak_local_max(distance, indices=False, footprint=np.ones((3, 3)),
|
||||
labels=image)
|
||||
markers = ndi.label(local_maxi)[0]
|
||||
labels = watershed(-distance, markers, mask=image)
|
||||
|
||||
fig, axes = plt.subplots(ncols=3, figsize=(8, 2.7), sharex=True, sharey=True, subplot_kw={'adjustable':'box-forced'})
|
||||
ax0, ax1, ax2 = axes
|
||||
|
||||
ax0.imshow(image, cmap=plt.cm.gray, interpolation='nearest')
|
||||
ax0.set_title('Overlapping objects')
|
||||
ax1.imshow(-distance, cmap=plt.cm.jet, interpolation='nearest')
|
||||
ax1.set_title('Distances')
|
||||
ax2.imshow(labels, cmap=plt.cm.spectral, interpolation='nearest')
|
||||
ax2.set_title('Separated objects')
|
||||
|
||||
for ax in axes:
|
||||
ax.axis('off')
|
||||
|
||||
fig.subplots_adjust(hspace=0.01, wspace=0.01, top=0.9, bottom=0, left=0,
|
||||
right=1)
|
||||
plt.show()
|
||||
Reference in New Issue
Block a user