如何从numpy数组中提取任意值行?


问题内容

我有一个包含一些图像数据的numpy数组。我想在图像上绘制横断面的“轮廓”。最简单的情况是轮廓平行于图像边缘,因此,如果图像阵列为imdat,则所选点处的轮廓(r,c)就是imdat[r](水平)或imdat[:,c](垂直)。

现在,我想把两个点(r1,c1)(r2,c2)都作为输入,它们都位于内部imdat。我想沿着连接这两点的线绘制值的轮廓。

沿着这样一条线从numpy数组中获取值的最佳方法是什么?更一般地说,沿着路径/多边形?

我以前使用过切片和索引,但是对于连续切片元素不在同一行或同一列中的这种情况,我似乎无法找到一种优雅的解决方案。谢谢你的帮助。


问题答案:

@Sven的答案是简单的方法,但是对于大型数组而言效率很低。如果您要处理的是相对较小的阵列,则不会注意到其中的区别,如果要从较大的配置文件(例如> 50
MB)中选择,则可能要尝试其他几种方法。但是,您需要在“像素”坐标中进行操作,因此存在一层额外的复杂性。

还有两种内存效率更高的方法。1)scipy.ndimage.map_coordinates如果需要双线性或三次插值,请使用。2)如果您只想要最近的邻居采样,则直接使用索引。

作为第一个示例:

import numpy as np
import scipy.ndimage
import matplotlib.pyplot as plt

#-- Generate some data...
x, y = np.mgrid[-5:5:0.1, -5:5:0.1]
z = np.sqrt(x**2 + y**2) + np.sin(x**2 + y**2)

#-- Extract the line...
# Make a line with "num" points...
x0, y0 = 5, 4.5 # These are in _pixel_ coordinates!!
x1, y1 = 60, 75
num = 1000
x, y = np.linspace(x0, x1, num), np.linspace(y0, y1, num)

# Extract the values along the line, using cubic interpolation
zi = scipy.ndimage.map_coordinates(z, np.vstack((x,y)))

#-- Plot...
fig, axes = plt.subplots(nrows=2)
axes[0].imshow(z)
axes[0].plot([x0, x1], [y0, y1], 'ro-')
axes[0].axis('image')

axes[1].plot(zi)

plt.show()

在此处输入图片说明

使用最近邻插值的等效项如下所示:

import numpy as np
import matplotlib.pyplot as plt

#-- Generate some data...
x, y = np.mgrid[-5:5:0.1, -5:5:0.1]
z = np.sqrt(x**2 + y**2) + np.sin(x**2 + y**2)

#-- Extract the line...
# Make a line with "num" points...
x0, y0 = 5, 4.5 # These are in _pixel_ coordinates!!
x1, y1 = 60, 75
num = 1000
x, y = np.linspace(x0, x1, num), np.linspace(y0, y1, num)

# Extract the values along the line
zi = z[x.astype(np.int), y.astype(np.int)]

#-- Plot...
fig, axes = plt.subplots(nrows=2)
axes[0].imshow(z)
axes[0].plot([x0, x1], [y0, y1], 'ro-')
axes[0].axis('image')

axes[1].plot(zi)

plt.show()

在此处输入图片说明

但是,如果您使用的是最近邻,您可能只希望在每个像素处采样,因此您可能会做更多类似的事情,而不是…

import numpy as np
import matplotlib.pyplot as plt

#-- Generate some data...
x, y = np.mgrid[-5:5:0.1, -5:5:0.1]
z = np.sqrt(x**2 + y**2) + np.sin(x**2 + y**2)

#-- Extract the line...
# Make a line with "num" points...
x0, y0 = 5, 4.5 # These are in _pixel_ coordinates!!
x1, y1 = 60, 75
length = int(np.hypot(x1-x0, y1-y0))
x, y = np.linspace(x0, x1, length), np.linspace(y0, y1, length)

# Extract the values along the line
zi = z[x.astype(np.int), y.astype(np.int)]

#-- Plot...
fig, axes = plt.subplots(nrows=2)
axes[0].imshow(z)
axes[0].plot([x0, x1], [y0, y1], 'ro-')
axes[0].axis('image')

axes[1].plot(zi)

plt.show()

在此处输入图片说明