用于图像压缩的 C# 预测编码

发布于 2024-10-31 19:40:02 字数 1982 浏览 1 评论 0原文

我一直在对图像使用霍夫曼压缩来减小尺寸,同时保持无损图像,但我也了解到您可以使用预测编码通过减少熵来进一步压缩图像数据。

据我了解,在无损 JPEG 标准中,每个像素都被预测为光栅顺序中已经遇到的相邻 4 个像素的加权平均值(上面三个,左边一个)。例如,尝试根据左侧和上方的先前像素 x 来预测像素 a 的值:

x x x
x a 

然后计算残差并对其进行编码(预测值与实际值之间的差异)。

但我不明白的是,如果平均 4 个相邻像素不是 4 的倍数,你会得到一个分数,对吧?该分数应该被忽略吗?如果是这样,8 位图像的正确编码(保存在 byte[] 中)是否会类似于:

public static void Encode(byte[] buffer, int width, int height)
{
    var tempBuff = new byte[buffer.Length];

    for (int i = 0; i < buffer.Length; i++)
    {
        tempBuff[i] = buffer[i];
    }

    for (int i = 1; i < height; i++)
    {
        for (int j = 1; j < width - 1; j++)
        {
            int offsetUp = ((i - 1) * width) + (j - 1);
            int offset = (i * width) + (j - 1);

            int a = tempBuff[offsetUp];
            int b = tempBuff[offsetUp + 1];
            int c = tempBuff[offsetUp + 2];
            int d = tempBuff[offset];
            int pixel = tempBuff[offset + 1];

            var ave = (a + b + c + d) / 4;
            var val = (byte)(ave - pixel);
            buffer[offset + 1] = val;
        }
    }
}

public static void Decode(byte[] buffer, int width, int height)
{
    for (int i = 1; i < height; i++)
    {
        for (int j = 1; j < width - 1; j++)
        {
            int offsetUp = ((i - 1) * width) + (j - 1);
            int offset = (i * width) + (j - 1);

            int a = buffer[offsetUp];
            int b = buffer[offsetUp + 1];
            int c = buffer[offsetUp + 2];
            int d = buffer[offset];
            int pixel = buffer[offset + 1];

            var ave = (a + b + c + d) / 4;
            var val = (byte)(ave - pixel);
            buffer[offset + 1] = val;
        }
    }
}

我不明白这实际上会如何减少熵?这将如何帮助进一步压缩我的图像,同时仍然保持无损?

感谢您的任何启发

编辑:

所以在玩了预测编码图像之后,我注意到直方图数据显示了许多不同像素的+-1。在某些情况下,这会大大降低熵。这是屏幕截图:

在此处输入图像描述

I've been playing with Huffman Compression on images to reduce size while maintaining a lossless image, but I've also read that you can use predictive coding to further compress image data by reducing entropy.

From what I understand, in the lossless JPEG standard, each pixel is predicted as the weighted average of the adjacent 4 pixels already encountered in raster order (three above and one to the left). e.g., trying to predict the value of a pixel a based on preceding pixels, x, to the left as well as above a :

x x x
x a 

Then calculate and encode the residual (difference between predicted and actual value).

But what I don't get is if the average 4 neighbor pixels aren't a multiple of 4, you'd get a fraction right? Should that fraction be ignored? If so, would the proper encoding of an 8 bit image (saved in a byte[]) be something like:

public static void Encode(byte[] buffer, int width, int height)
{
    var tempBuff = new byte[buffer.Length];

    for (int i = 0; i < buffer.Length; i++)
    {
        tempBuff[i] = buffer[i];
    }

    for (int i = 1; i < height; i++)
    {
        for (int j = 1; j < width - 1; j++)
        {
            int offsetUp = ((i - 1) * width) + (j - 1);
            int offset = (i * width) + (j - 1);

            int a = tempBuff[offsetUp];
            int b = tempBuff[offsetUp + 1];
            int c = tempBuff[offsetUp + 2];
            int d = tempBuff[offset];
            int pixel = tempBuff[offset + 1];

            var ave = (a + b + c + d) / 4;
            var val = (byte)(ave - pixel);
            buffer[offset + 1] = val;
        }
    }
}

public static void Decode(byte[] buffer, int width, int height)
{
    for (int i = 1; i < height; i++)
    {
        for (int j = 1; j < width - 1; j++)
        {
            int offsetUp = ((i - 1) * width) + (j - 1);
            int offset = (i * width) + (j - 1);

            int a = buffer[offsetUp];
            int b = buffer[offsetUp + 1];
            int c = buffer[offsetUp + 2];
            int d = buffer[offset];
            int pixel = buffer[offset + 1];

            var ave = (a + b + c + d) / 4;
            var val = (byte)(ave - pixel);
            buffer[offset + 1] = val;
        }
    }
}

I don't see how this really will reduce entropy? How will this help compress my images further while still being lossless?

Thanks for any enlightenment

EDIT:

So after playing with the predictive coding images, I noticed that the histogram data shows a lot of +-1's of the varous pixels. This reduces entropy quite a bit in some cases. Here is a screenshot:

enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

终难遇 2024-11-07 19:40:02

是的,只是截断。没关系,因为你存储了差异。它减少了熵,因为您只存储很小的值,其中很多都是 -1、0 或 1。顺便说一句,您的代码片段中有一些差一的错误。

Yes, just truncate. Doesn't matter because you store the difference. It reduces entropy because you only store small values, a lot of them will be -1, 0 or 1. There are a couple of off-by-one bugs in your snippet btw.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文