【问题标题】:Array slice maximum that depends on the index of the previous axis取决于前一个轴的索引的数组切片最大值
【发布时间】:2014-03-06 17:13:00
【问题描述】:

所以我有一个来自 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 循环?我一直在阅读有关口罩和滚动窗户的信息,但仍然无法找到解决方案。 提前致谢!

【问题讨论】:

    标签: python arrays numpy slice


    【解决方案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)
    

    如果我拍摄一个简单的“图像”并将其连接到自身(水平或对角),这会很好。

    【讨论】:

    • 经过测试,它非常出色,速度非常快,提高了 40 倍。这是我的想法之一,但无法理解掩码的工作原理。我相信虽然I 的定义应该有一个符号变化,而且为了保持一致,MinterY 所以:I = -indx[0,...]*slope + indx[1,...]>=interY。我会编辑你的帖子。
    【解决方案2】:

    为什么不用你写的代码:

    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-loops(将所有行的行索引更改为 for 循环中的行索引)。当然,您仍然需要将行中的结果相加。

    【讨论】:

    • 它可以工作并提高性能,但我仍然想摆脱 所有 for 循环
    猜你喜欢
    • 2020-11-03
    • 2017-09-20
    • 2011-09-30
    • 1970-01-01
    • 2021-04-19
    • 2015-03-27
    • 2017-03-27
    • 1970-01-01
    相关资源
    最近更新 更多