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

Posted

技术标签:

【中文标题】PySide:分离精灵表/将图像分离成连续的颜色区域【英文标题】:PySide: Separating a spritesheet / Separating an image into contiguous regions of color 【发布时间】:2013-01-04 02:48:35 【问题描述】:

我正在开发一个程序,在该程序中我需要分离 spritesheets,或者换句话说,将图像分成连续的颜色区域。

我以前从未做过任何图像处理,所以我想知道我将如何处理这个问题。测试像素颜色后我会做什么?确定每个精灵对应哪个像素的最佳方法是什么?

所有输入图像都有统一的背景,并且与背景不同的 alpha 通道算作颜色。输出图像的顺序需要从左到右,从上到下。我的项目是用 PySide 编写的,所以我也希望将它用于此任务,但如果需要,我可以导入更多库。

感谢您的回复!

附: 我不确定 PySide 标签是否合适,因为我使用的是 PySide,但问题不涉及它的 GUI 方面。如果某个模组觉得它不属于它,请随意删除它。


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

我想把它分成这些:

【问题讨论】:

我在 javascript 中找到了类似的解决方案:***.com/questions/14507440/… 【参考方案1】:

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

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

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 图像并打开它,您会看到以下内容(我在您的空窗口中添加了一个矩形):

使用上图,如果我们想加入其他内部的精灵(如添加的矩形,见上图),接下来我们需要填充它的洞。这是另一个简单的规则:如果从 [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)。

【讨论】:

是否有任何理由创建轮廓,然后填充孔?看来如果我加if im[x, y] != bg: mask[x, y] = 255,就不需要m = morphology.binary_fill_holes(m)了。 @user1588857 这是一种简化,也适用于您可能拥有的其他图像。但是假设在最右边的精灵中,您在未连接到窗口的空窗口中有一个球,您的建议将导致为这个球创建一个精灵,并为外部组件创建另一个精灵。 @user1588857 我在编辑后的答案中采纳了你的建议,检查它是否处理我们在这里讨论的内容。 效果很好,我还没有遇到任何问题。非常感谢! 你是如何在 Java 中做到这一点的?哦,等等,这与 this 问题无关,因此 不是 how to do it in Java? 的重复项

以上是关于PySide:分离精灵表/将图像分离成连续的颜色区域的主要内容,如果未能解决你的问题,请参考以下文章

python使用openCV加载图像并将BGR格式转换成HSV格式定义HSV格式中需要分离颜色的掩码(掩模)区间(mask)并使用mask信息进行颜色分离BGR格式的图像转化为RGB并可视化

opencv学习笔记第六篇:分离颜色通道多通道图像混合和图像对比度亮度值的调整

OpenCV实现图像颜色通道分离图像二值化图像滤波降噪C++

opencv图像混合,分离颜色通道多通道图像混合

学习 opencv--- 分离颜色通道 && 多通道混合

Separation Studio for Mac(颜色分离工具)