【问题标题】:NumPy: How to check if a tuple is in a 1D numpy arrayNumPy:如何检查元组是否在一维 numpy 数组中
【发布时间】:2021-10-24 06:06:03
【问题描述】:

我在尝试检查 python 元组是否在一维 numpy 数组中时遇到了一些麻烦。我正在研究一个循环,它将记录图像中存在的所有颜色并将它们存储到一个数组中。使用普通列表效果很好,但图像非常大,我认为 NumPy 数组会加快循环,因为它需要几分钟才能完成循环。

代码如下:

from PIL import Image
import numpy as np

img = Image.open("bg.jpg").convert("RGB")
pixels = img.load()

colors = np.array([])

for h in range(img.size[1]):
    for w in range(img.size[0]):
        if pixels[w,h] not in colors:
            colors = np.append(colors, pixels[w,h])
        else:
            continue

当我运行它时,我收到以下错误:

DeprecationWarning: elementwise comparison failed; this will raise an error in the future.
  if pixels[w,h] in colors:

提前致谢,如果您知道更快的方法,请告诉我。

【问题讨论】:

  • 使用 numpy 数组通常不会加速循环。 numpy 的优势在于矢量化。 pixels的形状是什么?是3D吗?高度和宽度以及三个颜色通道?你想要什么?图像中独特颜色的列表? 如何独一无二?您想考虑将(255, 255, 255)(255, 255, 253) 不同吗?你想如何存储你的颜色?作为元组?还是作为 3D 数组?
  • @ddejhon 存储的每种颜色都是唯一的,所以是的,(255、255、255)将不同于(255、255、253)。颜色模式为RGB,颜色将存储为元组,但存储在数组/列表中。该数组显然是二维的,每个维度有 4 个元素。
  • 等等,你想要每个像素的颜色的二维数组吗?您不仅想要图像中的独特颜色,还想要它们的位置? 4个元素是什么? R、G、B 和...?
  • 你能加一个Minimal Reproducible Example吗?
  • @ddejhon 抱歉,我的意思是 3 个元素。是的,一个包含 RGB 值的 3 个元素的二维数组。我遇到的问题是检查像素颜色(元组)是否在数组中,但是如果我按照上面显示的方式进行操作,则会出现错误。所以我的问题再次是,我如何检查一个元组是否在一个一维的 NumPy 数组中?

标签: python arrays numpy tuples python-imaging-library


【解决方案1】:

我不确定您到底需要什么。但我希望下一段代码对你有所帮助。

import numpy as np

image = np.arange(75).reshape(5, 5, 3) % 8

# Get the set of unique pixles
pixel_list = image.reshape(-1, 3)
unique_pixels = np.unique(pixel_list, axis = 0)

# Test whether a pixel is in the list of pixels:
i = 0
pixel_in_list = (unique_pixels[i] == pixel_list).all(1).any(0)
# all(1) - all the dimensions (rgb) of the pixels need to match
# any(0) - test if any of the pixels match

# Test whether any of the pixels in the set is in the list of pixels:
compare_all = unique_pixels.reshape(-1, 1, 3) == pixel_list.reshape(1, -1, 3)
pixels_in_list = compare_all.all(2).any()
# all(2) - all the dimensions (rgb) of the pixels need to match
# any()  - test if any of the pixelsin the set matches any of the pixels in the list

【讨论】:

    【解决方案2】:

    我找到了一种更快的方法来让我的循环在没有 NumPy 的情况下运行得更快,那就是使用 sets,这比使用列表或 NumPy 快得多。这就是代码现在的样子:

    from PIL import Image
    
    img = Image.open("bg.jpg").convert("RGB")
    pixels = img.load()
    
    colors = set({})
    
    for h in range(img.size[1]):
        for w in range(img.size[0]):
            if pixels[w,h] in colors:
                continue
            else:
                colors.add(pixels[w,h])
    

    这解决了我最初的列表太慢而无法循环的问题,并且解决了 NumPy 无法比较元组的第二个问题。谢谢大家的回复,祝你有个美好的一天。

    【讨论】:

      【解决方案3】:

      假设pixels 的形状为(3, w, h)(3, h, w)(即颜色通道沿第一个轴),并假设您所追求的只是图像中的独特颜色:

      channels = (channel.flatten() for channel in pixels)
      colors = set(zip(*channels))
      

      如果你想要一个list 而不是一个集合,colors = list(set(zip(*channels)))

      您似乎误解了 numpy 派上用场的地方。一个 numpy 元组数组不会比一个 Python 元组列表快。 numpy 的速度在矩阵和向量的数值计算中发挥了作用。一个 numpy 元组数组无法利用任何使 numpy 如此之快的因素。

      您尝试做的只是 不适合 numpy,并且根本无助于加速您的代码。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-12-17
        • 2023-02-03
        • 2018-04-07
        • 2019-02-22
        • 1970-01-01
        • 2012-07-02
        相关资源
        最近更新 更多