八叉树算法--图像量化法

SLAM学习交流可加群:248085206

1 总述

        关于八叉树图像量化法,网上有很多文章,在这里我只写我关心的。

2 什么是八叉树

        学过数据结构的人都知道二叉树,由二叉树的概念可以推知八叉树。八叉树就是非叶子结点最多有八个子结点的树,其他没有任何特殊的。

3 八叉树是如何代表颜色的?

这里有前提,那就是这里说的颜色是指由RGB组成的颜色,RGB都是颜色的分量。颜色的每个分量在计算机中都是由8比特来表示的,这8个比特从高位到低位都是由0和1来表示的,不过这里说的只不过是单独的分量而已。现在把RGB当做一个整体来看待,为了方便理解,现在假设有一个矩阵,列分别是由颜色分量中的各位来表示的,于是这个矩阵就有了3列,分别是RGB。接着是行,那就是由RGB中处于相同位序的01组成的了。于是每一行由01所代表的二进制数字可以转换成一个十进制数字,并且这种转换是一一对应的。即,这个十进制数字可以唯一地转换成对应行的二进制数字,而那一行的二进制数字也只能转换成这个十进制数字。于是这个十进制数字和那一行二进制数字就具备互相代表的能力。
既然如此,1个由RGB组成的颜色,从上到下就可以被分割成由8个十进制数字表示的8个层次了,每个层次对应1个十进制数字。
那么这就变成了一个固定长度的数字序列,那么这么一个每个数字范围相同的,固定长度的数字序列,就完全可以被看成是一条路径了,于是它就很符合树的适用条件啦,因为数字的范围是8,所以八叉树比较合适。
好,现在我们把思考的角度换成八叉树,那么这条路径就是八叉树中的一个枝叉了,其中每个数字就代表了当前结点的以该数字作为标识的子结点了,简而言之,该数字就是当前结点的某个子结点的索引。另外,由此可以推知,这颗八叉树的叶子结点是就不包含索引的了,并且这个八叉树应该是有9层的,因为是父结点包含了子结点的索引嘛。

4 八叉树高低层的意义

八叉树的这种结构层次的高低是有意义的,在颜色八叉树中每一条完整的路径都代表一个准确的颜色,因为根据那个索引值就能提取出准确的颜色来。所谓完整的路径就是指从树根结点到最后一层次的叶子结点都是有结点存在的,由此推想可知,肯定还会存在不完整的路径的。但是不管是完整的还是不完整的路径都会从根结点的子结点那里往下层分散,越是往下,路径中的结点就越多从而反映出的颜色就越准确。所以八叉树的高层次代表的是颜色的估计值,而低层次代表的是颜色准确值。所以取个极限的话就是树根结点的子节点是最不准确的值,而叶子结点则是最准确的值。
正是因为颜色都会从八叉树的高层向底层进行分散,所以高层次汇聚了很多的颜色值。这是因为在向八叉树插入颜色的时候,每个层次的结点都会累加当前正在插入的颜色的RGB值。
在这里插入图片描述

5 如何向八叉树插入颜色呢?

        程序首先会读入一张图片,这张图片你可以使用原图,也可以使用经过压缩的图片,但是我建议使用经过压缩的图片,为什么呢?因为计算量小,快啊。把这张图片转换成RGBA数据,并且获取它的像素数。
逐个像素地去遍历得到的RGBA数据,在这个过程中肯定有颜色相同的像素和颜色不同的像素。
那么插入的过程很简单啦,就按照子节点的索引去寻找子结点,找到以后就在该子结点上面累加正在插入的颜色RGB的值,又因为是一个新的像素点被读取了嘛,所以还要在该子结点上的像素数上面累加1,并且在沿途所有的子节点上都这样做,直到没有结点为止。
如果再插入的过程遇到子结点应该有但是还没有的情况,你就创建一个呗。
如果你遇到了叶子结点那就代表本次插入到此为止了,因为这是已经经过归并的结点了,那你就不能继续插入了,要不然颜色总数就超过了最大的颜色限制了。
这样做的好处是,越是高层数据量就越全,越完整,但是越是不准确,越是低层数据量就越少,越准确。
再有就是,在提取颜色的时候你只需要获取叶子结点的数据即可。
因为你只需要把叶子结点的RGB各分量和除以叶子结点的像素数即可得到结果了。
这也反映出了八叉树的叶子结点反映出了最后的结果颜色,从而,叶子结点的数量代表着最后得到的颜色数量。

6 如何限制想得到的最大颜色数量?

为啥要限制颜色数量呢?因为颜色越多所需要存储的空间就越大,再有就是颜色越少越方便挑选图片的代表颜色。一般来说256种颜色足够表达图像的内容了,也就是说你也就能看明白这个图像里面是个啥样子的了。
但是高清的图像包含的颜色数可是要远远高于256种颜色的,所以这就涉及到一旦一个颜色插入以后叶子结点的数量超过了最大的颜色数量,该怎么处理的问题了。
总的思想就是合并最相似的颜色。

