视频压缩初探

最近研究这一部分,试图配合自创的压缩方式,形成自有的视频格式,试验总结如下。(以前没接触过这一块,都是在网上临时学习的,边学边试验,得出初步的结果)

1. 当前大部分视频经过DCT(离散余弦变换)处理后压缩,视频处理过程(编码过程)如下:

视频帧 -> 分解成YUV色差 -> UV色差偏移+128 -> 分区块DCT处理 -> 量化 -> 压缩  -> 压缩帧打包。视频解压是反过来的,(解码过程)如下:

视频帧 <- YUV色差合成RGB <- UV色差偏移-128 <- 反向DCT还原YUV区块 <- 反向量化 <- 解压 <- 压缩帧解包。

2. DCT理论是无损的,得到的是浮点数,再用浮点反向DCT变换,回复原数(是浮点都会有损失,取决于浮点精度)。因压缩需要整形数,所以转成整形数,这一过程称“量化”,造成一定损失,如果DCT后将浮点数“放大”(乘以某数,提高精度),恢复质量有所提高,但压缩率下降。一般称这一数为量化质量,为10时,压缩率为20%,图像质量尚可,不“放大”,显示效果极差,无法接受。

3. DCT输入范围:测试过字节和字输入,特性一样。有符号数和无符号数特性基本一样。

4. 传统视频(几乎当前所有视频)需要转成YUV色差方式再DCT变换压缩,是因为以下三个原因:

(1)最早期是黑白电视机,也就是黑白灰度信号,当彩色电视机出现后,为了兼容黑白电视机,选择了色差信号,其中Y是三个基色合成的信号,可以针对彩色和黑白电视机。

(2)压缩需要,由于对颜色细节不敏感,单独减少颜色细节,具有一定压缩作用。

(3)因最早是由黑白电视机、摄像机、录像机、演播传播系统等发展而来,选择的是兼容方式,当今虽然有RGB摄像及录像原始信号,但未压缩,无法正常使用,所以需要转色差方式压缩。

5. 作为一款自研多媒体软件,视频是不可少的,现有视频播放器都是调用别人的视频播放库,没有任何自主权,虽然有免费的库,但考虑到完全自控,简洁,还是要走创新的路,思路如下:

(1)视频分解成色差方式,其一是为了“兼容”传统黑白系统,作为独立软件不需要考虑“兼容”,采用自有格式,自己的播放器。

(2)视频压缩不同于传统压缩,要求速度,还要兼顾压缩率,看了当今几乎所以的压缩原理,通过融合自我想法,尝试新压缩方法。

(3)转换成色差,压缩颜色,充分利用视觉特点也是很好的方案,相对基于RGB的压缩方式,是否有优势,还需更多的思考。目前可以确定 YUV4:2:0 效果不好,YUV4:1:1 有改善,但很少用,YUV4:2:2 效果和压缩均衡,相对较好。YUV的不足是需要分离视频,需要运算,耗用一定时间,另一个问题是三个基色相互依赖,对还原色纯度不利。

(4)如果分别压缩RGB三个基色变量,因相互无牵连,当压缩率不同时,可能造成色彩混乱。所以RGB作为一个变量压缩,使用最多的RGB888也就是RGB24原始彩色格式,作为一个24位无符号变量,但没有相关量化表,出现困局。

(5)自己造量化表有点悬了,量化表是根据心里因素,对去除图像中的高频分量(也就是清晰度),做了权衡,是相关专家组经过大量实践得出的,经试验,确实如此。

(6)转了一圈,还是回到了色差方式,不是为了兼容,而是为了压缩色彩,利用现有资源,先做到自主,完全掌握,迈出第一步。

6. 相关参考:

//YUV转换宏
#define MY(R, G, B) ( R *  0.2989 + G *  0.5866 + B * 0.1145) 
#define MU(R, G, B) ((R * (-0.1688) + G * (-0.3312) + B * 0.5000 + 128)) 
#define MV(R, G, B) ((R *  0.5000 + G * (-0.4184) + B * (-0.0816) + 128))

const BYTE bzYQTable[8][8] = { //亮度Y量化表
{16,11,10,16,24,40,51,61},
{12,12,14,19,26,58,60,55},
{14,13,16,24,40,57,69,56},
{14,17,22,29,51,87,80,62},
{18,22,37,56,68,109,103,77},
{24,35,55,64,81,104,113,92},
{49,64,78,87,103,121,120,101},
{72,92,95,98,112,100,103,99}};

const BYTE bzUVQTable[8][8] = { //色度UV量化表
{17,18,24,47,99,99,99,99},
{18,21,26,66,99,99,99,99},
{24,26,56,99,99,99,99,99},
{47,66,99,99,99,99,99,99},
{99,99,99,99,99,99,99,99},
{99,99,99,99,99,99,99,99},
{99,99,99,99,99,99,99,99},
{99,99,99,99,99,99,99,99}};

void __fastcall CDCT::DCT(float fOutPut[][8], char czInPut[][8])//离散余玄变换
{
   float ALPHA, BETA, tmp; int u,v,i,j;

   for(u = 0; u < 8; u++)
      {
        for(v = 0; v < 8; v++)
           {
             if(u == 0)
                ALPHA = sqrt(1.0 / 8.0);
                else
                ALPHA = sqrt(2.0 / 8.0);

             if(v == 0)
                BETA = sqrt(1.0 / 8.0);
                else
                BETA = sqrt(2.0 / 8.0);

             tmp = 0.0;
             for(i = 0; i < 8; i++)
             for(j = 0; j < 8; j++)
                {
                   tmp += czInPut[i][j] * cos((2 * i + 1) * u * PI / (2 * 8)) * cos((2 * j + 1) * v * PI / (2 * 8));
                }
             fOutPut[u][v] = ALPHA * BETA * tmp;
           }
      }
}

void __fastcall CDCT::Quant(int czOutPut[][8], float InMatrix[][8], const BYTE bzQTable[][8])//量化
{
   int x,y; float fQuant;

   for(x = 0; x < 8; x++)
   for(y = 0; y < 8; y++)
      {
         fQuant = InMatrix[x][y] / bzQTable[x][y];//量化
         fQuant = fQuant * byQuantizationQuality;//量化质量
         czOutPut[x][y] = (int)fQuant;//截尾
      }
}

猜你喜欢

转载自www.cnblogs.com/hbg200/p/8931224.html