获取图像的所有像素 [Wand]

Get all pixels of an Image [Wand]

我正在使用 Wand Python Library, and trying to solve the Python Challenge,我当前的问题要求我获取所有 even/odd 像素。

显然,这是一项非常简单的任务。但是,我发现 Wand 库在加载 pixels/copying 像素时非常慢(也许是因为我也将 fill_color 更改为每个像素的颜色?),我想知道我是否可以加载它们一次全部。

我目前加载所有像素的解决方案是这样的:

from wand.image import Image
img = Image(filename="5808.jpg")
pixels = []
for x in range(img.width+1):
    for y in range(img.height+1):
        pixels.append(img[x, y])

print(pixels)

我更喜欢这样的东西:

from wand.image import Image
img = Image(filename="5808.jpg")
print(img.pixels)

有类似的东西吗?提前致谢。

没有尝试阅读 Python 挑战,只是专注于问题..

I'd prefer something like this: img.pixels

迭代图像大小以收集 wand.color.Color 对象会很慢,因为这会调用重复使用 MagickWand 的内部像素迭代和像素结构。正如所说的挑战是 Python,而不是 C 缓冲区,我建议获取一次像素数据缓冲区。之后,您可以自由地迭代、比较、评估等,而无需 ImageMagick 资源。

对于这个例子,我假设图像是下面的 2x2 PNG (缩放可见性。)

from wand.image import Image

# Prototype local variables
pixels = []
width, height = 0, 0
blob = None

# Load image
with Image(filename='2x2.png') as image:
    # Enforce pixels quantum between 0 & 255
    image.depth = 8
    # Save width & height for later use
    width, height = image.width, image.height
    # Copy raw image data into blob string
    blob = image.make_blob(format='RGB')

# Iterate over blob and collect pixels
for cursor in range(0, width * height * 3, 3):
    # Save tuple of color values
    pixels.append((blob[cursor],      # Red
                   blob[cursor + 1],  # Green
                   blob[cursor + 2])) # Blue
print(pixels)
#=> [(255, 0, 0), (0, 0, 255), (0, 128, 0), (255, 255, 255)]

这个例子非常快,但请记住 Python 对象处理得很好。让我们扩展 Image 对象,并创建满足 img.pixels.

的方法
# Lets create a generic pixel class for easy color management
class MyPixel(object):
    red = 0
    green = 0
    blue = 0
    def __init__(self, red=0, green=0, blue=0):
        self.red = red
        self.green = green
        self.blue = blue
    def __repr__(self):
        return u'#{0.red:02X}{0.green:02X}{0.blue:02X}'.format(self)

# Extend wand.image.Image and add a new `img.pixels` pseudo-attribute
class MyImage(Image):
    # Repeat above example
    @property
    def pixels(self):
        pixels = []
        self.depth = 8
        blob = self.make_blob(format='RGB')
        for cursor in range(0, self.width * self.height * 3, 3):
            pixel = MyPixel(red=blob[cursor],
                            green=blob[cursor + 1],
                            blue=blob[cursor + 2])
            pixels.append(pixel)
        return pixels

# Call your custom class; which, collects your custom pixels
with MyImage(filename=filename) as img:
    print(img.pixels)
#=> [#FF0000, #0000FF, #008000, #FFFFFF]