我正在寻找一种算法,可以将图像分割成较小的图像,但有一些约束。 一个约束是使用最少量的“空白”意味着空像素。另一种是指定最大数量的图像将其拆分成。
例如,让我们看一下下图。其中有很多“空白”。我想将这些图像分成几个其他图像,这样我可以减少这个图像占用的内存量,同时减少这个图像所需的“绘图”量。
.=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个图像。
答案 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。然后从图像中提取剩余的矩形,并将它们装入最终图像中。
这给了我一些很好的结果,大大减少了图像尺寸(因为我的图像中有很多空白),并且还有时间将它们绘制到最小。