我有一个提供高质量 MJPEG 的网络摄像头。
我需要通过网络发送小型、低质量的 JPEG。我的硬件是 Raspberry Pi (700MHz ARM)。我希望代码使用尽可能少的 CPU 资源,并尽可能减少延迟。我可以对每一帧进行解码和重新编码,但这可能很浪费......
在不解码的情况下降低 JPEG 图像的质量在逻辑上是否可行?
即我可以找到并删除“细粒度”数据块,然后修复字段长度和校验和吗?
我有一个提供高质量 MJPEG 的网络摄像头。
我需要通过网络发送小型、低质量的 JPEG。我的硬件是 Raspberry Pi (700MHz ARM)。我希望代码使用尽可能少的 CPU 资源,并尽可能减少延迟。我可以对每一帧进行解码和重新编码,但这可能很浪费......
在不解码的情况下降低 JPEG 图像的质量在逻辑上是否可行?
即我可以找到并删除“细粒度”数据块,然后修复字段长度和校验和吗?
但实际上,任何能够做到这一点的系统都能够在合理的时间内对 jpeg 进行解码和重新编码。
任何试图直接降低 jpeg 质量的代码都需要有以下两个阶段:
阶段 1。解析 jpeg 文件以识别各种标记和有效负载。
阶段 2。剥离有效载荷的高熵部分并准备新文件。
上面的 Phase1 将具有 jpeg 解码器的复杂性。
任何潜在的性能提升都必须通过实施 Phase2 来获得,以比 jpeg 编码在较低 Q 值下执行得更快。这不是一个有吸引力的提议,因为编码时间随着 Q 因子2的降低而减少。换句话说,以较低 Q 因子编码图像数据几乎总是比尝试剥离以较高 Q 因子编码的图像数据更快。
另一种方法(类似于您的想法)将很好地适用于 jpeg 图像的子集 -渐进式 JPEG(顺便说一句,简直太棒了)。
在渐进式 JPEG 图像中,分量在多次扫描中进行编码。每个组件的压缩数据最少放置 2 次,最多 896 次扫描。初始扫描创建图像的粗略版本,而后续扫描对其进行细化。
本质上,扫描的数量决定了 jpeg 的质量,因为后者的扫描通过在图像中添加细粒度的高熵信息来改进先前的扫描。
在 jpeg 流中,每次扫描都由本质上为 2 个字节的 SOS(扫描开始标记)表示0xFF
,0xDA
后跟有效负载,即包含在该特定扫描中的编码数据(或“切片”,在技术上是准确的)。
为了减小渐进式 jpeg 的大小,可以简单地从 jpeg 文件中读入预定数量的扫描/切片,并以质量为代价删除后者。这可以在从文件中读取 jpeg 数据时实现,或者稍后在编码数据的单次传递中实现。
参考资料:
1. en.wikipedia.org/wiki/JPEG。
2. 格雷戈里·K·华莱士。JPEG 静态图片压缩标准。ACM 的通讯,34(10),1991 年 10 月。
3. ece.ucdavis.edu/cerl/ReliableJPEG/Cung/jpeg.html
感谢您请求评论。
嗯,Motion-JPEG 实际上是目前可用的最高质量的运动图像格式,并且它具有很大的进一步处理和转换的潜力,而这目前还远未实现。
有几个方面需要考虑,我可以在这里给你举三个具体的例子。
首先,通过在汇编器级别上对 JPEG 编解码器进行特定于平台的优化,可以极大地提高运行时性能,如下所示:
通过针对特定 ARM 平台的极端软件优化,该应用程序甚至比在此设备上为此目的的专用硬件解决方案实现了更快的速度!
其次,有一些应用程序可以通过优化量化表来显着减小相同分辨率和相同外观质量的给定 JPEG 图像的大小。搜索 ThinPic App 和 JPEGmini(看来我不允许在这里发布更多链接)。
这些都是商业产品,因此没有可用的免费源代码。
第三,我需要降低给定 Motion-JPEG 文件的分辨率。它们是在数码相机上以 1280x720 拍摄的,我想在屏幕上的窗口中以 640x360 的一半大小播放它们。
我使用 JPEG 8 引入的新 SmartScale 功能,通过简单地切断 DCT 块的高频系数来实现这种减少而不损失质量。生成的文件大小的减少并不是那么大(大约小 20%),但是用 4x4 DCT 播放 640x360 而不是用 8x8 DCT 播放 1280x720 的要求要低得多。
转码是使用特别改编的VirtualDub和jpegtran源代码完成的(在这个用例中引入了 IJG 代码的新内存源和目标管理器)。播放是通过特别改编的ffdshow源代码完成的。这是一个用于演示的实验设置,远非可分发状态。
问候,Guido Vollbeding,独立组织者 JPEG 组