使用字符串定义Numpy数组切片

时间:2017-03-29 09:43:45

标签: python arrays numpy slice

我的图像阵列的X倍Y形状为2048x2088。 x轴具有两个20个像素区域,一个在开始处,一个在末端,用于校准主图像区域。要访问这些区域,我可以像这样对数组进行切片:

prescan_area = img[:, :20]
data_area = img[:, 20:2068]
overscan_area = img[:, 2068:]

我的问题是如何在配置文件中定义这些区域,以便将此切片推广到可能具有不同预扫描和过扫描区域的其他相机,因此需要不同的切片。

理想情况下,类似下面的字符串将允许在相机特定配置文件中进行简单表示,但我不确定如何将这些字符串转换为数组切片。

prescan_area_def = "[:, :20]"
image_area_def = "[:, 20:2068]"
overscan_area_def = "[:, 2068:]"

也许有一些明显的东西让我失踪?

谢谢!

4 个答案:

答案 0 :(得分:3)

你可以这样做:

var1="img"
prescan_area_def = "[:, :20]"

并使用eval

prescan_area=eval(var1+prescan_area_def)

答案 1 :(得分:1)

您可以解析字符串并使用slicetuple中的以下生成器表达式将为您创建切片对象:

tuple(slice(*(int(i) if i else None for i in part.strip().split(':'))) for part in prescan_area_def.strip('[]').split(','))

演示:

In [5]: import numpy as np

In [6]: 

In [6]: a = np.arange(20).reshape(4, 5)

In [7]: a
Out[7]: 
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19]])

In [8]: 

In [8]: prescan_area_def = "[:, :3]"

In [9]: a[:, :3]
Out[9]: 
array([[ 0,  1,  2],
       [ 5,  6,  7],
       [10, 11, 12],
       [15, 16, 17]])

In [10]: indices = tuple(slice(*(int(i) if i else None for i in part.strip().split(':'))) for part in prescan_area_def.strip('[]').split(','))

In [11]: indices
Out[11]: (slice(None, None, None), slice(None, 3, None))

In [12]: a[indices]
Out[12]: 
array([[ 0,  1,  2],
       [ 5,  6,  7],
       [10, 11, 12],
       [15, 16, 17]])

答案 2 :(得分:0)

这是一种使用正则表达式的方法。

import numpy as np
import re

def slice_from_str(img, s):

    REGEX = r'\[(\d*):(\d*), (\d*):(\d*)\]'

    m = re.findall(REGEX,s)
    if m:
        # convert empty strings to None
        groups = [None if x=='' else int(x) for x in m[0]]
        start_x, end_x, start_y, end_y = groups
        x_slice = slice(start_x, end_x)
        y_slice = slice(start_y, end_y)

        return img[x_slice,y_slice]

    return []

img = np.random.rand(2048,2088)

prescan_area_def = '[:, :20]'
image_area_def = "[:, 20:2068]"
overscan_area_def = "[:, 2068:0]"

slice_from_str(img, prescan_area_def)
slice_from_str(img, image_area_def)
slice_from_str(img, overscan_area_def)

答案 3 :(得分:0)

出于对圣洁事物的热爱,请不要使用eval来解析简单的输入(请参阅下面的详细内容*)。

索引/切片组合字符串的答案,例如"[0, 1:5, :6, 13]"

扩展@Kasravnd出色的答案(但很可能令人困惑),这是一个函数,该函数将解析同时包含一维切片和标量索引的ND字符串切片:

def parseSlice(sliceStr):
    return tuple((slice(*(int(i) if i else None for i in part.strip().split(':'))) if ':' in part else int(part.strip())) for part in sliceStr.split(','))

简而言之,这是它的顺序:

  1. sliceStr分解为多个部分,原始part中的每个,每一个sliceStr

  2. 如果part包含:,请将其视为切片

    i。将part分解为索引,原始i中的每个:每一个part

    ii。将每个i转换为int

    iii。将生成的i值列表输入到内置slice函数中(*符号使您pass a list of args to a function

  3. 否则,将part视为标量索引,然后将part转换为int

  4. 最后,将intslice对象的结果序列包装到tuple中并返回

* eval怒吼

确实只有两种情况,有人会尝试使用eval从字符串中确定切片。要么a)用户是一个原始初学者,应被指示使用正确的非字符串语法来定义他们的片段,或者b)用户试图解析外部源提供的字符串,在这种情况下,他们会亲吻任何外表安全告别。 is no proven way to sanitize evalis no completely safe way to use evaleval really is amazingly dangerously

简而言之,可能实际上从未在代码中使用原始的eval调用。绝对不要在您打算公开发布的任何代码中使用eval。这就是严重外伤的发生。实际上,有99%的时间有比评估任何事情更好的解决方案(因为OP的问题),有99.9%的时间您可能会逃脱使用更安全的ast.literal_eval。是的,eval有一些合法的应用。不,您的用例几乎可以肯定不在.01%