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

反变换表示如下:

代码实现
根据上面的公式,很容易就能写出代码
// DCT - Discrete Cosine Transform
void DCT( double ** input, double ** output, int row, int col )
{
cout<<"Test in DCT"<<endl;
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 <<setw(8)<< *((double*) output + col*m + n)<<" \t";
}
cout << endl;
}
}
注意代码中的函数参数不是二维数组,而是一个指向二维数组的指针。相应的反变换的代码如下:
// Inverse DCT
void IDCT( double ** input, double ** output, int row, int col )
{
cout<<"Test in IDCT"<<endl;
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 <<setw(8)<< *((double*) output + col*m + n)<<"\t";
}
cout << endl;
}
}
测试代码
#include <iostream>
#include <math.h>
#include<cstdio>
#include <iomanip>
#include<algorithm>
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;
}
程序运行结果如下:

小结
之后可以对代码进行升级,不再使用二维数组作为参数传递,而是使用Eigen类型作为参数,这样代码更加清晰,并且内存管理等方面也更加方便。
转载请注明出处:http://www.cnblogs.com/scut-linmaojiang/p/5013590.html
C++实现离散余弦变换(参数为二维指针)的更多相关文章
- C#微信公众号接口开发实例-高级接口-申请带参数的二维码
最近公司涉及到微信绑定用户,做了高级接口-申请带参数的二维码,总结了下微信开发接口.微信接口开发都是除了消息用的xml 回复基本上都是用json的形式传递信息(post/get),开发的方法基本都是一 ...
- Force.com微信开发系列(八)生成带参数的二维码
为了满足用户渠道推广分析的需要,公众平台提供了生成带二维码的接口.使用该接口可以获得多个带不同场景值的二维码,用户扫描后,公众号可以接收到事件推送.目前有两种类型的二维码,分别是临时二维码和永久二维码 ...
- 微信开发之——Php批量生成带参数的二维码
带参数的二维码对于渠道营销推广来说是很有用的,可以获得多个带不同场景值的二维码,用户扫描后,公众号可以接收到事件推送,可喜的是微信开通了这个接口,那下面就来研究一下吧. 具体接口说明请参见,微信公众平 ...
- C语言里的指针探析——type *name[] 在函数参数里面,是一个二维指针
type *name[] 在函数参数里面声明和不在函数里面声明其实不一样. type *name[] 如果在函数参数里声明,则name 是一个二维指针,并不是一个指针数组,而如果不在函数参数里声明,则 ...
- 微信公众号生成带参数的二维码asp源码下载
晚上闲着没事,一个朋友联系,让帮忙写一个微信公众号利用asp生成带参数的二维码,别人扫了后如果已经关注过该公众号的,则直接进入公众号里,如果没关注则提示关注,关注后自动把该微信用户资料获取到并且保存入 ...
- 通过数组初始化链表的两种方法:指向指针的引用node *&tail和指向指针的指针(二维指针)node **tail
面试高频题:单链表的逆置操作/链表逆序相关文章 点击打开 void init_node(node *tail,char *init_array) 这样声明函数是不正确的,函数的原意是通过数组初始化链表 ...
- 【视频开发】OpenCV中Mat,图像二维指针和CxImage类的转换
在做图像处理中,常用的函数接口有OpenCV中的Mat图像类,有时候需要直接用二维指针开辟内存直接存储图像数据,有时候需要用到CxImage类存储图像.本文主要是总结下这三类存储方式之间的图像数据的转 ...
- 二维指针*(void **)的研究(uC/OS-II案例) 《转载》
uC/OS-II内存管理函数内最难理解的部分就是二维指针,本文以图文并茂的方式对二维指针进行了详细分析与讲解.看完本文,相信对C里面指针的概念又会有进一步的认识. 一.OSMemCreate( ) 函 ...
- 最长公共子序列的C++实现---附二维指针的使用方法
想了挺久到底第一篇在这儿的博客写什么好,刚好这两天又一次看到动态规划的LCS算法觉得还是有点意思的,就拿来写了写,第一篇博客就发它吧. #include<iostream> #includ ...
随机推荐
- java io流缓冲理解
bufferedinputstream和bufferedoutputstream:这两个类是在inputstream和outputstream的基础上增加了一个buffer的缓冲区,从而使数据不直接写 ...
- C#五层架构
UI Business Logic Layer Business Rule Layer Data Access Layer Data Definition Layer 简单工厂模式 simple fa ...
- System.Windows.Forms.AxHost.InvalidActiveXStateException”类型的异常在 ESRI.ArcGIS.AxControls.dll 中发生,但未在用户代码中进行处理
private void CopyAndOverwriteMap() { //IObjectCopy接口变量申明 IObjectCopy objectCopy = new ObjectCopyClas ...
- C++:向函数传递对象(对象、对象指针、对象引用)
3.5.1 使用对象作为函数参数,其方法与传递基本类型的变量相同 //例3.21 使用对象作为函数参数 #include<iostream> using namespace std; ...
- Hibernate 多表关联
hibernate中可以一次对多个表进行数据插入,这种插入类似 Hibernate的关联映射关系有:多对一 ---- many-to-one一对多 ---- one-to-many一对一 ---- o ...
- java23中设计模式
原文来自:http://zz563143188.iteye.com/blog/1847029 设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design patt ...
- java开发之匿名内部类,接口的使用
下面的例子是Java.JDK7学习笔记上的 打算开发多人联机程序,对每个联机客户端,都会建立Client对象封装相关信息 1.Client.java public class Client { pri ...
- mac 下 apache设置
windows下面的apache配置 apache是mac下是默认就有的,我们只需使用命令开启.暂停和重启就好了 sudo apachectl start sudo apachectl stop su ...
- 函数fsp_get_space_header
/**********************************************************************//** Gets a pointer to the sp ...
- 文件大小转换成可显示的Mb,Gb和kb方法
public static String unitConversion(float resource) { String[] unit = new String[] { "B", ...