二维离散变换由c语言编写,C++实现离散余弦变换(参数为二维指针)(示例代码)...

http://www.cnblogs.com/scut-linmaojiang/p/5013590.html

写在前面

到目前为止已经阅读了相当一部分的网格水印等方面的论文了,但是论文的实现进度还没有更上,这个月准备挑选一些较为经典的论文,将其中的算法实现。在实现论文的过程中,发现论文中有用到一些空域转频率域的算法。因此也就想到了实现一下离散余弦变换。虽然本文的代码和网上很多已有的代码很类似,思路都没有太多的差别,但是本文有一个比较重要的改进。具体的说,网上现有DCT算法输入的是一个固定的二维数组。当二维数组作为函数参数进行传递时,至少需要给出第二个维度的大小,否则编译器会报错。但是在图形图像处理中,当我们希望使用DCT变换把某个图形或者图像转换到频域时,可能我在调用DCT函数之前事先并不知道图形或者图像的规模,因此这种传参方式较大限制了代码的使用。本文的一个改进就是,DCT函数的参数不再是二维数组,而是传入一个二维指针,通过手动寻址来实现函数功能。

离散余弦变换理论基础

我想大家比较熟知的是傅立叶变换。其实离散余弦变换跟傅立叶变换差不多。二维离散余弦变换的定义由下式表示:

f16b08ca356b272e3845d3c3a4ac8225.png

反变换表示如下:

d8332d4627730050a0e9c321da1aee51.png

代码实现

根据上面的公式,很容易就能写出代码

// DCT - Discrete Cosine Transform

void DCT( double ** input, double ** output, int row, int col )

{

cout<

double ALPHA, BETA;

int u = 0;

int v = 0;

int i = 0;

int j = 0;

for(u = 0; u < row; u++)

{

for(v = 0; v < col; v++)

{

if(u == 0)

{

ALPHA = sqrt(1.0 / row);

}

else

{

ALPHA = sqrt(2.0 / row);

}

if(v == 0)

{

BETA = sqrt(1.0 / col);

}

else

{

BETA = sqrt(2.0 / col);

}

double tmp = 0.0;

for(i = 0; i < row; i++)

{

for(j = 0; j < col; j++)

{

tmp += *((double*) input + col*i + j ) * cos((2*i+1)*u*PI/(2.0 * row)) * cos((2*j+1)*v*PI/(2.0 * col));

}

}

*((double*) output + col*u + v) = ALPHA * BETA * tmp;

}

}

cout << "The result of DCT:" << endl;

for(int m = 0; m < row; m++)

{

for(int n= 0; n < col; n++)

{

cout <

}

cout << endl;

}

}

注意代码中的函数参数不是二维数组,而是一个指向二维数组的指针。相应的反变换的代码如下:

// Inverse DCT

void IDCT( double ** input, double ** output, int row, int col )

{

cout<

double ALPHA, BETA;

int u = 0;

int v = 0;

int i = 0;

int j = 0;

for(i = 0; i < row; i++)

{

for( j = 0; j < col; j++)

{

double tmp = 0.0;

for(u = 0; u < row; u++)

{

for(v = 0; v < col; v++)

{

if(u == 0)

{

ALPHA = sqrt(1.0 / row);

}

else

{

ALPHA = sqrt(2.0 / row);

}

if(v == 0)

{

BETA = sqrt(1.0 / col);

}

else

{

BETA = sqrt(2.0 / col);

}

tmp += ALPHA * BETA * *((double*) input + col*u + v )* cos((2*i+1)*u*PI/(2.0 * row)) * cos((2*j+1)*v*PI/(2.0 * col));

}

}

*((double*) output + col*i + j) = tmp;

}

}

cout << "The result of IDCT:" << endl;

for(int m = 0; m < row; m++)

{

for(int n= 0; n < col; n++)

{

cout <

}

cout << endl;

}

}

测试代码

#include

#include

#include

#include

#include

using namespace std;

#define PI 3.1415926

int main()

{

int i = 0;

int j = 0;

int u = 0;

int v = 0;

const int rows = 3;

const int cols = 3;

double inputdata[rows][cols] = {

{89,101,114},

{97,115,131},

{114,134,159},

};

double outputdata[rows][cols];

DCT( (double**)inputdata, (double**)outputdata,rows, cols );

IDCT( (double**)outputdata, (double**)inputdata,rows,cols );

system("pause");

return 0;

}

程序运行结果如下:

647790a84f1a1db9b5c96f77239b9270.png

小结

之后可以对代码进行升级,不再使用二维数组作为参数传递,而是使用Eigen类型作为参数,这样代码更加清晰,并且内存管理等方面也更加方便。

转载请注明出处:http://www.cnblogs.com/scut-linmaojiang/p/5013590.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值