NameError问题:未定义名称“ vor”

时间:2019-05-06 11:21:53

标签: python

我正在使用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未被定义或导入问题有关之外,我不确定导致该错误的原因是什么?

3 个答案:

答案 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)

在该细分受众群修复之前。