7 什么是最接近的颜色?

要知道在计算机中没什么接近不接近,它只知道是或者不是。其实最接近的颜色,就是指具有相同父结点的叶子结点。

8 具体该怎么合并?

你总是要挑最底层的,具备最少像素数的非叶子结点,把它的子结点中的RGB分量和像素数都累加到该非叶子结点上,然后把它的子结点全部删除,这样该非叶子结点就变成了一个新的叶子结点。
这就是合并的具体过程了。
如果合并以后的叶子结点数量还是超过了最大的颜色数量,那么继续按照这个方法合并叶子结点。

9 为啥非要是最底层的具备最少像素数的非叶子结点进行合并呢?

其实这个最底层是个相对的概念,我的意思只不过是指从下面的层次往上面的层次去寻找。因为层次越低颜色就越精细,人眼对它们的区分能力就越弱,失真度就越低。
像素数最少,这个就很好解释了嘛,它在图像中所占的比例是最微不足道的,有它没它无所谓的那种,人眼对它的辨识度也是很弱的,从而图像就越保真。
你要合并的是叶子结点,所以要在非叶子结点上做这件事了,所以就是非叶子结点喽。

10 那么用什么数据结构来表示八叉树呢?

这个就涉及到具体的编程语言了,现在我以Objective-C为例简单说明一下。
八叉树的结点,其实就是个数据模型。它应该具备一个字典,因为它是要根据索引去寻找子节点的嘛,所以当前结点需要持有子结点的指针,和子结点的索引值。一个用来标识该结点处于该八叉树哪个层次的标识。用来累加像素数,和各颜色通道的整形属性。还有一个就是标识该结点是否是叶子结点的标志位。这样一来各个父子结点之间就能建立起层次关系了。
你需要建立8个有序可变集合,分别用来容纳每个层次的非叶子结点,另外,它还能方便排序找到具备最少像素数的那个非叶子结点。
你需要一个可变集合,用来容纳生成的叶子结点。
集合的便利之处在于它会自动去重,能给出当前的集合元素数量,有序集合还能给集合中的元素进行排序。
在插入颜色的过程中,在创建结点的时候就把该结点插入到相应层次的集合中,每个颜色被插入完成的时候再把叶子结点插入到叶子结点的集合中。
合并的时候要把删除的叶子结点从叶子结点集合中删除,同时要把新的叶子结点从原来的非叶子结点的层次集合中移除,并加入到叶子结点集合中。

11 如何把量化后的颜色转换成图像?

在程序一开始从图像得到的数据只是被读取了,并没有被改变,它是有用的。
此时你再遍历该数据,与开始时候插入颜色不同,此时是根据某个像素,在已经完成的八叉树上面沿着路径去寻找对应的叶子结点的过程,这个过程不涉及创建结点的步骤。
在遍历的过程中既会遇到完整的路径,也会遇到不完整的路径,都是没关系的,只要获取到当前路径的叶子结点的RGB数据值再除以当前叶子结点的像素数量,就能得到想要的RGB分量了。
然后再用这个RGB分量去修改对应的原来的图像数据。
遍历完成以后就能得到经过量化的图像了的数据了。
接下来再用这个数据去生成图像即可,在iOS中是有这个API的。

12 效果

在这里插入图片描述原图

在这里插入图片描述结果图

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
八叉树颜色量化算法是一种用于处理图像颜色的算法。该算法通过将原始图像中的颜色值分解为RGB三个分量,将每个分量的值映射到一个[0,255]的范围内。然后,将图像中的像素点分布到一个八叉树数据结构中。 八叉树是一种树状数据结构,每个节点最多可以有八个子节点。在进行颜色量化时,我们通过将颜色空间划分为八个子空间来构建这个八叉树。对于每个节点,我们计算子空间中所有像素点的平均颜色值,并将其用作该节点的颜色。 在构建完成八叉树后,我们可以根据需要对图像进行压缩或减小颜色深度。压缩时,将八叉树中的叶子节点合并为一个新的节点,以减小颜色数量。减小颜色深度时,我们可以对八叉树进行剪切,使得树的深度减少,进而减小颜色级别。 对于每个图像像素点,我们可以使用八叉树来查找最接近的颜色节点,并将其替换为该节点的颜色值。这样一来,就实现了图像的颜色量化八叉树颜色量化算法具有如下优点:对于图像较为均匀的地方,可以保留更多的细节,因为这些细节可以对应到八叉树中较为细小的子空间中;同时,对于图像中颜色分布不均匀的地方,可以将颜色量化得更加精确,避免颜色丢失。 总体而言,八叉树颜色量化算法是一种高效且灵活的处理图像颜色的算法,可以在保持图像质量的同时减小颜色深度和文件大小。该算法在很多图像处理应用中被广泛使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值