⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 freqcalculate.cpp

📁 电子书《数字图像处理学》Visual C++实现 郎锐编写 所附源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
 * 返回值:
 *   无。
 *
 * 说明:
 *   该函数用来实现一维快速离散余弦变换
 *
 ************************************************************************/

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 + -