如何解决为什么 JPEG 压缩未压缩图像与其原始图像不同FFmpeg、NvJPEG 等
我目前正在努力理解为什么重新压缩未压缩的 JPEG 图像与原始图像不同。
很明显,JPEG 是一种有损压缩,但如果要压缩的图像已经未压缩,这意味着所有采样损失都已包含在内怎么办?换句话说:此时下采样和 DCT 应该是可逆的,不会丢失数据。
为确保色彩空间转换不会影响损失,跳过此步骤并使用 YUV 图像。
- 将 YUV 图像压缩为 JPEG (image.yuv --> image.yuv.jpg)
- 将JPEG图像解压为YUV图像(image.yuv.jpg --> image.yuv.jpg.yuv)
- 将 YUV 图像压缩为 JPEG (image.yuv.jpg.yuv --> image.yuv.jpg.yuv.jpg)
- 将JPEG图像解压为YUV图像(image.yuv.jpg.yuv.jpg --> image.yuv.jpg.yuv.jpg.yuv)立>
第 1 步包含有损压缩,因此我们将不再处理此步骤。对我来说,有趣的是之后发生的事情:
如果再次压缩(步骤 3),将 JPEG 图像解压缩回 YUV(步骤 2)会导致图像完全适合所有采样步骤。所以步骤 3 之后的 JPEG 图像(根据我的理解)应该与步骤 1 之后的完全相同。此外,步骤 4 和步骤 2 之后的 YUV 图像应该彼此相等。
查看一个 8x8 块的步骤,以下简化序列应该说明我想要描述的内容。让我们从原始的 YUV 图像开始,该图像只能解压缩丢失所有小数位:
[ 1.123,2.345,3.456,... ] (YUV)
DTC + Quantization
[ -26,-3,-6,... ] (Quantized frequency space)
Inverse DTC + Quantization
[ 1,2,3,... ] (YUV)
使用已经匹配所有步骤的输入执行此操作,这可能会导致之后丢失数据(在我的示例中使用整数),解压后的图像应与其原始图像匹配:
[ 1,... ] (YUV)
DTC + Quantization
[ -26,... ] (YUV)
还有一些来源和讨论,证实了我的想法:
- need help creating Jpeg Generational Degradation code
- What factors cause or prevent “generational loss” when JPEGs are recompressed multiple times?
- Lossless Chroma Subampling
理论到此为止。在实践中,我使用 ffmpeg 和 Nvidias jpeg samples(使用 NvJPEGEncoder)运行了这些步骤。
ffmpeg:
#Create YUV image
ffmpeg -y -i image.jpg -s 1920x1080 -pix_fmt yuv420p image.yuv
#YUV to JPEG
ffmpeg -y -s 1920x1080 -pix_fmt yuv420p -i image.yuv image.yuv.jpg
#JPEG TO YUV
ffmpeg -y -i image.yuv.jpg -s 1920x1080 -pix_fmt yuv420p image.yuv.jpg.yuv
#YUV to JPEG
ffmpeg -y -s 1920x1080 -pix_fmt yuv420p -i image.yuv.jpg.yuv image.yuv.jpg.yuv.jpg
#JPEG TO YUV
ffmpeg -y -i image.yuv.jpg.yuv.jpg -s 1920x1080 -pix_fmt yuv420p image.yuv.jpg.yuv.jpg.yuv
#YUV to JPEG
ffmpeg -y -s 1920x1080 -pix_fmt yuv420p -i image.yuv.jpg.yuv.jpg.yuv image.yuv.jpg.yuv.jpg.yuv.jpg
英伟达:
#Create YUV image
./jpeg_decode num_files 1 image.jpg image.yuv
#YUV to JPEG
./jpeg_encode image.yuv 1920 1080 image.yuv.jpg
#JPEG TO YUV
./jpeg_decode num_files 1 image.yuv.jpg image.yuv.jpg.yuv
#YUV to JPEG
./jpeg_encode image.yuv.jpg.yuv 1920 1080 image.yuv.jpg.yuv.jpg
#JPEG TO YUV
./jpeg_decode num_files 1 image.yuv.jpg.yuv.jpg image.yuv.jpg.yuv.jpg.yuv
#YUV to JPEG
./jpeg_encode image.yuv.jpg.yuv.jpg.yuv 1920 1080 image.yuv.jpg.yuv.jpg.yuv.jpg
图片对比
- image.yuv.jpg.yuv 和 image.yuv.jpg.yuv.jpg.yuv
- image.yuv.jpg.yuv.jpg 和 image.yuv.jpg.yuv.jpg.yuv.jpg
显示文件中的差异。这让我想到了我的问题差异发生的原因和地点,因为根据我的理解,文件应该是相等的。
解决方法
这是generation loss
FFmpeg 会将输入解码为未压缩的原始帧(除非您启用 stream copy 模式)。它对所有格式都这样做。来自 ffmpeg
Documentation 的图表:
_______ ______________
| | | |
| input | demuxer | encoded data | decoder
| file | ---------> | packets | -----+
|_______| |______________| |
v
_________
| |
| decoded |
| frames |
|_________|
________ ______________ |
| | | | |
| output | <-------- | encoded data | <----+
| file | muxer | packets | encoder
|________| |______________|
- 不考虑编码数据,因为图像变成了一个简单的原始帧。
- 编码伪影被视为原始帧的一部分。有损编码器的每一代都会损坏图像以尝试压缩并添加更多编码伪像。
- 由于
ffmpeg
会在重新编码为 JPEG 之前自动将 JPEG 转换为原始 YUV,因此您可以跳过在实验中制作 YUV 文件。 - 解决方案是避免使用有损编码器重新编码。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。