Numpy根据x/y索引操作True值数组

0 投票
1 回答
1380 浏览
提问于 2025-04-16 14:14

我有一个很大的数组(2048x2048),我想根据元素的位置进行一些逐个元素的操作。但是我对怎么做感到很困惑(有人告诉我不要使用for循环,结果我尝试的时候我的开发环境卡住了,速度也很慢)。

接下来是我的问题:

h = aperatureimage
h[:,:] = 0
indices = np.where(aperatureimage>1)

for True in h:
    h[index] = np.exp(1j*k*z)*np.exp(1j*k*(x**2+y**2)/(2*z))/(1j*wave*z)

我有一个索引,我假设它是我更大数组的一个“裁剪”版本。*注意:这个“光圈图像”是一个灰度图像转换成的数组,上面有形状或文字,我想找到所有“白色”区域并进行我的操作。

我该如何访问索引的每个x/y值,以便进行我的指数运算?当我尝试使用index[:,None]时,程序却报了‘ValueError: broadcast dimensions too large’的错误。我还遇到数组无法广播到正确形状的问题。希望能得到一些帮助!

再补充一下:我只想改变x和y的值(也就是我数组中白色的点,z、k和之前定义的其他值不变)。

编辑:

我不确定我上面发布的代码是否正确,它返回了两个空数组。不过,当我这样做时: index = (aperatureimage==1) print len(index)

实际上,我到目前为止做的事情都不正确。我有一张2048x2048的图像,中间有一个128x128的白色方块。我想把这张图像转换成数组,查看所有的值,确定数组中不是黑色的索引值(我只有黑白两色,双级图像对我没用)。然后我想把所有不是0的值(x,y)乘以上面提到的h[index]值。

如果需要,我可以提供更多信息。如果你能看出来,我现在卡住了。

编辑2:这里有一些可能有帮助的代码 - 我想我已经解决了上面的问题(我现在可以访问数组的成员并对它们进行操作)。但是 - 不知为何,我的for循环中的Fx值从来没有增加,Fy却一直循环下去……

import sys, os
from scipy.signal import *
import numpy as np
import Image, ImageDraw, ImageFont, ImageOps, ImageEnhance, ImageColor



def createImage(aperature, type):
    imsize = aperature*8
    middle = imsize/2
    im = Image.new("L", (imsize,imsize))
    draw = ImageDraw.Draw(im)
    box = ((middle-aperature/2, middle-aperature/2), (middle+aperature/2, middle+aperature/2))
import sys, os
from scipy.signal import *
import numpy as np
import Image, ImageDraw, ImageFont, ImageOps, ImageEnhance, ImageColor



def createImage(aperature, type):

    imsize = aperature*8 #Add 0 padding to make it nice
    middle = imsize/2 # The middle (physical 0) of our image will be the imagesize/2
    im = Image.new("L", (imsize,imsize)) #Make a grayscale image with imsize*imsize pixels
    draw = ImageDraw.Draw(im) #Create a new draw method
    box = ((middle-aperature/2, middle-aperature/2), (middle+aperature/2, middle+aperature/2)) #Bounding box for aperature
    if type == 'Rectangle':
        draw.rectangle(box, fill = 'white') #Draw rectangle in the box and color it white
    del draw
    return im, middle


