Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/351.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在python中高效地生成点阵_Python_Optimization_Numpy_Matplotlib_Scipy - Fatal编程技术网

在python中高效地生成点阵

在python中高效地生成点阵,python,optimization,numpy,matplotlib,scipy,Python,Optimization,Numpy,Matplotlib,Scipy,帮助加快我的代码速度:我的python代码需要生成一个二维点阵,点阵位于边界矩形内。我拼凑了一些生成这个晶格的代码(如下所示)。然而,这个函数被多次调用,已经成为我的应用程序中的一个严重瓶颈 我相信有一种更快的方法可以做到这一点,可能是使用numpy数组而不是列表。有没有关于更快、更优雅的方法的建议 功能说明: 我有两个二维向量,v1和v2。这些向量。在我的例子中,我的向量定义了一个几乎是六边形但不完全是六边形的晶格。我想生成该晶格上位于某个边界矩形中的所有2D点的集合。在我的例子中,矩形的一个

帮助加快我的代码速度:我的python代码需要生成一个二维点阵,点阵位于边界矩形内。我拼凑了一些生成这个晶格的代码(如下所示)。然而,这个函数被多次调用,已经成为我的应用程序中的一个严重瓶颈

我相信有一种更快的方法可以做到这一点,可能是使用numpy数组而不是列表。有没有关于更快、更优雅的方法的建议

功能说明: 我有两个二维向量,v1和v2。这些向量。在我的例子中,我的向量定义了一个几乎是六边形但不完全是六边形的晶格。我想生成该晶格上位于某个边界矩形中的所有2D点的集合。在我的例子中,矩形的一个角位于(0,0),其他角位于正坐标

示例: 如果边界矩形的远角位于(3,3),并且我的晶格向量为:

v1 = (1.2, 0.1)
v2 = (0.2, 1.1)
我希望我的函数返回点:

(1.2, 0.1) #v1
(2.4, 0.2) #2*v1
(0.2, 1.1) #v2
(0.4, 2.2) #2*v2
(1.4, 1.2) #v1 + v2
(2.6, 1.3) #2*v1 + v2
(1.6, 2.3) #v1 + 2*v2
(2.8, 2.4) #2*v1 + 2*v2
我不关心边缘案例;例如,函数是否返回(0,0)并不重要

我目前做这件事的缓慢方式

import numpy, pylab

