将图像分割成较小图像的算法减少了空白量并指定了最大量的矩形

时间:2011-05-13 11:39:01

标签: algorithm image rectangles

我正在寻找一种算法,可以将图像分割成较小的图像,但有一些约束。 一个约束是使用最少量的“空白”意味着空像素。另一种是指定最大数量的图像将其拆分成。

例如,让我们看一下下图。其中有很多“空白”。我想将这些图像分成几个其他图像,这样我可以减少这个图像占用的内存量,同时减少这个图像所需的“绘图”量。

.=transparent pixel
x=colored pixel

....................
.xxxxxxxxxxx........
...xxxx...xxxxxx....
.............xxxxx..
...............xxx..
...............xxx..
....................
..xxxxxx............
.....xxxxxxxxxxx....
.........xxxxxxxxxx.
....................

假设我想将图像分割成最多4张图像,可能的溶剂如下图所示。

....................
.111111111111111....
.111111111111111....
.............22222..
.............22222.
.............22222..
....................
..3333333...........
..33333334444444444.
.........4444444444.
....................

有没有人有这个算法,或者知道算法的名称呢? 我一直在寻找一段时间并找到了一些相关的算法,但是我发现的算法没有考虑到空白,例如他们将图像分割成仅覆盖非透明像素的矩形,从而产生大量的矩形。 我正在使用的真实数据是1024 * 1024像素的图像,我宁愿将它们减少到最多16个部分。诀窍是使用最少量的空格提取16个图像。

5 个答案:

答案 0 :(得分:2)

我使用与ravloony相同的算法,但稍作修改,使用“裁剪”操作查找最小/最大的列和不完全为空的行并丢弃其余的。

实际上,裁剪操作会获得一个X*Y区域作为输入,并输出4个整数 - 包含该区域所有已用像素的最小矩形的坐标。这也可用于检测和丢弃空白区域。

实施例

....................
.xxxxxxxxxxx........     xxxxxxxxxxx.......
...xxxx...xxxxxx....     ..xxxx...xxxxxx...
.............xxxxx..     ............xxxxx.
...............xxx.. =>  ..............xxx. (first crop)
...............xxx..     ..............xxx.
....................     ..................
..xxxxxx............     .xxxxxx...........
.....xxxxxxxxxxx....     ....xxxxxxxxxxx...
.........xxxxxxxxxx.     ........xxxxxxxxxx
....................

现在将图像分成NxN个部分(这里使用N = 4)并对每个部分使用裁剪操作:

xxxxx|xxxxx|x....|
..xxx|x...x|xxxxx|
---------------------
     |     |  xxx|xx
     |     |  ..x|xx
---------------------
     |     |    x|xx
     |     |     |
---------------------
 xxxx|xx...|     |
 ...x|xxxxx|xxxxx|
     |...xx|xxxxx|xxx

对于这个例子,我们得到10 + 10 + 10 + 6 + 4 + 1 + 2 + 8 + 15 + 10 + 3 = 79像素而不是21 * 11 = 231,这只是34,2%。请注意,这与您手工制作的4部分细分(30 + 15 + 14 + 20 = 79)的数量相同!

结论

当然会有一些额外的数据来跟踪每个部分的16个部分的位置和大小,并且它不会总是给出最好的结果,但我认为这是速度和节省之间的一个很好的折衷,算法是易于编写和维护。

关于附加数据:大小为1024x1024并分成4x4部分的图像可以使用4字节值来存储每个矩形,因此额外的数据大小只有16 * 4 = 64字节 - 对此,你也许应该考虑增加你的16个部分,除非它会大幅减慢其他部分,如图纸。

最坏情况

此算法的最坏情况是在边缘处或附近设置一些像素的部分,如下所示:

x......x    xxxxxxxx    xx......
........    ........    x.......
........    ........    ........
x......x    ...x....    .......x

我想到了几种解决方案:

  • 再次分裂该区域(结束 使用四叉树实现)
  • 使用一些额外步骤进行检测 完全空的矩形 内部。
  • 翻译定义部分的网格

答案 1 :(得分:0)

您想要编写运行长度或增量压缩算法。或者您想使用空间归档曲线或空间索引。 sfc递归地将表面细分为较小的4个图块,并将2维的复杂度降低到1维,因此可以更容易地识别白色空间。你想寻找尼克的希尔伯特曲线四叉树空间索引博客。你想在phpclasses.org下载我的php类hilbert曲线。

答案 2 :(得分:0)

我会看看递归地做,每次分成两半或四,直到你达到你想要的水平(为你2 - > 4 ^ 2 = 16)。在底层检查空方块并丢弃它们。 当然,这会给你一个与原始图像的形状成比例的矩形网格,而不是最佳放置的矩形,但它可能会让你在正确的轨道上开始。

答案 3 :(得分:0)

我的直觉说理想的解决方案类似于背包问题,因此在计算上是不切实际的。您可以使用某种启发式方法来生成“足够好”的解决方案。

您可以使用泛光填充算法来选择非透明像素的连接区域。作为第一个切割,这将为每个不相交的颜色区域提供一个矩形。如果您的预算中有更多矩形可用,您可以尝试以不同方式剪切它们,以查看哪种矩形为您提供最高的“密度”彩色像素。

答案 4 :(得分:0)

对于迟到的评论感到抱歉,但我花了一些时间才找到一个“好”的算法。

经过一番研究后,我将采用以下解决方案。 首先,我使用Quadtree并执行SplitAndMerge。我先拆分“空白”。然后我将所有矩形合并到最大区域的矩形中。

之后我根据区域大小对四叉树进行排序,只保留最大的x区域。 (因此必须保留最大的空白区域)。但是我不想要空白,我想要除了空白之外的所有东西,所以我颠倒了四叉树,再做一次SplitAndMerge。然后从图像中提取剩余的矩形,并将它们装入最终图像中。

这给了我一些很好的结果,大大减少了图像尺寸(因为我的图像中有很多空白),并且还有时间将它们绘制到最小。