Couldn't find Moore boundary tracking algorithm (gw page 797) implemented in scikit-image, though it might be behind the covers as there are several ways to find boundaries: http://scikit-image.org/docs/dev/api/skimage.segmentation.html
I'll describe it instead.
In [1]:
%pylab inline
# turn of interpolation in imshow
mpl.rcParams['image.interpolation'] = 'none'
# create an image
img = np.zeros((8,8))
img[2,1:6] = 1
img[2:5, 5] = 1
imshow(img);
We have an edge
In [2]:
# first point, upper left
img[2,1] = 2
# start position for clockwise turn
img[2,0] = 3
# visualize
imshow(img);
Red: start point of edge search
Yellow: first boundary point
In [3]:
# traverse clockwise around first point to find border
img[1,0:3] = 3
# border found
img[2,2] = 4
# visualize
imshow(img);
Orange: Clockwise search
Green: Points in boundary
Red: Found connected point
In [4]:
# last empty pixel before new point is new start for clockwise turn
img[1:3,0] = 0
img[1,1] = 0
# border point is added
img[2,2] = 2
imshow(img);
Yellow: Points in boundary
Red: New edge search point
In [5]:
# now repeat
img[1,3] = 3
img[2,3] = 4
imshow(img);
Repeat the steps over and over.
Chain codes gives direction of border.
Using 0 left, 1 up, 2 right, 3 down, codes for border above would be:
0 (left)
0 (left)
0 (left)
0 (left)
3 (down)
3 (down)
or 000033
This might prove useful in finding direction an edge:
In [6]:
from skimage import data, measure
from skimage.color import rgb2gray
# get sample image
img = data.coffee()
img = rgb2gray(img)
# show it
figure(figsize=(14,14))
imshow(img, cmap="gray")
# find contours
contours = measure.find_contours(img, level=0.9)
# remove small ones
contours = [c for c in contours
if c.shape[0] > 100]
# draw them
for contour in contours:
plot(contour[:,1], contour[:,0])
xlim(0,img.shape[1])
ylim(img.shape[0],0);
Lets make the contours to polygons
In [7]:
figure(figsize=(14,14))
imshow(img, cmap="gray")
for contour in contours:
polygon = measure.approximate_polygon(contour, 10)
plot(polygon[:,1], polygon[:,0])
xlim(0,img.shape[1])
ylim(img.shape[0],0);
Find center of the circle, plot 1d signature (gw page 809)
In [8]:
# pick the first circle
circle = contours[0]
# find center of points
cy = np.mean(circle[:,0])
cx = np.mean(circle[:,1])
# calculate distance to each point
# assume the points are in order and equally spaces
distance = np.zeros(circle.shape[0])
for i,pos in enumerate(circle):
y,x = pos
distance[i] = sqrt((x-cx)**2 + (y-cy)**2)
ylim(0,120)
plot(distance);
Neat! Seems like it is a ellipse, not a circle :-)
Lets do the same with the polygon.
In [9]:
# find center of points
cy = np.mean(polygon[:,0])
cx = np.mean(polygon[:,1])
# calculate distance to each point
# assume the points are in order and equally spaces
distance = np.zeros(polygon.shape[0])
for i,pos in enumerate(polygon):
y,x = pos
distance[i] = sqrt((x-cx)**2 + (y-cy)**2)
ylim(0,110)
plot(distance);
Smallest convex set H which contains whole set S
In [10]:
from skimage.morphology import star, convex_hull_image
# create a set
S = star(60).astype(bool)
imshow(S)
# calculate convex hull
H = convex_hull_image(S)
# display it
figure()
imshow(H);
Same with our own defined polygon
In [15]:
from skimage.draw import polygon
# our polygon with four vertices
vertices = (np.array([0,100,0,50]), np.array([0,100,200,100]))
# create mask
mask = polygon(*vertices)
# create image
img = np.zeros((100,200))
img[mask] = 1
# create convex hull
H = convex_hull_image(img)
imshow(img)
figure()
imshow(H);
Two approaches exists in scikit-image: skeletonize and medial_axis
In [20]:
from skimage.morphology import medial_axis, skeletonize
medial = medial_axis(img)
imshow(medial)
title('medial axis')
skelet = skeletonize(img)
figure()
title('skeletonize')
imshow(skelet);
medial_axis may return distance to background also with return_distance=True