c语言 - 'Modified Median Cut'的Leptonica实现根本不使用中位数吗?



我在图像处理方面玩了一会儿,决定阅读一下颜色量化是如何工作的,经过一番阅读,我发现了改进的中值切割量化算法。

我一直在阅读Leptonica库中的C实现代码,发现了一些我认为有点奇怪的东西。

现在我想强调的是,我远不是这方面的专家,也不是数学专家,所以我预测这一切都归结为我没有理解所有这些,也不是算法的实现是错误的。

该算法指出,vbox应沿lagest轴拆分,并应使用以下逻辑进行拆分

最大的轴是通过定位具有中间像素的bin来划分的(按人口),选择较长的一边,并在中间进行划分那一边。我们可以简单地将bin与中值像素放在一起在较短的一侧,但在细分的早期阶段倾向于将低密度集群(在细分)作为高密度集群的一部分将在中值vbox颜色中投票超过它,即使未来基于中值细分。这里使用的算法在早期的细分,3有助于提供可见但较低的群体颜色集群自己的vbox。这对高密度集群的细分,最终他们的vbox中的人口大致相等。

为了便于讨论,让我们假设我们有一个vbox,我们正在进行拆分,并且红色轴是最大的。在Leptonica算法中,在01297行,代码似乎执行以下

  • 遍历红色的所有可能的绿色和蓝色变体
  • 对于每次迭代,它都会添加到沿红色轴找到的总像素数(总体)中
  • 对于每种红色,它将当前红色和以前红色的总体相加,从而存储每种红色的累积值

注意:当我说"红色"时,我指的是迭代覆盖的轴上的每个点,实际颜色可能不是红色,而是包含一定量的红色

因此,为了便于说明,假设我们沿着红轴有9个"仓",它们有以下种群

4 8 20 16 1 9 12 8 8

在所有红色仓的迭代之后,偏和数组将包含上述仓的以下计数

4 12 32 48 49 58 70 78 86

总计的值为86

完成后,是时候执行实际中值切割了,对于红色轴,这是在01346 线上执行的

它对bin进行迭代,并检查它们是否累积了sum。这是我从算法描述中想到的部分。它查找具有大于总值<2的值的第一个bin

total/2不是意味着它正在寻找一个值大于平均值而不是中值的bin吗?上述仓的中位数为49

4349的使用可能会对盒子的分割方式产生巨大影响,即使算法会移动到匹配值所在的较大边的中心。。

另一件让我有点困惑的事情是,论文规定了应该定位具有中值的垃圾箱,但没有提到如果有偶数个垃圾箱,该如何处理。。中位数将是(a+b)/2的结果,并且不能保证任何一个箱都包含该种群计数。这就是为什么我认为,有一些近似值可以忽略不计,因为分割实际上是如何在所选垃圾箱的大边的中心进行的。

如果它有点冗长,我很抱歉,但我想尽可能彻底,因为这几天已经让我抓狂了;)

在9-bin示例中,49是前5个bin中的像素数。49是9个部分和的集合中的中值,但我们希望86个像素集合的中值像素为43(或44),并且它位于第4个bin中。

对leptonica的colorquant2.c中修改的中值切割算法的检查表明,三维框的实际切割位置不一定出现在包含中值像素的bin附近。函数medianCutApply()中解释了其原因。这是对Paul Heckbert原始方法的"修改"之一。另一个重要的修改是根据总体和产品(总体*体积)的组合来决定下一个剪切哪个3d框,从而允许分割颜色空间的大但稀疏的区域。

我不知道算法,但我假设您的数组包含每个红色的种群;让我们用一个例子来解释这一点:

假设你有四个红色等级:A、B、C和D您有以下红色值序列:

AABDCADBBBAAA

要找到中位数,你必须根据红色值对它们进行排序,并取中间值:

    median
      v
AAAAAABBBBCDD

现在让我们使用他们的方法:

A:6 => 6 
B:4 => 10
C:1 => 11
D:2 => 13
13/2 = 6.5 => B

我认为错配的发生是因为你在计算人口;平均颜色为:

(6*A+4*B+1*C+2*D)/13

最新更新