可微抖动

2020-09-16 22:51:23

发布于2020年9月9日的问题让我们假设我们想要减少图像中的颜色数量。例如,考虑下面的水果图像:如果我们计算上面的图像中有多少种颜色,我们会得到惊人的157376(对于900x450像素的图像)。所有这些颜色真的有必要吗?上图有16种颜色,下图只有8种颜色。调色板减少的问题已经过广泛研究,典型的方法大致如下:

通过将颜色空间最多划分为N个不同的区域来构建大小为N的缩减调色板,其中每个区域由一种颜色表示。这通常是通过几种流行的方法之一来实现的。

使图像抖动。抖动的过程消除了色带,并通过点画般的效果创造了更多颜色的错觉。如果您不熟悉抖动,我们稍后将对其进行更详细的探讨。在给定固定调色板的情况下,有专门的抖动算法,如弗洛伊德·斯蒂恩伯格(Floyd Stienberg)。

与通常的方法不同,我们将使用梯度下降法同时解决这两个问题。

首先,让我们定义一个由N种颜色组成的调色板。对于本文来说,颜色将是RGB空间中的3个分量矢量。对图形书呆子的一个快速警告,为了便于移植和简单,我们没有考虑Gamma校正。

现在,我们如何以可区分的方式将一组离散的颜色分配给像素呢?我决定用概率分布来做这件事。每个像素由一个矢量表示,该矢量包含为该像素选择每个调色板颜色的概率。当实际生成图像时,我们只是从它的分布中采样每个像素的颜色。

上面的表述相当笼统。重要的是,调色板中的颜色和图像像素到调色板颜色的映射都是我们可以同时优化的变量。现在我们需要做的就是附加多个损失函数中的任何一个。

我最初选择使用的损失函数只是原始图像和输出图像期望值之间的平方差:

那么这里的想法是什么呢?基本上,预期的输出允许我们的图像假装它有比实际更多的颜色。

例如,让我们假设我们的调色板只有两种颜色,黑色和白色。另外,假设我们的目标图像是一个50%的灰色正方形。请考虑图像的以下三种可能表示形式。一个是全黑的图像,一个是全白的,第三个是50%的黑色和50%的白色像素随机分布在图像上。如果我们从很远的地方看,第三张图像会看起来更好。这是因为黑白像素将一起模糊并显示为灰色。这种效果称为抖动。

通过上面的推理,我们想要确保抖动像素分配(每个像素有50%的机会是黑或白)应该比损失函数的其他两个候选者看起来更令人满意。取目标图像和每个像素的预期颜色之间的平方误差就可以做到这一点。

你可能会问,为什么不取整个平方误差的期望值呢?这将如下所示:

这实际上是行不通的。要了解其中的原因,让我们看看上面相同的设置,并考虑单个像素的期望值(对于数学顽固的人,我们可以这样做,因为期望值是线性的)。由总是选择黑色的随机变量\(X\)表示的像素的损失函数为:

并且由50%黑50%白的随机X表示的像素的损失函数为:

不幸的是,在这两种情况下,这里的值是相同的,这排除了这个损失函数。

嘿!。还不错!正如我们所看到的,不同的阴影被不同密度的深色像素捕捉到。举一个更明显的例子,让我们试试这个垂直黑白渐变的图片:

现在让我们试试16种颜色:上图突出了我们目前损失功能的一个弱点。它是非常嘈杂的,即使它不是必须的。

举一个极端的例子,考虑一幅有三种颜色红色、蓝色和紫色(50%红色和50%蓝色的混合)的图像。让我们假设我们的调色板中有3种颜色的空间。在公式1中,以下两个解将具有相同的损失:

红色像素是红色,蓝色像素是蓝色,紫色像素是紫色。我们尽最大努力使用调色板中的所有三种颜色,图像复制得非常完美。

每个红色像素为红色,每个蓝色像素为蓝色,每个紫色像素有\(\frac{1}{2}\)机会为红色,\(\frac{1}{2}\)为蓝色。请注意,这里我们只使用了三种可能颜色中的两种,最终的图像质量明显较低。

为了控制这一弱点,我在损失函数中添加了一个附加项,用于惩罚像素方差的总和。现在我只是手动调整差异惩罚的系数。一个很好的经验法则似乎是,调色板越大,变化的权重就越大。应用此惩罚(方差系数=0.25),我们可以看到此帖子顶部的16色图像:

权衡之处在于,太小的方差会消除噪声,由于没有抖动,最终图像看起来包含的颜色较少,并且还会产生条带效果。下图有16种颜色,方差系数=1.0。它说明了这两个问题:

请注意,这里有许多有效的损失函数选择,我并不是说我的损失函数是完美的。例如,这篇关于创建最佳抖动模式的文章模糊了这两幅图像,并区分了它们之间的差异。我们可以尝试使用这个想法,或者寻找其他东西来代替简单的平方误差。尝试使用真实的图像质量度量(如SSIM)来测量图像质量,而不是使用方差作为代理,也会很有趣。

另一个需要改进的地方是我们的方法很慢(最多几分钟)。它也不能很好地将内存扩展到大调色板上(当我尝试使用200多种颜色来显示900x450像素的水果图像时,我的CoLab笔记本内存就用完了)。这是因为在这种情况下,需要优化的变量超过200x950x450。我们可以通过两种方式潜在地解决这些问题。为了解决速度问题,我们可以尝试将图像分成小批次。为了解决内存使用问题,我们可以尝试使用神经网络来输出每个像素位置的概率,而不是显式地存储它们。

为什么我认为这种方法很有趣?虽然这种方法在速度或质量上都不是最先进的,但我认为有趣的是,我们可以同时优化调色板选择和抖动。

据我所知,抖动和调色板选择并不是当今有损压缩技术的一部分。然而,如果可以将这些相同的概念应用于JPEG压缩的颜色空间变换、离散余弦变换和加权量化步骤,那将是非常巧妙的。

管道梦将是一个完全可微分的图像压缩流水线,其中所有步骤可以微调在一起,以相对于任何可微分损失函数优化特定的图像。