import itertools import feedparser import urllib import io import pandas import skimage.segmentation import networkx FEED='http://api.flickr.com/services/feeds/photos_public.gne?tags=beach;sand;waves' feed = feedparser.parse(FEED) photos = [] for entry in feed.entries: for link in entry.links: if link['rel'] == 'enclosure': photos.append(link['href']) import IPython.display IPython.display.Image(url=photos[5]) # Read the data as array f = io.BytesIO(urllib.urlopen(photos[5]).read()) f.seek(0) img = plt.imread(f, format='jpg') # What do we have plt.imshow(img) # 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) # use a trick to show a segmented img plt.imshow(superpixel % 11, cmap='Set3') # 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"]) # 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) # 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.') # 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 # 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() # This should show up as a similar picture to the original node position networkx.draw_spring(graph, weight="distance") 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]) 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-') # 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) # oh, it's just.... rows = superpixel % nrow cols = superpixel // nrow (cols*nrow + rows == superpixel).all() df['m'] = rows.ravel() df['n'] = cols.ravel() 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-') N, R, nrow, ncol, (N/R)**0.5, (N*R)**0.5