📄 freqcalculate.cpp
字号:
* 返回值:
* 无。
*
* 说明:
* 该函数用来实现一维快速离散余弦变换
*
************************************************************************/
void CFreqCalculate::DCT(double *f, double *F, int r)
{
// 循环变量
int i;
// 中间变量
double dTemp;
// 计算离散余弦变换点数
LONG N = 1<<r;
// 申请并分配内存
complex<double> *XIn;
complex<double> *XOut;
XIn = new complex<double>[N * 2];
XOut = new complex<double>[N * 2];
// 赋初值为0
memset(XIn, 0, sizeof(complex<double>) * N * 2);
memset(XOut, 0, sizeof(complex<double>) * N * 2);
// 将时域点写入数组X
for (i = 0; i < N; i++)
XIn[i] = complex<double>(*(f + i), 0);
// 调用快速付立叶变换
FFT(XIn, XOut, r + 1);
// 调整系数
dTemp = 1 / sqrt(N);
// 求F[0]
F[0] = XOut[0].real() * dTemp;
dTemp *= sqrt(2);
// 求F[u]
for (i = 1; i < N; i++)
*(F + i) = (XOut[i].real() * cos(i * PI / (N * 2)) + XOut[i].imag() * sin(i * PI / (N * 2))) * dTemp;
// 释放内存
delete[] XIn;
delete[] XOut;
}
/*************************************************************************
*
* 函数名称:
* IDCT()
*
* 参数:
* double * F - 指向频域值的指针
* double * f - 指向时域值的指针
* r -2的幂数
*
* 返回值:
* 无。
*
* 说明:
* 该函数实现一维快速离散余弦逆变换
*
************************************************************************/
void CFreqCalculate::IDCT(double *F, double *f, int r)
{
// 循环变量
int i;
// 中间变量
double dTemp, d0;
// 计算离散余弦变换点数
LONG N = 1<<r;
// 分配内存
complex<double> *XIn;
complex<double> *XOut;
XIn = new complex<double>[N * 2];
XOut = new complex<double>[N * 2];
// 赋初值为0
memset(XIn, 0, sizeof(complex<double>) * N * 2);
memset(XOut, 0, sizeof(complex<double>) * N * 2);
// 将频域变换后点写入数组X
for (i = 0; i < N; i++)
XIn[i] = complex<double>(F[i] * cos(i * PI / (N * 2)), F[i] * sin(i * PI / (N * 2)));
// 调用快速付立叶反变换
IFFT(XIn, XOut, r + 1);
// 调整系数
dTemp = sqrt(2.0 / N);
d0 = (sqrt(1.0 / N) - dTemp) * F[0];
// 计算f(x)
for (i = 0; i < N; i++)
f[i] = d0 + XOut[i].real()* dTemp * 2 * N;
// 释放内存
delete[] XIn;
delete[] XOut;
}
/*************************************************************************
*
* 函数名称:
* FreqDCT()
*
* 参数:
* double* f - 输入的时域序列
* double* F - 输出的频域序列
* LONG lWidth - 图象宽度
* LONG lHeight - 图象高度
*
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数进行二维快速离散余弦变换。
*
************************************************************************/
BOOL CFreqCalculate::FreqDCT(double *f, double *F, LONG lWidth, LONG lHeight)
{
// 循环变量
LONG i;
LONG j;
LONG k;
// 更改光标形状
BeginWaitCursor();
// 进行离散余弦变换的宽度和高度(2的整数次方)
LONG w = 1;
LONG h = 1;
int wp = 0;
int hp = 0;
// 计算进行离散余弦变换的宽度和高度(2的整数次方)
while (w < lWidth)
{
w *= 2;
wp++;
}
while (h < lHeight)
{
h *= 2;
hp++;
}
// 分配内存
double* TempIn = new double[h];
double* TempOut = new double[h];
// 对y方向进行离散余弦变换
for (i = 0; i < w * 3; i++)
{
// 抽取数据
for (j = 0; j < h; j++)
TempIn[j] = f[j * w * 3 + i];
// 一维快速离散余弦变换
DCT(TempIn, TempOut, hp);
// 保存变换结果
for (j = 0; j < h; j++)
f[j * w * 3 + i] = TempOut[j];
}
// 释放内存
delete TempIn;
delete TempOut;
// 分配内存
TempIn = new double[w];
TempOut = new double[w];
// 对x方向进行快速离散余弦变换
for (i = 0; i < h; i++)
{
for (k = 0; k < 3; k++)
{
// 抽取数据
for (j = 0; j < w; j++)
TempIn[j] = f[i * w * 3 + j * 3 + k];
// 一维快速离散余弦变换
DCT(TempIn, TempOut, wp);
// 保存变换结果
for (j = 0; j < w; j++)
F[i * w * 3 + j * 3 + k] = TempOut[j];
}
}
// 释放内存
delete TempIn;
delete TempOut;
return TRUE;
}
/*************************************************************************
*
* 函数名称:
* IFreqDCT()
*
* 参数:
* double* f - 输入的时域序列
* double* F - 输出的频域序列
* LONG lWidth - 图象宽度
* LONG lHeight - 图象高度
*
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数进行二维快速离散余弦逆变换。
*
************************************************************************/
BOOL CFreqCalculate::IFreqDCT(double *f, double *F, LONG lWidth, LONG lHeight)
{
// 循环变量
LONG i;
LONG j;
LONG k;
// 更改光标形状
BeginWaitCursor();
// 进行离散余弦变换的宽度和高度(2的整数次方)
LONG w = 1;
LONG h = 1;
int wp = 0;
int hp = 0;
// 计算进行付立叶变换的宽度和高度(2的整数次方)
while (w < lWidth)
{
w *= 2;
wp++;
}
while (h < lHeight)
{
h *= 2;
hp++;
}
// 计算图像每行的字节数
LONG lLineBytes = WIDTHBYTES(lWidth * 24);
// 分配内存
double* TempIn = new double[w];
double* TempOut = new double[w];
// 对x方向进行快速付立叶变换
for (i = 0; i < h; i++)
{
for (k = 0; k < 3; k++)
{
// 抽取数据
for (j = 0; j < w; j++)
TempIn[j] = F[i * w * 3 + j * 3 + k];
// 一维快速傅立叶变换
IDCT(TempIn, TempOut, wp);
// 保存变换结果
for (j = 0; j < w; j++)
F[i * w * 3 + j * 3 + k] = TempOut[j];
}
}
// 释放内存
delete TempIn;
delete TempOut;
TempIn = new double[h];
TempOut = new double[h];
// 对y方向进行快速付立叶变换
for (i = 0; i < w * 3; i++)
{
// 抽取数据
for (j = 0; j < h; j++)
TempIn[j] = F[j * w * 3 + i];
// 一维快速傅立叶变换
IDCT(TempIn, TempOut, hp);
// 保存变换结果
for (j = 0; j < h; j++)
F[j * w * 3 + i] = TempOut[j];
}
// 释放内存
delete TempIn;
delete TempOut;
for (i = 0; i < h; i++)
{
for (j = 0; j < w * 3; j++)
{
if (i < lHeight && j < lLineBytes)
*(f + i * lLineBytes + j) = F[i * w * 3 + j];
}
}
return TRUE;
}
/*************************************************************************
*
* 函数名称:
* DIBDCT()
*
* 参数:
* HDIB hDIB - 待处理的DIB
*
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数用来对图像进行离散余弦变换。
*
************************************************************************/
BOOL CFreqCalculate::DIBDCT(HDIB hDIB)
{
// 进行离散余弦变换的宽度和高度(2的整数次方)
LONG i;
LONG j;
// 指向DIB的指针
LPBYTE lpDIB;
// 指向DIB象素指针
LPBYTE lpDIBBits;
// 锁定DIB
lpDIB = (LPBYTE) ::GlobalLock((HGLOBAL) hDIB);
// 找到DIB图像象素起始位置
lpDIBBits = m_clsDIB.FindDIBBits(lpDIB);
// 判断是否是24-bpp位图
if (m_clsDIB.DIBBitCount(lpDIB) != 24)
{
// 提示用户
MessageBox("请先将其转换为24位色位图,再进行处理!", "系统提示" , MB_ICONINFORMATION | MB_OK);
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 返回
return FALSE;
}
// DIB的宽度
LONG lWidth = m_clsDIB.DIBWidth(lpDIB);
// DIB的高度
LONG lHeight = m_clsDIB.DIBHeight(lpDIB);
// 计算图像每行的字节数
LONG lLineBytes = WIDTHBYTES(lWidth * 24);
// 进行离散余弦变换的宽度和高度(2的整数次方)
LONG w = 1;
LONG h = 1;
int wp = 0;
int hp = 0;
// 计算进行离散余弦变换的宽度和高度(2的整数次方)
while (w < lWidth)
{
w *= 2;
wp++;
}
while (h < lHeight)
{
h *= 2;
hp++;
}
// 分配内存
double *f = new double[w * h * 3];
double *F = new double[w * h * 3];
// 向时域赋值并补零
for (i = 0; i < h; i++)
{
for (j = 0; j < w * 3; j++)
{
if (i < lHeight && j < lLineBytes)
f[i * w * 3 + j] = *(unsigned char*)(lpDIBBits + lLineBytes * i + j);
else
f[w * i * 3 + j] = 0.0f;
}
}
// 进行频谱分析
if (FreqDCT(f, F,lWidth, lHeight) == FALSE)
return FALSE;
// 更新所有象素
for (i = 0; i < lHeight; i++)
{
for (j = 0; j < lLineBytes; j++)
{
// 判断是否超过255
if (fabs(F[i * w * 3 + j]) > 255)
{
// 对于超过的,直接设置为255
*(unsigned char*)(lpDIBBits + lLineBytes * (lHeight - 1 - i) + j) = 255;
}
else
{
// 如果没有超过,则按实际计算结果赋值
*(unsigned char*)(lpDIBBits + lLineBytes * (lHeight - 1 - i) + j) = fabs(F[i * w * 3 + j]);
}
}
}
// 解除锁定
::GlobalUnlock(hDIB);
// 释放内存
delete []f;
delete[] F;
// 返回
return TRUE;
}
/*************************************************************************
*
* 函数名称:
* WALSH()
*
* 参数:
* double* f - 输入的时域序列
* double* F - 输出的频域序列
* int r - 2的幂数
*
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数进行一维快速沃尔什——哈达马变换。
*
************************************************************************/
void CFreqCalculate::WALSH(double *f, double *F, int r)
{
// 循环变量
LONG i;
LONG j;
LONG k;
// 中间变量
int p;
double* X;
// 计算快速沃尔什变换点数
LONG N = 1 << r;
// 分配运算所需的数组
double* X1 = new double[N];
double* X2 = new double[N];
// 将时域点写入数组X1
memcpy(X1, f, sizeof(double) * N);
// 蝶形运算
for (k = 0; k < r; k++)
{
for (j = 0; j < 1<<k; j++)
{
for (i = 0; i < 1<<(r - k - 1); i++)
{
p = j * (1<<(r - k));
X2[i + p] = X1[i + p] + X1[i + p + (int)(1<<(r - k - 1))];
X2[i + p + (int)(1<<(r - k - 1))] = X1[i + p] - X1[i + p + (int)(1<<(r - k - 1))];
}
}
// 互换X1和X2
X = X1;
X1 = X2;
X2 = X;
}
// 调整系数
for (j = 0; j < N; j++)
{
p = 0;
for (i = 0; i < r; i++)
{
if (j & (1<<i))
{
p += 1<<(r - i - 1);
}
}
F[j] = X1[p] / N;
}
// 释放内存
delete X1;
delete X2;
}
/*************************************************************************
*
* 函数名称:
* IWALSH()
*
* 参数:
* double* f - 输入的时域序列
* double* F - 输出的频域序列
* int r - 2的幂数
*
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数进行一维快速沃尔什——哈达马逆变换。
*
************************************************************************/
void CFreqCalculate::IWALSH(double *F, double *f, int r)
{
// 循环变量
int i;
// 计算变换点数
LONG N = 1 << r;
// 调用快速沃尔什-哈达玛变换进行反变换
WALSH(F, f, r);
// 调整系数
for (i = 0; i < N; i++)
f[i] *= N;
}
/*************************************************************************
*
* 函数名称:
* FreqWALSH()
*
* 参数:
* double* f - 输入的时域序列
* double* F - 输出的频域序列
* LONG lWidth - 图象宽度
* LONG lHeight - 图象高度
*
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数进行二维快速沃尔什——哈达玛变换。
*
************************************************************************/
BOOL CFreqCalculate::FreqWALSH(double *f, double *F, LONG lWidth, LONG lHeight)
{
// 循环变量
LONG i;
LONG j;
LONG k;
// 更改光标形状
BeginWaitCursor();
// 进行离散余弦变换的宽度和高度(2的整数次方)
LONG w = 1;
LONG h = 1;
int wp = 0;
int hp = 0;
// 计算进行离散余弦变换的宽度和高度(2的整数次方)
while (w < lWidth)
{
w *= 2;
wp++;
}
while (h < lHeight)
{
h *= 2;
hp++;
}
// 分配内存
double* TempIn = new double[h];
double* TempOut = new double[h];
// 对y方向进行离散余弦变换
for (i = 0; i < w * 3; i++)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -