In [1]:
import itertools
import feedparser
import urllib
import io
import pandas
import skimage.segmentation
import networkx
In [2]:
FEED='http://api.flickr.com/services/feeds/photos_public.gne?tags=beach;sand;waves'
In [3]:
feed = feedparser.parse(FEED)
In [4]:
photos = []
for entry in feed.entries:
for link in entry.links:
if link['rel'] == 'enclosure':
photos.append(link['href'])
In [10]:
import IPython.display
IPython.display.Image(url=photos[5])
Out[10]:
In [11]:
# Read the data as array
f = io.BytesIO(urllib.urlopen(photos[5]).read())
f.seek(0)
img = plt.imread(f, format='jpg')
In [12]:
# What do we have
plt.imshow(img)
Out[12]:
In [13]:
# Compute superpixels
slice=2 # Reduce because I don't have the fast version built
imgsliced = img[::slice,::slice]
superpixel = skimage.segmentation.slic(imgsliced, n_segments=200,ratio=20)
In [15]:
# use a trick to show a segmented img
plt.imshow(superpixel % 11, cmap='Set3')
Out[15]:
In [16]:
# Create a table of pixels
rows=[]
for (i,j), px in np.ndenumerate(superpixel):
row = [i,j,px]
row.extend(imgsliced[i,j])
rows.append(row)
df = pandas.DataFrame(data=rows, columns=["i", "j", "superpixel", "R", "G", "B"])
In [17]:
# Compute superpixel properties
agg = df.groupby("superpixel").mean()
meaned = np.floor(agg.ix[superpixel.ravel()][["R", "G", "B"]].as_matrix()).astype('uint8')
meaned = meaned.reshape(imgsliced.shape)
In [18]:
# Something went wrong with the means here...
# Triangulate to setup node connections
fig, ax = plt.subplots(figsize=(15,10))
ax.imshow(meaned)
# plot the mean location of each superpixel
ax.plot(agg.j, agg.i, 'k.')
Out[18]:
In [19]:
# Compute triangulation, can we reduce the number of connections?
tri = matplotlib.tri.triangulation.Triangulation(agg.j, agg.i)
matplotlib.tri.triplot(ax, tri)
# show the figure
fig
Out[19]:
In [20]:
# Generate a graph from the triangular network
graph = networkx.Graph()
for (i, row) in agg.iterrows():
graph.add_node(row.name, i=row['i'])
distances = np.sqrt(np.diff(tri.x[tri.edges],1)**2 + np.diff(tri.y[tri.edges],1)**2)
for (edge, distance) in zip(tri.edges, distances):
graph.add_edge(*edge, distance=distance[0])
graphoriginal = graph.copy()
In [21]:
# This should show up as a similar picture to the original node position
networkx.draw_spring(graph, weight="distance")
In [22]:
graph = graphoriginal.copy()
for node in graph.nodes():
plt.plot(agg.ix[node]['j'], agg.ix[node]['i'], 'k.')
for edge in graph.edges():
plt.plot(agg.ix[np.array(edge)]['j'], agg.ix[np.array(edge)]['i'], 'b-')
edges = sorted(graph.edges(data=True), key=lambda x:x[2]['distance'], reverse=True)
i = 0.1
for edge in edges:
# can we toss this one out?
if len(graph.edge[edge[0]]) >4 and len(graph.edge[edge[1]]) >4:
plt.plot(agg.ix[np.array(edge[:2])]['j'], agg.ix[np.array(edge[:2])]['i'], linewidth=1/float(i), color='red')
i += 0.005
graph.remove_edge(edge[0], edge[1])
In [23]:
for node in graph.nodes():
plt.plot(agg.ix[node]['j'], agg.ix[node]['i'], 'k.')
for edge in graph.edges():
plt.plot(agg.ix[np.array(edge)]['j'], agg.ix[np.array(edge)]['i'], 'b-')
In [24]:
# Compute the number of rows and columns
N = len(agg)
# pixels per superpixel
R = float(imgsliced.shape[0])/float(imgsliced.shape[1])
# average height
nrow = int(round((N/R)**0.5))
ncol = int(round((N*R)**0.5))
# Pixelsize, approximately
S = np.sqrt((imgsliced.shape[0]*imgsliced.shape[1])/float(N))
S, imgsliced.shape[0]/S, imgsliced.shape[1]/S
assert nrow*ncol == N, "{} != {}".format(nrow*ncol, N)
In [25]:
# oh, it's just....
rows = superpixel % nrow
cols = superpixel // nrow
(cols*nrow + rows == superpixel).all()
Out[25]:
In [26]:
df['m'] = rows.ravel()
df['n'] = cols.ravel()
In [27]:
fig, ax = plt.subplots(figsize=(15,10))
ax.imshow(meaned)
# plot the mean location of each superpixel
ax.plot(agg.j, agg.i, 'k.')
for i in range(nrow):
for j in range(ncol):
node0 = j*nrow + i
node1 = j*nrow + i+1
node2 = (j+1)*nrow + i
edge1 = np.array([node0, node1])
edge2 = np.array([node0, node2])
if i<(nrow-1):
ax.plot(agg.ix[edge1]['j'], agg.ix[edge1]['i'], 'k-')
if j<(ncol-1):
ax.plot(agg.ix[edge2]['j'], agg.ix[edge2]['i'], 'k-')
In [28]:
N, R, nrow, ncol, (N/R)**0.5, (N*R)**0.5
Out[28]:
In [186]:
In [186]: