【问题标题】:Fastest way to create list of (X,Y) incrementing tuples with step value?创建具有步长值的(X,Y)递增元组列表的最快方法?
【发布时间】:2021-01-30 17:11:52
【问题描述】:

我需要一种快速的方法来创建表示图像像素坐标的元组列表(X, Y)

其中X 是从0sizeY 是从0size

1 的步长值导致 (0, 1, 2, 3...) 的 XY 值是太多的元组。使用大于1 的步长值将减少处理时间。例如,如果步长值为2,则值为 (0, 2, 4, 6...)。如果步长值为 4,则值为 (0, 4, 8, 12...)。

在纯 python 中可能会使用range 命令。但是,NumPy 默认安装在我的 Linux 发行版中。在 NumPy 中,可能会使用 arrange 命令,但我很难将注意力集中在 NumPy 数组语法上。

PS:创建元组列表后,它会被随机打乱,然后在循环中读取。


编辑 1

在下面使用this answer

它不是从左到右进行某种奇怪的擦除,而不是图像消失。使用答案中的代码稍作修改:

        step = 4
        size = self.play_rotated_art.size[0] - step

        self.xy_list = [
            (x, y)
            for x in range(0, size - step, step)
            for y in range(0, size - step, step)
        ]

错误更新

我的代码有错误,现在可以正常工作了:

更新后的代码是:

        self.step = 4
        size = self.play_rotated_art.size[0] - self.step

        self.xy_list = [
            (x, y)
            for x in range(0, size - self.step, self.step)
            for y in range(0, size - self.step, self.step)
        ]

        shuffle(self.xy_list)
        # Convert numpy array into python list & calculate chunk size
        self.current_chunk = 0
        self.chunk_size = int(len(self.xy_list) / 100)

    # Where we stop copying pixels for current 1% chunck
    end = self.current_chunk + self.chunk_size
    if end > len(self.xy_list) - 1:
       end = len(self.xy_list) - 1

    while self.current_chunk < end:
        x0, y0 = self.xy_list[self.current_chunk]
        x1 = x0 + self.step
        y1 = y0 + self.step
        box = (x0, y0, x1, y1)
        region = self.play_rotated_art.crop(box)
        self.fade.paste(region, box)
        self.current_chunk += 1

    self.play_artfade_count += 1
    return self.fade

TL;DR

我已经有带有步长值1 的代码,但是此代码过于复杂且请求修改效率低下。上述一般性问题将对其他人有更多帮助,如果得到回答,仍然对我有帮助。

步长值1的现有代码:

def play_artfade2(self):
    ''' PILLOW VERSION:
        Fade in artwork in 100 chunks leaving loop after chunk and
        reentering after Tkinter updates screen and pauses.
    '''
    if self.play_artfade_count == 100:
        # We'have completed a full cycle. Force graphical effects exit
        self.play_artfade_count = 0         # Reset art fade count
        self.play_rotated_value = -361      # Force Spin Art
        return None

    # Initialize numpy arrays first time through
    if self.play_artfade_count == 0:

        # Create black image to fade into
        self.fade = Image.new('RGBA', self.play_rotated_art.size, \
                              color='black')

        # Generate a randomly shuffled array of the coordinates
        im = np.array(self.play_rotated_art)
        X,Y = np.where(im[...,0]>=0)
        coords = np.column_stack((X,Y))
        np.random.shuffle(coords)

        # Convert numpy array into python list & calculate chunk size
        self.xy_list = list(coords)
        self.current_chunk = 0
        self.chunk_size = int(len(self.xy_list) / 100)

    # Where we stop copying pixels for current 1% chunck
    end = self.current_chunk + self.chunk_size
    if end > len(self.xy_list) - 1:
       end = len(self.xy_list) - 1

    while self.current_chunk < end:
        x0, y0 = self.xy_list[self.current_chunk]
        x1 = x0 + 1
        y1 = y0 + 1
        box = (x0, y0, x1, y1)
        region = self.play_rotated_art.crop(box)
        self.fade.paste(region, box)
        self.current_chunk += 1

    self.play_artfade_count += 1
    return self.fade

使用 Pillow 的 Image.crop()Image.paste() 对于单个像素来说太过分了,但最初的工作设计未来专注于利用盒子大小为的“超级像素” 2x2、3x3、5x5 等,因为图像从 200x200 调整为 333x333 到 512x512 等。

【问题讨论】:

    标签: python list numpy tuples


    【解决方案1】:

    我需要快速创建表示图像像素坐标 (X, Y) 的元组列表。

    X 是从 0 到 size,Y 是从 0 到 size

    range 的列表理解将起作用:

    xsize = 10
    ysize = 10
    coords = [(x, y) for x in range(xsize) for y in range(ysize)]
    
    # this verifies the shape is correct
    assert len(coords) == xsize * ysize
    

    如果您想要1 以外的步骤,这是设置步骤参数:

    coords = [(x, y) for x in range(0, xsize, 2) for y in range(0, ysize, 2)]
    

    【讨论】:

    • 我认为这与第一个答案基本相同,但作为返回列表的一个班轮?
    【解决方案2】:

    您可以使用生成器表达式:

    size = 16
    step = 4
    
    coords = (
        (x, y)
        for x in range(0, size, step)
        for y in range(0, size, step)
    )
    

    然后您可以像使用 list 一样对其进行迭代

    for coord in coords:
        print(coord)
    

    使用生成器而不是列表或元组的优点是内存效率更高。

    【讨论】:

    • 感谢您的回答,但我觉得仍然需要一个列表,因为我将其处理为 100 个块。
    • coords = ...中的外部()替换为[],生成器将被收集到一个列表中。
    • 我会试一试的。谢谢。
    • 我试过你的答案,但我不认为 [(X, Y), (X,Y)...] 生成正确?我用输出更新了我的问题。
    • 忽略最后的评论。我的代码中有错误,我用正确的图像和代码更新了我的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-20
    • 2021-11-11
    • 2016-09-03
    • 1970-01-01
    相关资源
    最近更新 更多