我正在使用https://github.com/ReScience-Archives/Rougier-2017/tree/master/code
中的代码运行它时出现错误:
for region in vor.filtered_regions:
NameError: name 'vor' is not defined
这是stippler.py文件中的相关代码:
stippler.py
import tqdm
import voronoi
import os.path
import scipy.misc
import scipy.ndimage
import numpy as np
---- ---
# Plot voronoi regions if you want
for region in vor.filtered_regions:
vertices = vor.vertices[region, :]
ax.plot(vertices[:, 0], vertices[:, 1], linewidth=.5, color='.5' )
这是导入文件voronoi.py中的代码
voronoi.py
import numpy as np
import scipy.spatial
def rasterize(V):
n = len(V)
X, Y = V[:, 0], V[:, 1]
ymin = int(np.ceil(Y.min()))
ymax = int(np.floor(Y.max()))
#ymin = int(np.round(Y.min()))
#ymax = int(np.round(Y.max()))
P = []
for y in range(ymin, ymax+1):
segments = []
for i in range(n):
index1, index2 = (i-1) % n, i
y1, y2 = Y[index1], Y[index2]
x1, x2 = X[index1], X[index2]
if y1 > y2:
y1, y2 = y2, y1
x1, x2 = x2, x1
elif y1 == y2:
continue
if (y1 <= y < y2) or (y == ymax and y1 < y <= y2):
segments.append((y-y1) * (x2-x1) / (y2-y1) + x1)
segments.sort()
for i in range(0, (2*(len(segments)//2)), 2):
x1 = int(np.ceil(segments[i]))
x2 = int(np.floor(segments[i+1]))
# x1 = int(np.round(segments[i]))
# x2 = int(np.round(segments[i+1]))
P.extend([[x, y] for x in range(x1, x2+1)])
if not len(P):
return V
return np.array(P)
def rasterize_outline(V):
n = len(V)
X, Y = V[:, 0], V[:, 1]
ymin = int(np.ceil(Y.min()))
ymax = int(np.floor(Y.max()))
points = np.zeros((2+(ymax-ymin)*2, 3), dtype=int)
index = 0
for y in range(ymin, ymax+1):
segments = []
for i in range(n):
index1, index2 = (i-1) % n , i
y1, y2 = Y[index1], Y[index2]
x1, x2 = X[index1], X[index2]
if y1 > y2:
y1, y2 = y2, y1
x1, x2 = x2, x1
elif y1 == y2:
continue
if (y1 <= y < y2) or (y == ymax and y1 < y <= y2):
segments.append((y-y1) * (x2-x1) / (y2-y1) + x1)
segments.sort()
for i in range(0, (2*(len(segments)//2)), 2):
x1 = int(np.ceil(segments[i]))
x2 = int(np.ceil(segments[i+1]))
points[index] = x1, x2, y
index += 1
return points[:index]
def weighted_centroid_outline(V, P, Q):
O = rasterize_outline(V)
X1, X2, Y = O[:,0], O[:,1], O[:,2]
Y = np.minimum(Y, P.shape[0]-1)
X1 = np.minimum(X1, P.shape[1]-1)
X2 = np.minimum(X2, P.shape[1]-1)
d = (P[Y,X2]-P[Y,X1]).sum()
x = ((X2*P[Y,X2] - Q[Y,X2]) - (X1*P[Y,X1] - Q[Y,X1])).sum()
y = (Y * (P[Y,X2] - P[Y,X1])).sum()
if d:
return [x/d, y/d]
return [x, y]
def uniform_centroid(V):
"""
Given an ordered set of vertices V describing a polygon,
returns the uniform surface centroid.
See http://paulbourke.net/geometry/polygonmesh/
"""
A = 0
Cx = 0
Cy = 0
for i in range(len(V)-1):
s = (V[i, 0]*V[i+1, 1] - V[i+1, 0]*V[i, 1])
A += s
Cx += (V[i, 0] + V[i+1, 0]) * s
Cy += (V[i, 1] + V[i+1, 1]) * s
Cx /= 3*A
Cy /= 3*A
return [Cx, Cy]
def weighted_centroid(V, D):
P = rasterize(V)
Pi = P.astype(int)
Pi[:, 0] = np.minimum(Pi[:, 0], D.shape[1]-1)
Pi[:, 1] = np.minimum(Pi[:, 1], D.shape[0]-1)
D = D[Pi[:, 1], Pi[:, 0]].reshape(len(Pi), 1)
return ((P*D)).sum(axis=0) / D.sum()
def in_box(points, bbox):
return np.logical_and(
np.logical_and(bbox[0] <= points[:, 0], points[:, 0] <= bbox[1]),
np.logical_and(bbox[2] <= points[:, 1], points[:, 1] <= bbox[3]))
def voronoi(points, bbox):
i = in_box(points, bbox)
points_center = points[i, :]
points_left = np.copy(points_center)
points_left[:, 0] = bbox[0] - (points_left[:, 0] - bbox[0])
points_right = np.copy(points_center)
points_right[:, 0] = bbox[1] + (bbox[1] - points_right[:, 0])
points_down = np.copy(points_center)
points_down[:, 1] = bbox[2] - (points_down[:, 1] - bbox[2])
points_up = np.copy(points_center)
points_up[:, 1] = bbox[3] + (bbox[3] - points_up[:, 1])
points = np.append(points_center,
np.append(np.append(points_left, points_right, axis=0),
np.append(points_down, points_up, axis=0),
axis=0), axis=0)
# Compute Voronoi
vor = scipy.spatial.Voronoi(points)
# Filter regions
epsilon = 0.1
regions = []
for region in vor.regions:
flag = True
for index in region:
if index == -1:
flag = False
break
else:
x = vor.vertices[index, 0]
y = vor.vertices[index, 1]
if not(bbox[0]-epsilon <= x <= bbox[1]+epsilon and
bbox[2]-epsilon <= y <= bbox[3]+epsilon):
flag = False
break
if region != [] and flag:
regions.append(region)
vor.filtered_points = points_center
vor.filtered_regions = regions
return vor
def centroids(points, density, density_P=None, density_Q=None):
"""
Given a set of point and a density array, return the set of weighted
centroids.
"""
X, Y = points[:,0], points[:, 1]
# You must ensure:
# 0 < X.min() < X.max() < density.shape[0]
# 0 < Y.min() < Y.max() < density.shape[1]
xmin, xmax = 0, density.shape[1]
ymin, ymax = 0, density.shape[0]
bbox = np.array([xmin, xmax, ymin, ymax])
vor = voronoi(points, bbox)
regions = vor.filtered_regions
centroids = []
for region in regions:
vertices = vor.vertices[region + [region[0]], :]
# vertices = vor.filtered_points[region + [region[0]], :]
# Full version from all the points
# centroid = weighted_centroid(vertices, density)
# Optimized version from only the outline
centroid = weighted_centroid_outline(vertices, density_P, density_Q)
centroids.append(centroid)
return regions, np.array(centroids)
我是python的新手,所以除了知道它与vor未被定义或导入问题有关之外,我不确定导致该错误的原因是什么?
答案 0 :(得分:0)
问题在于访问变量之前未定义变量“ vor”。
答案 1 :(得分:0)
This is entirely too much code to post, you need to trim it down to just show a minimum complete viable example. With that being said in stippler.py
you import voronoi
which is a function which returns vor
according to voronoi.py
. Nowhere in stippler.py
do you call on that function to return vor
which is what you want. You also have the problem that your script has the same name as your function so you would probably need to do something like the following in order to call the function:
from voronoi import voronoi
# feed your function the relevant inputs
vor = voronoi(points, bbox)
# continue your code here
答案 2 :(得分:0)
该代码had been commented out in the original code,大概是因为它不再起作用了(如您所知)。
具有vor
属性的filtered_regions
对象是由voronoi.voronoi()
函数生成的,但似乎不再被当前代码调用。
也许只是
vor = voronoi.voronoi(points, bbox)
在该细分受众群修复之前。