首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

JPEG 原理详细实例分析及其在嵌入式 Linux 中的应用(4)JPEG 压缩过程的优化

JPEG 原理详细实例分析及其在嵌入式 Linux 中的应用(4)JPEG 压缩过程的优化

JPEG 在目前的应用范围是非常广泛的,各种嵌入式系统中也大量地使用了 JPEG 压缩,如 IPCAM 摄像头、数字相机、移动存贮等。在这些领域由于传输数据的带宽限制或者是存贮数据的容量的限制,常常需要使用图像压缩技术来将原始大量的图像数据压缩后在进行传输或存贮,以充分利用带宽与存贮空间,达到更好的利用效率。这样,在嵌入系统中,就会使用到 JPEG 压缩。而且由于嵌入系统的资源有限的特点,在很多情况下,很需要再对 JPEG 编码压缩的过程做更进一步的优化,我们这里详细讨论一下如何实现这些优化。
浮点运算的优化我们回头查看一下 JPEG 压缩中的 DCT 变换过程,公式:
由于公式中有两个 i/j=0~7 的部分,这样要获得一个 DCT 系数,需要做 8 x 8=64 次乘法和 8 x 8=64 次加法, 而完成整个 8 x 8 像素的 DCT 需要 8 x 8 x 8 x 8=4096 次乘法和 8 x 8 x 8 x 8=4096 次加法. 计算量是相当的大。
对于有些无浮点运算的嵌入式系统或无专门的数学运算协处理器的系统,会造成大量的运算,极大地占用CPU的资源。
上面的公式属于 DCT 的二维计算方式,经过简化,可以将其简化为两个一维的公式:
这样,上面的过程就可以简化为分别计算行和列的 DCT 变换。
对于一行来说需要计算的是 (8 x 8) 次乘法和 (8 x 8) 次加法,8 行就是 8 x (8 x 8) 次乘法和 8 x (8 x 8) 次加法,然后列也是相同,那么总数就为 2 x (8 x (8 x 8))=1024 次乘法和 2 x (8 x (8 x 8))=1024 次加法, 运算量变为二维计算的1/4。
但是这样的运算数量还是太大,还需要进一步优化。
在很多嵌入系统中,很多情况下需要不使用浮点运算,这样就需要再找出一维 DCT 的一些规律,然后对其进行进一步的优化。
在对一维 DCT 的运算中,还可以分为奇数列/行和偶数列/行
对上面的处理,就又出现了多种优化:ChenDCT,LeeDCT,AAN 算法和 LLM 算法。
其中 AAN 算法只需要 29 次加法和 5 次乘法。(注意,它是指每次一维运算要 29 次加法和 5 次乘法,一共是需要 29*8*2 次加法和 5*8*2 次乘法的)。
其中 Y[0]-Y[7] 都是 1*8 的矩阵,X[1]-X[7] 也都是 1*8 的矩阵。
{a, b, c, d, e, f, g} =  1/2 { cos(pi/4), cos(pi/16), cos(pi/8), cos(3pi/16), cos(5pi/16), cos(3pi/8), cos(7pi/16) }
再对上面的含有 pi 的系数进行整数优化,从而避免浮点运算,就会得到:
其中:
3/8=1/4+1/8
5/8=1/2+1/8
7/8=1-1/8
上面的除以 2,除以 8,都可以通过移位来实现,即右移一位和右移三位。即总数为 30 次加法,12 次移位即可。
这样就在很大程度上将原本需要使用乘法,浮点运算的过程全部转换成了简单的加法和移位处理了,这样使用数学的方法,用近似的值来完成整个转换过程,会有很好的性能和处理效果。
在处理上面的数据中,可以使用一些中间变量来记录中间结果,这样就可以减少反复计算中间值,而直接使用已经计算得到了的中间值。
   tmp0 = x[0] + x[7];
   tmp7 = x[0] - x[7];
   tmp1 = x[1] + x[6];
   tmp6 = x[1] - x[6];
   tmp2 = x[2] + x[5];
   tmp5 = x[2] - x[5];
   tmp3 = x[3] + x[4];
   tmp4 = x[3] - x[4];
   tmp10 = tmp0 + tmp3;
   tmp13 = tmp0 - tmp3;
   tmp11 = tmp1 + tmp2;
   tmp12 = tmp1 - tmp2;
/* 对偶数项进行运算 X 0,4,6,2 */   
   X[0]=tmp1+tmp11;
   X[4]=tmp10 /2 - tmp11
   X[6]=tmp12-(tmp13/4+ tmp13/8);
   X[2]=tmp12/4+tmp12/8-tmp13;
其他的各个值也是类似处理的。
返回列表