def Diffraction(aperaturediameter = 1, type = 'Rectangle', z = 2000000, wave = .001):

    # Constants
    deltaF = 1/8 # Image will be 8mm wide
    z = 1/3.
    wave = 0.001
    k = 2*pi/wave

    # Now let's get to work
    aperature = aperaturediameter * 128 # Aperaturediameter (in mm) to some pixels
    im, middle = createImage(aperature, type) #Create an image depending on type of aperature 
    aperaturearray = np.array(im) # Turn image into numpy array

    # Fourier Transform of Aperature
    Ta = np.fft.fftshift(np.fft.fft2(aperaturearray))/(len(aperaturearray)) 

    # Transforming and calculating of Transfer Function Method
    H = aperaturearray.copy() # Copy image so H (transfer function) has the same dimensions as aperaturearray
    H[:,:] = 0 # Set H to 0
    U = aperaturearray.copy()
    U[:,:] = 0
    index = np.nonzero(aperaturearray) # Find nonzero elements of aperaturearray
    H[index[0],index[1]] = np.exp(1j*k*z)*np.exp(-1j*k*wave*z*((index[0]-middle)**2+(index[1]-middle)**2)) # Free space transfer for ap array
    Utfm = abs(np.fft.fftshift(np.fft.ifft2(Ta*H))) # Compute intensity at distance z

    # Fourier Integral Method
    apindex = np.nonzero(aperaturearray)
    U[index[0],index[1]] = aperaturearray[index[0],index[1]] * np.exp(1j*k*((index[0]-middle)**2+(index[1]-middle)**2)/(2*z))
    Ufim = abs(np.fft.fftshift(np.fft.fft2(U))/len(U))

    # Save image
    fim = Image.fromarray(np.uint8(Ufim))
    fim.save("PATH\Fim.jpg")
    ftfm = Image.fromarray(np.uint8(Utfm))
    ftfm.save("PATH\FTFM.jpg")
    print "that may have worked..."
    return

if __name__ == '__main__':
    Diffraction()

你需要numpy、scipy和PIL来处理这段代码。

当我运行这段代码时,它会执行,但里面没有数据(所有都是黑色的)。现在我遇到了一个真正的问题,因为我完全不理解我在做的数学(这是作业),而且我对Python也没有很好的掌握。

U[index[0],index[1]] = aperaturearray[index[0],index[1]] * np.exp(1j*k*((index[0]-middle)**2+(index[1]-middle)**2)/(2*z))

那行代码应该可以对我的数组进行逐元素计算吗?

1 个回答

2

你能不能发一个简单完整的例子?就是那种我们可以直接复制粘贴并运行的例子?

在此之前,你当前例子的前两行:

h = aperatureimage
h[:,:] = 0

你把'aperatureimage'和'h'都设置成了0。这可能不是你想要的。你可以考虑这样:

h = aperatureimage.copy()

这样做会生成'aperatureimage'的一个副本,而你的代码只是让'h'指向和'aperatureimage'相同的数组。所以如果你改变了一个,另一个也会跟着改变。要注意,复制非常大的数组可能会占用比你想要的更多内存。

我觉得你想做的是这个:

import numpy as np

N = 2048
M = 64

a = np.zeros((N, N))
a[N/2-M:N/2+M,N/2-M:N/2+M]=1

x,y = np.meshgrid(np.linspace(0, 1, N), np.linspace(0, 1, N))

b = a.copy()

indices = np.where(a>0)

b[indices] = np.exp(x[indices]**2+y[indices]**2)

或者类似的东西。无论如何,这样做会根据'x/y'坐标设置'b'中的一些值,前提是'a'大于0。试着用imshow来可视化一下。祝你好运!

关于编辑的内容

你应该把输出标准化,这样它才能适应8位整数。目前,你的一个数组的最大值远大于255,而另一个的最大值则远小于这个。试试这个:

fim = Image.fromarray(np.uint8(255*Ufim/np.amax(Ufim)))
fim.save("PATH\Fim.jpg")
ftfm = Image.fromarray(np.uint8(255*Utfm/np.amax(Utfm)))
ftfm.save("PATH\FTFM.jpg")

另外,考虑使用np.zeros_like(),而不是复制和清空H和U。

最后,我个人非常喜欢在开发这种东西时使用ipython。如果你把代码放在你的Diffraction函数的顶层(替换掉'if __ name __ &c.'),那么你就可以直接从ipython访问这些变量。像np.amax(Utfm)这样的快速命令会让你看到确实有值不等于0。imshow()总是很适合查看矩阵。

撰写回答