PySide:分离spritesheet /将图像分离成连续的颜色区域

时间:2013-01-21 03:15:35

标签: python image-processing pyside sprite-sheet

我正在制作一个程序,其中我需要分隔spritesheets ,换句话说,将图像分隔成连续的颜色区域。

我之前从未做过任何图像处理,所以我想知道如何处理这个问题。测试像素颜色后我该怎么办?确定哪个像素与每个精灵一起使用的最佳方法是什么?

所有输入图像均匀背景,不同于背景的alpha通道计为颜色。输出图像的顺序需要左右,上下。我的项目是用PySide编写的,所以我也希望将它用于此任务,但如果需要,我可以导入更多的库。

谢谢你的回复!

P.S .: 我不确定PySide标签是否合适,因为我使用PySide,但问题不涉及它的GUI方面。如果mod认为它不属于,请随意将其删除。


例如,我有一个spritesheet,如下所示:

Input image

我想把它分成这些:

Output 1 Output 2 Output 3 Output 4 Output 5 Output 6 Output 7 Output 8

1 个答案:

答案 0 :(得分:4)

这听起来应该在处理精灵的任何东西中实现,但在这里我们将实现我们自己的精灵分裂器。

这里我们需要的第一件事是提取单个对象。在这种情况下,只需确定像素是否是背景像素。如果我们假设原点是背景像素,那么我们就完成了:

from PIL import Image

def sprite_mask(img, bg_point=(0, 0)):
    width, height = img.size
    im = img.load()

    bg = im[bg_point]
    mask_img = Image.new('L', img.size)
    mask = mask_img.load()
    for x in xrange(width):
        for y in xrange(height):
            if im[x, y] != bg:
                mask[x, y] = 255
    return mask_img, bg

如果保存上面创建的mask图像并将其打开,您可以在此处看到(我在空窗口中添加了一个矩形):

enter image description here

使用上面的图片,我们需要的下一件事是填充它的洞,如果我们想要加入其他内部的精灵(如添加的矩形,请参见上图)。这是另一个简单的规则:如果从[0,0]处的点无法到达一个点,那么它就是一个洞,必须填充它。剩下的就是分离各个图像中的每个精灵。这是通过连接组件标签完成的。对于每个组件,我们得到其轴对齐的边界框以定义该块的尺寸,然后我们从原始图像复制属于给定组件的点。为了简短起见,以下代码使用scipy来完成这些任务:

import sys
import numpy
from scipy.ndimage import label, morphology

def split_sprite(img, mask, bg, join_interior=True, basename='sprite_%d.png'):
    im = img.load()

    m = numpy.array(mask, dtype=numpy.uint8)
    if join_interior:
        m = morphology.binary_fill_holes(m)
    lbl, ncc = label(m, numpy.ones((3, 3)))

    for i in xrange(1, ncc + 1):
        px, py = numpy.nonzero(lbl == i)
        xmin, xmax, ymin, ymax = px.min(), px.max(), py.min(), py.max()

        sprite = Image.new(img.mode, (ymax - ymin + 1, xmax - xmin + 1), bg)
        sp = sprite.load()
        for x, y in zip(px, py):
            x, y = int(x), int(y)
            sp[y - int(ymin), x - int(xmin)] = im[y, x]

        name = basename % i
        sprite.save(name)
        print "Wrote %s" % name

sprite = Image.open(sys.argv[1])
mask, bg = sprite_mask(sprite)
split_sprite(sprite, mask, bg)

现在,你完全按照问题所包含的所有部分(sprite_1.png,sprite_2.png,...,sprite_8.png)。