离散余弦变换(C++实现)

比眉伴天荒 2022-08-07 15:00 278阅读 0赞

理论部分转载自这篇blog: http://blog.csdn.net/luoweifu/article/details/8214959 该blog给出的是java代码,我用c++将其实现了。

理论:

图像处理中常用的正交变换除了傅里叶变换外,还有其他一些有用的正交变换,其中离散余弦就是一种。离散余弦变换表示为DCT( Discrete Cosine Transformation),常用于图像处理和图像识别等。

一维离散余弦变换

正变换

1353632653_2255.png (1)

1353632745_6059.png (2)

式中F(u)是第u个余弦变换系数,u是广义频率变量,u=1,2,3……N-1; f(x)是时域N点序列, x=0,1,2……N-1

反变换

1353632875_8831.png (3)

显然,式(1)式(2)和式(3)构成了一维离散余弦变换对。

二维离散余弦变换

正变换

1353633096_2524.png (4)

式(4)是正变换公式。其中f(x,y)是空间域二维向量之元素, x,y=0,1,2,……N-1;F(u,v)是变换系数阵列之元素。式中表示的阵列为N×N

反变换

1353633198_1395.png (5)

式中的符号意义同正变换式一样。式(4)和式(5)是离散余弦变换的解析式定义。

矩阵表示法

更为简洁的定义方法是采用矩阵式定义。根据以上公式定义可知,离散余弦变换的系数矩阵可以写成如下:

1353633448_3354.png

如果令N=4,那么由一维解析式定义可得如下展开式。

1353633524_2787.png

写成矩阵式

1353633828_9577.png

若定义F(u)为变换矩阵,A为变换系数矩阵,f(x)为时域数据矩阵,则一维离散余弦变换的矩阵定义式可写成如下形式

[F(u)]=[A][f(x)] (6)

同理,可得到反变换展开式

1353634247_6785.png

写成矩阵式即

[f(x)]=[A]T[F(u)] (7)

二维离散余弦变换也可以写成矩阵式:

[F(u,v)]=[A][f(x,y)][A]T (8)

[f(x,y)]=[A]T[F(u,v)][A]

式中[f(x,y)]是空间数据阵列,A是变换系数阵列,[F(u,v)]是变换矩阵,[A]T是[A]的转置。

对二维图像进行离散余弦变换

由以上对二维离散余弦变换的定义及公式(7)可知,求二维图像的离散余弦变换要进行以下步骤:

1.获得图像的二维数据矩阵f(x,y);

2.求离散余弦变换的系数矩阵[A];

3.求系数矩阵对应的转置矩阵[A]T;

4.根据公式(7)[F(u,v)]=[A][f(x,y)][A]T 计算离散余弦变换;

以下是我的c++代码实现<当然其中针对的是图像,故用到了opencv的库函数>:

C++代码:

  1. /*
  2. 功能:获取DCT系数
  3. n:矩阵大小
  4. quotient: 系数
  5. quotientT: 系数转置
  6. */
  7. void coefficient(const int &n, double **quotient, double **quotientT){
  8. double sqr = 1.0/sqrt(n+0.0);
  9. for(int i = 0; i < n; i++){
  10. quotient[0][i] = sqr;
  11. quotientT[i][0] = sqr;
  12. }
  13. for(int i = 1; i < n; i++){
  14. for(int j = 0; j < n; j++){
  15. quotient[i][j] = sqrt(2.0/n)*cos(i*(j+0.5)*PI/n); // 由公式得到
  16. quotientT[j][i] = quotient[i][j];
  17. }
  18. }
  19. }
  20. /*
  21. 功能:两矩阵相乘
  22. A和B:源输入矩阵
  23. result:输出矩阵
  24. */
  25. void matrixMultiply(double **A, double **B, int n, double **result){
  26. double t = 0;
  27. for(int i = 0; i < n; i++){
  28. for(int j = 0; j < n; j++){
  29. t = 0;
  30. for(int k = 0; k < n; k++)
  31. t += A[i][k]*B[k][j];
  32. result[i][j] = t;
  33. }
  34. }
  35. }
  36. // DCT变换
  37. void DCT(Mat_<uchar> image, const int &n, double **iMatrix){
  38. for(int i = 0; i < n; i++){
  39. for(int j = 0; j < n; j++){
  40. iMatrix[i][j] = (double)image(i,j);
  41. }
  42. }
  43. // 为系数分配空间
  44. double **quotient = new double*[n];
  45. double **quotientT = new double*[n];
  46. double **tmp = new double*[n];
  47. for(int i = 0; i < n; i++){
  48. quotient[i] = new double[n];
  49. quotientT[i] = new double[n];
  50. tmp[i] = new double[n];
  51. }
  52. // 计算系数矩阵
  53. coefficient(n, quotient, quotientT);
  54. matrixMultiply(quotient, iMatrix, n, tmp); // 由公式成绩结果
  55. matrixMultiply(tmp, quotientT, n, iMatrix);
  56. for(int i = 0; i < n; i++){
  57. delete []tmp[i];
  58. delete []quotient[i];
  59. delete []quotientT[i];
  60. }
  61. delete []tmp;
  62. delete []quotient;
  63. delete []quotientT;
  64. }

发表评论

表情:
评论列表 (有 0 条评论,278人围观)

还没有评论,来说两句吧...

相关阅读