def generate_lattice( #Help me speed up this function, please!
    image_shape, lattice_vectors, center_pix='image', edge_buffer=2):

    ##Preprocessing. Not much of a bottleneck:
    if center_pix == 'image':
        center_pix = numpy.array(image_shape) // 2
    else: ##Express the center pixel in terms of the lattice vectors
        center_pix = numpy.array(center_pix) - (numpy.array(image_shape) // 2)
        lattice_components = numpy.linalg.solve(
            numpy.vstack(lattice_vectors[:2]).T,
            center_pix)
        lattice_components -= lattice_components // 1
        center_pix = (lattice_vectors[0] * lattice_components[0] +
                      lattice_vectors[1] * lattice_components[1] +
                      numpy.array(image_shape)//2)
    num_vectors = int( ##Estimate how many lattice points we need
        max(image_shape) / numpy.sqrt(lattice_vectors[0]**2).sum())
    lattice_points = []
    lower_bounds = numpy.array((edge_buffer, edge_buffer))
    upper_bounds = numpy.array(image_shape) - edge_buffer

    ##SLOW LOOP HERE. 'num_vectors' is often quite large.
    for i in range(-num_vectors, num_vectors):
        for j in range(-num_vectors, num_vectors):
            lp = i * lattice_vectors[0] + j * lattice_vectors[1] + center_pix
            if all(lower_bounds < lp) and all(lp < upper_bounds):
                lattice_points.append(lp)
    return lattice_points


##Test the function and display the output.
##No optimization needed past this point.
lattice_vectors = [
    numpy.array([-40., -1.]),
    numpy.array([ 18., -37.])]
image_shape = (1000, 1000)
spots = generate_lattice(image_shape, lattice_vectors)

fig=pylab.figure()
pylab.plot([p[1] for p in spots], [p[0] for p in spots], '.')
pylab.axis('equal')
fig.show()
import numpy,pylab
def generate_lattice(#请帮我加速此功能!
图像形状、晶格向量、中心像素=图像、边缘缓冲区=2):
##预处理。没有太大的瓶颈:
如果中心点=图像:
center\u pix=numpy.array(图像\u形状)//2
else:##根据晶格向量表示中心像素
center\u pix=numpy.array(center\u pix)-(numpy.array(image\u shape)//2)
lattice_components=numpy.linalg.solve(
vstack(格向量[:2]).T,
中心(pix)
lattice_components-=lattice_components//1
中心点向量=(晶格向量[0]*晶格分量[0]+
格_向量[1]*格_分量[1]+
numpy.array(image\u shape)//2)
num_vectors=int(##估计我们需要多少晶格点
max(image\u shape)/numpy.sqrt(lattice\u vectors[0]**2.sum())
晶格_点=[]
下限=numpy.array((边缓冲区,边缓冲区))
上界=numpy.array(图像形状)-边缘缓冲区
##在这里慢转。”num_vectors'通常相当大。
对于范围内的i(-num\u向量,num\u向量):
对于范围内的j(-num\u向量,num\u向量):
lp=i*格点向量[0]+j*格点向量[1]+center\u pix
如果all(下限
由于
下限
上限
仅为2元素数组,因此numpy可能不是正确的选择。试着替换

if all(lower_bounds < lp) and all(lp < upper_bounds):
如果全部(下限
使用基本Python内容:

if lower1 < lp and lower2 < lp and lp < upper1 and lp < upper2:
如果lower1
根据timeit,第二种方法要快得多:

>>> timeit.timeit('all(lower < lp)', 'import numpy\nlp=4\nlower = numpy.array((1,5))') 
3.7948939800262451
>>> timeit.timeit('lower1 < 4 and lower2 < 4', 'lp = 4\nlower1, lower2 = 1,5') 
0.074192047119140625
>>>timeit.timeit('all(lower>>timeit.timeit('lower1<4,lower2<4','lp=4\nlower1,lower2=1,5')
0.074192047119140625
根据我的经验,只要您不需要处理n维数据,并且不需要双精度浮点,使用基本Python数据类型和构造而不是numpy通常会更快,在这种情况下,numpy有点过载--请看



另一个小的改进是只计算一次
范围(-num\u vectors,num\u vectors)
,然后重用它。此外,您可能希望使用一个而不是嵌套的for循环,尽管我认为这些更改不会对性能产生重大影响。

可能您可以用这个替换两个for循环

i,j = numpy.mgrid[-num_vectors:num_vectors, -num_vectors:num_vectors]
numel = num_vectors ** 2;
i = i.reshape(numel, 1)
j = j.reshape(numel, 1)
lp = i * lattice_vectors[0] + j * lattice_vectors[1] + center_pix
valid = numpy.all(lower_bounds < lp, 1) and numpy.all(lp < upper_bounds, 1)
lattice_points = lp[valid]
i,j=numpy.mgrid[-num\u vectors:num\u vectors,-num\u vectors:num\u vectors]
numel=num_向量**2;
i=i.重塑(努梅尔,1)
j=j.重塑(努梅尔,1)
lp=i*格点向量[0]+j*格点向量[1]+center\u pix
valid=numpy.all(下界
可能有一些小错误,但你明白了

编辑


我对“numpy.all(lower_bounds..”进行了编辑以说明正确的尺寸。

如果要对整个对象进行矢量化,请生成一个方形晶格,然后剪切它。然后切掉盒子外面的边缘

这是我想到的。仍然有很多改进可以做,但这是基本的想法

def generate_lattice(image_shape, lattice_vectors) :
    center_pix = numpy.array(image_shape) // 2
    # Get the lower limit on the cell size.
    dx_cell = max(abs(lattice_vectors[0][0]), abs(lattice_vectors[1][0]))
    dy_cell = max(abs(lattice_vectors[0][1]), abs(lattice_vectors[1][1]))
    # Get an over estimate of how many cells across and up.
    nx = image_shape[0]//dx_cell
    ny = image_shape[1]//dy_cell
    # Generate a square lattice, with too many points.
    # Here I generate a factor of 4 more points than I need, which ensures 
    # coverage for highly sheared lattices.  If your lattice is not highly
    # sheared, than you can generate fewer points.
    x_sq = np.arange(-nx, nx, dtype=float)
    y_sq = np.arange(-ny, nx, dtype=float)
    x_sq.shape = x_sq.shape + (1,)
    y_sq.shape = (1,) + y_sq.shape
    # Now shear the whole thing using the lattice vectors
    x_lattice = lattice_vectors[0][0]*x_sq + lattice_vectors[1][0]*y_sq
    y_lattice = lattice_vectors[0][1]*x_sq + lattice_vectors[1][1]*y_sq
    # Trim to fit in box.
    mask = ((x_lattice < image_shape[0]/2.0)
             & (x_lattice > -image_shape[0]/2.0))
    mask = mask & ((y_lattice < image_shape[1]/2.0)
                    & (y_lattice > -image_shape[1]/2.0))
    x_lattice = x_lattice[mask]
    y_lattice = y_lattice[mask]
    # Translate to the centre pix.
    x_lattice += center_pix[0]
    y_lattice += center_pix[1]
    # Make output compatible with original version.
    out = np.empty((len(x_lattice), 2), dtype=float)
    out[:, 0] = y_lattice
    out[:, 1] = x_lattice
    return out
def生成网格(图像形状、网格向量):
center\u pix=numpy.array(图像\u形状)//2
#获取单元格大小的下限。
dx_cell=max(abs(lattice_向量[0][0]),abs(lattice_向量[1][0]))
dy_cell=max(abs(lattice_向量[0][1]),abs(lattice_向量[1][1]))
#高估横过和向上的单元格数量。
nx=图像\u形状[0]//dx\u单元
ny=image\u shape[1]//dy\u单元
#生成点过多的方形晶格。
#在这里,我生成了比我需要的多4个点的因子,这确保了
#高度剪切晶格的覆盖率。如果你的格子不是很高
#剪切后,可以生成更少的点。
x_sq=np.arange(-nx,nx,dtype=float)
y_sq=np.arange(-ny,nx,dtype=float)
x_sq.shape=x_sq.shape+(1,)
y_sq.shape=(1,)+y_sq.shape
#现在使用晶格向量剪切整个物体
x_lat
lv0, lv1 = lattice_vectors[0], lattice_vectors[1]
lv0_i = -num_vectors * lv0 + center_pix
lv1_orig = -num_vectors * lv1
lv1_j = lv1_orig
for i in xrange(-num_vectors, num_vectors):
    for j in xrange(-num_vectors, num_vectors):
        lp = lv0_i + lv1_j
        if all(lower_bounds < lp) and all(lp < upper_bounds):
            lattice_points.append(lp)
        lv1_j += lv1
    lv0_i += lv0
    lv1_j = lv1_orig
>>> t = Timer("generate_lattice(image_shape, lattice_vectors, orig=True)", "from __main__ import generate_lattice, lattice_vectors, image_shape")
>>> print t.timeit(number=50)
5.20121788979
>>> t = Timer("generate_lattice(image_shape, lattice_vectors, orig=False)", "from __main__ import generate_lattice, lattice_vectors, image_shape")
>>> print t.timeit(number=50)
2.17463898659