In [5]:
from math import sqrt
# import a bunch of stuff that we'll use to manipulate our images...
from skimage.io import imread
#from skimage import filter
from skimage.segmentation import slic
from skimage.segmentation import mark_boundaries
from skimage.util import img_as_float
from skimage import io
from skimage.measure import block_reduce
import numpy as np
from skimage.color import rgb2gray
from skimage import data
from skimage.filters import gaussian, roberts, sobel
from skimage.segmentation import active_contour
from skimage.transform import rescale
import scipy
from sklearn.cluster import KMeans
import pandas as pd
%matplotlib inline
import matplotlib.pyplot as plt
In [6]:
def get_line(start, end):
"""Bresenham's Line Algorithm
from: http://www.roguebasin.com/index.php?title=Bresenham%27s_Line_Algorithm
Produces a list of tuples from start and end
>>> points1 = get_line((0, 0), (3, 4))
>>> points2 = get_line((3, 4), (0, 0))
>>> assert(set(points1) == set(points2))
>>> print points1
[(0, 0), (1, 1), (1, 2), (2, 3), (3, 4)]
>>> print points2
[(3, 4), (2, 3), (1, 2), (1, 1), (0, 0)]
"""
# Setup initial conditions
x1, y1 = start
x2, y2 = end
dx = x2 - x1
dy = y2 - y1
# Determine how steep the line is
is_steep = abs(dy) > abs(dx)
# Rotate line
if is_steep:
x1, y1 = y1, x1
x2, y2 = y2, x2
# Swap start and end points if necessary and store swap state
swapped = False
if x1 > x2:
x1, x2 = x2, x1
y1, y2 = y2, y1
swapped = True
# Recalculate differentials
dx = x2 - x1
dy = y2 - y1
# Calculate error
error = int(dx / 2.0)
ystep = 1 if y1 < y2 else -1
# Iterate over bounding box generating points between start and end
y = y1
points = []
for x in range(x1, x2 + 1):
coord = (y, x) if is_steep else (x, y)
points.append(coord)
error -= abs(dy)
if error < 0:
y += ystep
error += dx
# Reverse the list if the coordinates were swapped
if swapped:
points.reverse()
return points
In [50]:
shelton = imread('img/test_portrait2.jpg')
#shelton = rescale(shelton, 0.25)
In [51]:
plt.imshow(shelton)
Out[51]:
In [52]:
shelton_gray = rgb2gray(shelton)
In [53]:
plt.imshow(shelton_gray, cmap=plt.get_cmap('gray'))
Out[53]:
In [54]:
shelton_edges = roberts(shelton_gray)
In [55]:
shelton_edges_rev = 1-shelton_edges
In [56]:
plt.imshow(shelton_edges_rev, cmap=plt.get_cmap('gray'))
Out[56]:
In [57]:
noise = np.random.random(shelton_edges_rev.shape)
shelton_edges_noisy = shelton_edges_rev - (noise*0.1)
shelton_edges_points = np.zeros(shelton_edges_noisy.shape)
shelton_edges_points[shelton_edges_noisy<0.8] = 1
In [58]:
shelton_edges_points
Out[58]:
In [59]:
shelton_edges_noisy
print len(np.transpose(np.nonzero(shelton_edges_points)))
print np.transpose(np.nonzero(shelton_edges_points))
shelton_points = np.transpose(np.nonzero(shelton_edges_points))
In [60]:
shelton_points
Out[60]:
In [61]:
# Calculate the euclidian distance in n-space of the route r traversing cities c, ending at the path start.
path_distance = lambda r,c: np.sum([np.linalg.norm(c[r[p]]-c[r[p-1]]) for p in range(len(r))])
# Reverse the order of all elements from element i to element k in array r.
two_opt_swap = lambda r,i,k: np.concatenate((r[0:i],r[k:-len(r)+i-1:-1],r[k+1:len(r)]))
def two_opt(cities,improvement_threshold): # 2-opt Algorithm adapted from https://en.wikipedia.org/wiki/2-opt
route = np.arange(cities.shape[0]) # Make an array of row numbers corresponding to cities.
improvement_factor = 1 # Initialize the improvement factor.
best_distance = path_distance(route,cities) # Calculate the distance of the initial path.
while improvement_factor > improvement_threshold: # If the route is still improving, keep going!
distance_to_beat = best_distance # Record the distance at the beginning of the loop.
for swap_first in range(1,len(route)-2): # From each city except the first and last,
for swap_last in range(swap_first+1,len(route)): # to each of the cities following,
new_route = two_opt_swap(route,swap_first,swap_last) # try reversing the order of these cities
new_distance = path_distance(new_route,cities) # and check the total distance with this modification.
if new_distance < best_distance: # If the path distance is an improvement,
route = new_route # make this the accepted best route
best_distance = new_distance # and update the distance corresponding to this route.
improvement_factor = 1 - best_distance/distance_to_beat # Calculate how much the route has improved.
return route # When the route is no longer improving substantially, stop searching and return the route.
In [62]:
# Create a matrix of cities, with each row being a location in 2-space (function works in n-dimensions).
#cities = np.random.RandomState(42).rand(70,2)
# Find a good route with 2-opt ("route" gives the order in which to travel to each city by row number.)
#route = two_opt(cities,0.001)
In [68]:
route = two_opt(shelton_points, 0.05)
In [64]:
route
Out[64]:
In [65]:
shelton_points[route]
Out[65]:
In [66]:
x, y = zip(*(shelton_points[route]))
In [67]:
plt.plot(y, x)
Out[67]:
In [47]:
plot_points = shelton_points[route]
In [48]:
def cable_steps(x, y, d=500, steps_per_inch=5):
a = int((sqrt(x**2 + y**2))*steps_per_inch)
b = int((sqrt((d-x)**2 + y**2))*steps_per_inch)
return a, b
In [ ]:
for