视频编码中变换编码之DCT变换原理
视频编码中变换编码之DCT变换原理
1、预测编码
2、变换编码
3、量化编码
4、熵编码
②、视频编码中熵编码之"Z"字扫描原理(变换DCT系数和小波变换系统分布特性和统计特性)
③、视频编码中熵编码之基于上下文的变长编码(Buffman霍夫曼编码和指数哥伦布)
5、 环路滤波
前言
变换被认为是图像或视频编码中最有效的技术之一,将空域信号变化到频域信号,有效地去除了信号的相关性,并使大部分能量集中到低频区域。根据变换的这一特点,有选择的编码部分显著的频域信号,掉弃不显著的频域信号,可以达到提高压缩效率的目的。
一、图形的频域统计特性
在频率熵, 图形表现为不同频率分量系数的 分布
1、FFT频谱图
图像进行FFT变换得到频谱图
FFT频谱图中间位置比较亮的,四周比较暗
图像的基础知识 => 255表示比较亮的, 0 表示暗的
中间能量比较大的, 四周能量比较小
2、DCT变换
图像左上角比较亮的, 说明左上角能量比较大
cv::Mat src = cv::imread("D:/Work/ccuda/CudaRuntime/CudaTexture/cinque_terre_small.jpg", 0);
if (src.empty())
{
std::cout << "the image is not exist" << std::endl;
return -1;
}
cv::resize(src, src, cv::Size(512, 512));
// 1. 转换为灰色图
src.convertTo(src, CV_32F, 1.0 / 255);
cv::Mat srcDCT;
// 2. dct变换
cv::dct(src, srcDCT);
// cv::Mat srcFFT;
// 3. FFT 变换
//Extending image
int m = cv::getOptimalDFTSize(src.rows);
int n = cv::getOptimalDFTSize(src.cols);
cv::copyMakeBorder(src, src, 0, m - src.rows, 0, n - src.cols, cv::BORDER_CONSTANT, cv::Scalar(0));
//Fourier transform
cv::Mat mFourier(src.rows + m, src.cols + n, CV_32FC2, cv::Scalar(0, 0));
cv::Mat mForFourier[] = { cv::Mat_<float>(src), cv::Mat::zeros(src.size(), CV_32F) };
cv::Mat mSrc;
cv::merge(mForFourier, 2, mSrc);
cv::dft(mSrc, mFourier);
//channels[0] is the real part of Fourier transform,channels[1] is the imaginary part of Fourier transform
std::vector<cv::Mat> channels;
cv::split(mFourier, channels);
cv::Mat mRe = channels[0];
cv::Mat mIm = channels[1];
//Calculate the amplitude
cv::Mat mAmplitude;
cv:: magnitude(mRe, mIm, mAmplitude);
//Logarithmic scale
mAmplitude += cv::Scalar(1);
cv::log(mAmplitude, mAmplitude);
//The normalized
cv::normalize(mAmplitude, mAmplitude, 0, 255, cv::NORM_MINMAX);
cv::Mat srcFFT(src.rows, src.cols, CV_8UC1, cv::Scalar(0));
for (int i = 0; i < src.rows; i++)
{
uchar* pResult = srcFFT.ptr<uchar>(i);
float* pAmplitude = mAmplitude.ptr<float>(i);
for (int j = 0; j < src.cols; j++)
{
pResult[j] = (uchar)pAmplitude[j];
}
}
cv::Mat mQuadrant1 = srcFFT(cv::Rect(srcFFT.cols / 2, 0, srcFFT.cols / 2, srcFFT.rows / 2));
cv::Mat mQuadrant2 = srcFFT(cv::Rect(0, 0, srcFFT.cols / 2, srcFFT.rows / 2));
cv::Mat mQuadrant3 = srcFFT(cv::Rect(0, srcFFT.rows / 2, srcFFT.cols / 2, srcFFT.rows / 2));
cv::Mat mQuadrant4 = srcFFT(cv::Rect(srcFFT.cols / 2, srcFFT.rows / 2, srcFFT.cols / 2, srcFFT.rows / 2));
cv::Mat mChange1 = mQuadrant1.clone();
//mQuadrant1 = mQuadrant3.clone();
//mQuadrant3 = mChange1.clone();
mQuadrant3.copyTo(mQuadrant1);
mChange1.copyTo(mQuadrant3);
cv::Mat mChange2 = mQuadrant2.clone();
//mQuadrant2 = mQuadrant4.clone();
//mQuadrant4 = mChange2.clone();
mQuadrant4.copyTo(mQuadrant2);
mChange2.copyTo(mQuadrant4);
cv::imshow("原图", src);
cv::imshow("原图的dct频谱图", srcDCT);
cv::imshow("原图的FFT频谱图", srcFFT);
cv::waitKey();
二、 DCT变换
或称为DCT变换(Discreate Cosine Transform)
简言之、DCT变换可以将8行8列的数组(或矩阵)变换成另外一个8行8列的数组(或矩阵)
直流系数(DC)
黑色区域是的数据称为直流系数,或叫做直流分量,也叫做低频分量;
在DCT变换后的64个系数中,低频分量包含了图像亮度的主要信息。
交流系数 (AC)
灰色区域的数据称为交流系数、或叫做交流分量,灰色区域叫做中频分量,白色区域叫做高频分量;
离散小波
离散博立叶
-
混合编码
JPEG编码
JPEG编码的具体步骤
量化
量化表中数除以DCT系数矩阵 得到量化后的DCT系数矩阵
DCT系数矩阵/量化系数
DC系数及AC系数编码
DC系数编码
DC系数反映了8X8数据块的主要信息(平均亮度),一般与相邻块有较大的相关性。所以对DC系数作差分编码,即用前一个数据块的DC系数作为当前块的预测值,再计算当前块的实际值与预测值的差值,最后对这个差值进行 <font color='red'> Huffman编码</font>。
AC系数编码
AC系数经过Z型排列后,更有可能出现连续的0组成的字符串,从而对其进行<font color='red'>行程编码</font>将有有利于压缩。
行程编码 例子
编码前:00000000000000202000000000007000000000000000000
编码后:[14,0][1,2][1,0][1,2][8,0][1,7][17,0]
离散傅里叶变换(DFT)与快速傅里叶变换(FFT)
总结
数字视频编码技术原理地址:https://chensongpoixs.github.io/cvideo_codec/