-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwalmartFunctions.py
102 lines (92 loc) · 3.96 KB
/
walmartFunctions.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import random
import matplotlib.pyplot as plt
import numpy as np
import cv2
def display_img(img, title="Store Map", figsize=(15, 10), cmap='gray', minmax=True):
plt.figure(figsize=figsize)
if minmax:
plt.imshow(img, cmap=cmap, vmin=0, vmax=255)
else:
plt.imshow(img, cmap=cmap)
plt.title(title)
plt.show()
def perlin(x, y, seed=0):
np.random.seed(seed)
p = np.arange(256, dtype=int)
np.random.shuffle(p)
p = np.stack([p, p]).flatten()
xi = x.astype(int)
yi = y.astype(int)
xf = x - xi
yf = y - yi
u = fade(xf)
v = fade(yf)
n00 = gradient(p[p[xi] + yi], xf, yf)
n01 = gradient(p[p[xi] + yi + 1], xf, yf - 1)
n11 = gradient(p[p[xi + 1] + yi + 1], xf - 1, yf - 1)
n10 = gradient(p[p[xi + 1] + yi], xf - 1, yf)
x1 = lerp(n00, n10, u)
x2 = lerp(n01, n11, u)
return lerp(x1, x2, v)
def lerp(a, b, x):
return a + x * (b - a)
def fade(t):
return 6 * t**5 - 15 * t**4 + 10 * t**3
def gradient(h,x,y):
vectors = np.array([[0, 1], [0, -1], [1, 0], [-1, 0]])
g = vectors[h % 4]
return g[:, :, 0] * x + g[:, :, 1] * y
def generate_noise_image(width, height, origin=0, scale_factor=5, seed=2):
size = max([width, height])
scale_x = width / size
scale_y = height / size
X = np.linspace(origin, scale_factor * scale_x, width, endpoint=False)
Y = np.linspace(origin, scale_factor * scale_y, height, endpoint=False)
x, y = np.meshgrid(X, Y)
noise_img = perlin(x, y, seed=seed)
return noise_img
def get_traffic_map_and_targets(N_targets, noise_seed, target_seed, origin=0, scale_factor=5):
# Load store map
im_gray = cv2.imread('1150.png', cv2.IMREAD_GRAYSCALE)
# Binarize
thresh, im_bw = cv2.threshold(im_gray, 254, 255, cv2.THRESH_BINARY_INV)
# Fill holes to make impassable areas
collision_map = im_bw.copy()
contour, hier = cv2.findContours(collision_map, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
for cnt in contour:
cv2.drawContours(collision_map, [cnt], 0, 255, -1)
# Edge detect to generate valid targets
valid_targets = cv2.Laplacian(collision_map, cv2.CV_64F)
# Generate random targets
random.seed(target_seed)
im_targets = im_gray.copy()
ys, xs = valid_targets.nonzero()
target_indicies = random.sample(range(len(xs)), N_targets)
target_xs, target_ys = xs[target_indicies], ys[target_indicies]
# Generate noise image for traffic
width, height = len(im_targets[0]), len(im_targets)
noise_img = generate_noise_image(width, height, seed=noise_seed, origin=origin, scale_factor=scale_factor)
noise_img = (noise_img - np.min(noise_img)) / (np.max(noise_img) - np.min(noise_img))
# Merge noise and collisions
travel_friction = (~collision_map>0).astype(int) * noise_img
# Enforce collision map infinite condition
travel_friction[collision_map>0] = np.inf
# Make targets passable
for x, y in zip(target_xs, target_ys):
travel_friction[y][x] = 0
# Return the friction map and the target points
return travel_friction, list(zip(target_xs, target_ys))
def evaluate_path(traffic_map, target_points, path_points):
# Confirm the path is contiguous
for i in range(0, len(path_points) - 1):
if np.abs(path_points[i][0] - path_points[i+1][0]) + np.abs(path_points[i][1] - path_points[i+1][1]) > 1:
raise ValueError('Error in path between {0} @ {1} and {2} @ {3}. The path given by path_points has jumps - the path must never move more than 1 square in either the horizontal or vertical direction. Diagonal is not allowed.'.format(i, path_points[i], i+1, path_points[i+1]))
# Confirm all points were visited
for idx, tp in enumerate(target_points):
if tp not in path_points:
raise ValueError('Not all target points were visited. Point {0} @ {1} was not visited. Stopping evaluation.'.format(idx, tp))
# Determine the score
score = 0
for pp in path_points:
score += traffic_map[pp[1]][pp[0]]
return score