65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.50/5 (12投票s)

2009年11月16日

CPOL

2分钟阅读

viewsIcon

85206

downloadIcon

7197

在 C# 中实现图像的 DCT(二维 DCT)及其逆变换

Click to enlarge image

引言

离散余弦变换 (DCT) 将有限多个数据点表示为不同频率下振荡的余弦函数之和。频率。DCT 在科学和工程领域的许多应用中都很重要,从有损压缩音频图像(其中可以丢弃小的、高频分量)到求解偏微分方程的数值谱方法。在这些应用中,使用余弦函数而不是正弦函数至关重要:对于压缩,事实证明余弦函数效率更高(如下所述,需要更少的函数来近似典型的信号),而对于微分方程,余弦函数表达了边界条件的特定选择。

特别是,DCT 是一种傅里叶相关变换,类似于离散傅里叶变换 (DFT),但仅使用实数。DCT 等价于长度大约是两倍的 DFT,作用于具有对称性的实数数据(因为实数和偶数函数的傅里叶变换是实数和偶数),在某些变体中,输入和/或输出数据会移动半个样本。有八种标准的 DCT 变体,其中四种很常见。

背景

在这里,我展示了 2D DCT 的实现。我们首先生成 2D DCT 核,然后使用矩阵运算执行 DCT。我懒得写理论。请参考相关书籍。

Using the Code

在这里,我们执行以下活动

  1. 选择图像,缩放图像以使其适合图片框,此缩放显示在缩放百分比框中。
  2. 选择图像的特定部分,我们选择尺寸是 2 的倍数(128*128、256*256)的图像部分。
  3. 将图像读取到 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;
            } 
  4. 创建实现 DCT 的 FastDCT2D 类的对象。
  5. 要找到 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,这是由另一位作者提供的。欢迎任何更改或建议。

© . All rights reserved.