C# 中的 DCT 实现(图像的 DCT)






4.50/5 (12投票s)
在 C# 中实现图像的 DCT(二维 DCT)及其逆变换

引言
离散余弦变换 (DCT) 将有限多个数据点表示为不同频率下振荡的余弦函数之和。频率。DCT 在科学和工程领域的许多应用中都很重要,从有损压缩的音频和图像(其中可以丢弃小的、高频分量)到求解偏微分方程的数值谱方法。在这些应用中,使用余弦函数而不是正弦函数至关重要:对于压缩,事实证明余弦函数效率更高(如下所述,需要更少的函数来近似典型的信号),而对于微分方程,余弦函数表达了边界条件的特定选择。
特别是,DCT 是一种傅里叶相关变换,类似于离散傅里叶变换 (DFT),但仅使用实数。DCT 等价于长度大约是两倍的 DFT,作用于具有偶对称性的实数数据(因为实数和偶数函数的傅里叶变换是实数和偶数),在某些变体中,输入和/或输出数据会移动半个样本。有八种标准的 DCT 变体,其中四种很常见。
背景
在这里,我展示了 2D DCT 的实现。我们首先生成 2D DCT 核,然后使用矩阵运算执行 DCT。我懒得写理论。请参考相关书籍。
Using the Code
在这里,我们执行以下活动
- 选择图像,缩放图像以使其适合图片框,此缩放显示在缩放百分比框中。
- 选择图像的特定部分,我们选择尺寸是 2 的倍数(128*128、256*256)的图像部分。
- 将图像读取到 2D 数组中,我们为此使用指针算术,我们必须在项目属性中允许指针操作。
private void ReadImage() { int i, j; GreyImage = new int[Width, Height]; //[Row,Column] Input = new double [Width, Height]; //[Row,Column] Bitmap image = Obj; BitmapData bitmapData1 = image.LockBits(new Rectangle (0, 0, image.Width, image.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); unsafe { byte* imagePointer1 = (byte*)bitmapData1.Scan0; for (i = 0; i < bitmapData1.Height; i++) { for (j = 0; j < bitmapData1.Width; j++) { GreyImage[j, i] = (int)((imagePointer1[0] + imagePointer1[1] + imagePointer1[2]) / 3.0); Input [j,i]=(double)GreyImage[j,i]; //4 bytes per pixel imagePointer1 += 4; }//end for j //4 bytes per pixel imagePointer1 += bitmapData1.Stride - (bitmapData1.Width * 4); }//end for i }//end unsafe image.UnlockBits(bitmapData1); return; }
- 创建实现 DCT 的
FastDCT2D
类的对象。 - 要找到 DCT,首先我们必须生成 2D DCT 核,然后实现乘法。
public double[,] GenerateDCTmatrix(int order) { int i, j; int N; N = order; double alpha; double denominator; double[,] DCTCoeff = new double[N, N]; for (j = 0; j <= N - 1; j++) { DCTCoeff[0, j] = Math.Sqrt(1 / (double)N); } alpha = Math.Sqrt(2 / (double)N); denominator = (double)2 * N; for (j = 0; j <= N - 1; j++) for (i = 1; i <= N - 1; i++) { DCTCoeff[i, j] = alpha * Math.Cos(((2 * j + 1) * i * 3.14159) / denominator); } return (DCTCoeff); }
public void FastDCT() { double[,] temp = new double[Width, Height]; DCTCoefficients = new double[Width, Height]; DCTkernel = new double[Width, Height]; DCTkernel = GenerateDCTmatrix(Order); temp = multiply(DCTkernel, Input); DCTCoefficients = multiply(temp, Transpose(DCTkernel)); DCTPlotGenerate(); return; }
关注点
DCT 图也使用动态范围压缩生成。
历史
这是我的第一次尝试。我还在代码中添加了一个慢速版本的 DCT,这是由另一位作者提供的。欢迎任何更改或建议。