尝试压缩图像时出现彩色像素(包含图片)

Jus*_*yer 5 java jama image-compression

我正在尝试使用奇异值分解来压缩给定的图像.我以为我有它,直到我注意到我在整个过程中不断出现垃圾色像素.

垃圾像素

右上角显示的数字表示迭代次数,其中0是原始图像.

这是一个常见错误吗?有什么我想念的吗?

我认为它可能与我的数学本身有关.我正在使用JAMA,一个java矩阵包,它为我处理这个.下面是我每次迭代的实现:

for (int i = 0; i < k; i++) {    
    Matrix step = (uColumns[i].times(sValues[i])).times(vColumns[i].transpose());
    encoded = encoded.plus(step);
}
Run Code Online (Sandbox Code Playgroud)

基本上我正在做(或尝试做)是:

M = M + (s1*u1*v1^t)
Run Code Online (Sandbox Code Playgroud)

我的实现是否有明显错误,或者错误可能是由于JAMA执行SVD的方式?根据我的测试,矩阵U和V中的值的符号在某些行中与Wolframalpha或Matlab生成的符号不同.

任何帮助表示赞赏.

谢谢,

瑞斯蒂昂

Gob*_*ist 4

这是分解为原色的图片:

Lena SVD 分解为 RGB

显然,您以错误的方式将颜色转换为数字,并将数字转换为颜色。您将int RGB 像素视为单个数值并将其传递给 SVD 数值过程,但它实际上是 RGB 的信息会丢失。

大多数有损图像压缩方法是通过丢弃低有效位来实现压缩的。但是,当单个int中有 RGB 时,每个 R、G 和 B 的低有效位都会与高有效位交织。当将像素作为单个数值传递时,该信息会丢失,并且 SVD 过程有效地将低有效位 R 位解释为比高有效位 G 位更有效,并且可能会尝试完全丢弃所有 G 和 B 位,因为它们存储在 R 位“之后”。

例如,浅灰色像素 (192,192,192) 的 RGB 值为 0xC0C0C0。例如,以 1% 的误差压缩该值会产生 0xC2AE32。从压缩算法的角度来看,这个值只比原始值大了1%,几乎察觉不到。但将其转换回 RGB 会得到 (194,174,50)。R 组件确实几乎相同,但 G 和 B 已损坏。这就是程序中“垃圾颜色”的来源。分解图像显示,R 分量被正确压缩,G 分量在高压缩级别下变成随机噪声,而 B 分量始终是随机的。

实现中的另一个问题是单个明亮像素分散在黑暗区域中。这些显然是由数字上溢和下溢引起的。例如黑色像素(0,0,0)编码为0x000000 = 0;有损压缩会引入一个小误差,可以是正数,也可以是负数,并且可以产生 -1 = 0xFFFFFFFF;在 RGB 中,它变成 (255,255,255),即白色。

该怎么办?

如果你只是测试SVD图像压缩并且使用灰度图像就足够了,那么你应该简单地从RGB值中取出低字节,该值的范围是0到255。相应地,在显示结果或写入输出文件时,将此值解释为灰度,或乘以 0x010101 以获得完整的 RGB 值。

如果需要压缩彩色图像,则应分别对 R、G 和 B 分量运行 SVD 算法。这是处理颜色的最简单方法,但不是最有效的方法。为了获得更高的压缩率和更不明显的伪像,最好从 RGB 转换为 Lab(亮度和两个色度通道);色度可以进一步压缩,这就是 JPEG 的工作方式。

解压缩图像时,在从 SVD 计算值之后但在屏幕上显示这些值或写入文件之前,将所有结果值(R、G 和 B)限制在 0-255 范围内。这将消除分散的白点。