数组切片最大值取决于前一个轴的索引

时间:2014-03-06 17:13:01

标签: python arrays numpy slice

所以我有一个大的二维数组,来自一个tiff图像,我想在其中计算质心。为此,我使用图像的索引(作为坐标)和平均函数:

from PIL import Image
from numpy import *

Im    = Image.open("32bit_grayscale.tif")
imArr = array(Im, dtype='float32')
indx  = indices(imArr.shape)

cenMassX = average(indx[0,:,:],weights=imArr[:,:])
cenMassY = average(indx[1,:,:],weights=imArr[:,:])

在其他一些类似的图像中,我想要计算两个不同的质心。两个计算区域都由一条直的曲线分开,其中我有它的等式。

我想再次使用average方法,因为它非常有效,但我需要将indx数组的第二轴切片的最大值设置为函数当前的第一个轴值。如果该行类似于y=slope*x+interY,我需要这样的东西:

cenMassX_A = average(indx[0,:,:slope*row+interY],weights=imArr[:,:slope*row+interY])
cenMassY_A = average(indx[1,:,:slope*row+interY],weights=imArr[:,:slope*row+interY])
cenMassX_B = average(indx[0,:,slope*row+interY:],weights=imArr[:,slope*row+interY:])
cenMassY_B = average(indx[1,:,slope*row+interY:],weights=imArr[:,slope*row+interY:])

其中row表示第一轴索引的当前值(“x”轴)。忽视我可以根据等式取消数组限制的事实。

我可以使用for循环执行此操作,但效率非常低(因子为20)并且不是非常“pythonic”:

cenMassX_A = 0
cenMassY_A = 0
cumSum     = 0
for row in range(0,imArr.shape[0]):
    for col in range(0,int(round(slope*row+interY))):
        cenMassX_A += row*imArr[row,col]
        cenMassY_A += col*imArr[row,col]
        cumSum     += imArr[row,col]
cenMassX_A /= cumSum
cenMassY_A /= cumSum

cenMassX_B = 0
cenMassY_B = 0
cumSum     = 0
for row in range(0,imArr.shape[0]):
    for col in range(int(round(slope*row+interY)),imArr.shape[1]):
        cenMassX_B += row*imArr[row,col]
        cenMassY_B += col*imArr[row,col]
        cumSum     += imArr[row,col]
cenMassX_B /= cumSum
cenMassY_B /= cumSum

那么,有没有办法做到这一点,还是我坚持使用for循环?我一直在阅读关于面具和滚动窗户但仍无法找到解决方案。 提前谢谢!

2 个答案:

答案 0 :(得分:1)

如果您为一行或另一行的所有点设置imArr[i,j]=0会怎样?这是最简单的掩蔽方法。

I = indx[0,...]*slope + indx[1,...]>=M
imArr1 = imArr.copy()
imArr1[I]=0
print np.average(indx[0,...],weights=imArr1)
print np.average(indx[1,...],weights=imArr1)

imArr1 = imArr.copy()
imArr1[~I]=0

print np.average(indx[0,...],weights=imArr1)
print np.average(indx[1,...],weights=imArr1)

如果我拍摄一个简单的“图像”并将其连接到自身(水平或对角线),这样就可以了。

答案 1 :(得分:0)

为什么不使用你写的代码:

cenMassX_A = average(indx[0,:,:slope*row+interY],weights=inArr[:,:slope*row+interY])
cenMassY_A = average(indx[1,:,:slope*row+interY],weights=inArr[:,:slope*row+interY])

并逐行应用?

将for循环保留在行上,但用此代码替换col循环(将所有行的row-index更改为for循环中的行索引)。当然,您仍然需要将行中的结果添加到一起。