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

📄 fretrans.cpp

📁 含《Visual c++数字图像处理典型算法及实现》这本书里所有源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	//图象的长宽大小
	CSize sizeImage		= pDib->GetDimensions();
	int nWidth			= sizeImage.cx		;
	int nHeight			= sizeImage.cy		;

	//图像在计算机在存储中的实际大小
	CSize sizeImageSave	= pDib->GetDibSaveDim();

	int nSaveWidth = sizeImageSave.cx;

	//图像数据的指针
	LPBYTE  pImageData = pDib->m_lpImage;


	// 正弦和余弦值
	double fCosTable;
	double fSinTable;
	fCosTable=0 ;
	fSinTable=0 ;

	// 临时变量
	double fTmpPxValue;
	double fRpartValue;
	double fIpartValue;
	fTmpPxValue=0;
	fRpartValue=0;
	fIpartValue=0;

	for(y=0; y<nHeight ; y++ )
		for(x=0 ; x<nWidth ; x++ )
		{
			fTmpPxValue=0;
			for(n=0; n<nHeight ; n++ )
				for(m=0 ; m<nWidth ; m++ )
				{
					// 生成正弦和余弦值
					fCosTable= 
						cos(	2*PI*( ((double)m*x)/nWidth + ((double)n*y)/nHeight) ) ;
					fSinTable= 
						sin(	2*PI*( ((double)m*x)/nWidth + ((double)n*y)/nHeight) ) ;

					// 傅立叶变化的实部与虚部
					fRpartValue=*(pTrRstRpart+ n*nHeight + m ) ;
					fIpartValue=*(pTrRstIpart+ n*nHeight + m ) ;
					
					// 加权相加
					fTmpPxValue+=fCosTable* fRpartValue-fSinTable*fIpartValue;
				}
			
			// 傅立叶系数变换对要求除以(nHeight*nWidth)
			fTmpPxValue=fTmpPxValue/(nHeight*nWidth);

			*( pImageData + nSaveWidth * y + x) = (unsigned char) fTmpPxValue ;
		}
}


/*************************************************************************
 *
 * 函数名称:
 *   DIBWalsh()
 *
 * 参数:
 *   CDib  *pDib       - 指向CDib类的指针
 *
 * 返回值:
 *   BOOL               - 成功返回TRUE,否则返回FALSE。
 *
 * 说明:
 *   该函数用来对图像进行二维快速沃尔什-哈达玛变换。
 *
 ***********************************************************************
 */

BOOL WINAPI DIBWalsh(CDib * pDib)
{
	// 指向源图像的指针
	unsigned char *lpSrc;		
	
	//图象的宽度和高度
	LONG    lWidth;
	LONG    lHeight;

	// 循环变量
	LONG	i;
	LONG	j;
	
	// 实际进行付立叶变换的宽度和高度
	LONG	lW = 1;
	LONG	lH = 1;
	
	int		wp = 0;
	int		hp = 0;
	
	// 中间变量
	double	dTemp;	

	//得到图象的宽度和高度
	CSize   SizeDim;
	SizeDim = pDib->GetDimensions();
	lWidth = SizeDim.cx;
	lHeight = SizeDim.cy;	
	
	//得到实际的图象存储大小
	CSize   SizeRealDim;
	SizeRealDim = pDib->GetDibSaveDim();

	// 图像每行的字节数
	LONG	lLineBytes;
	
	// 计算图像每行的字节数
	lLineBytes = SizeRealDim.cx;

	//图像数据的指针
	LPBYTE  lpDIBBits = pDib->m_lpImage;
		
	// 保证离散余弦变换的宽度和高度为2的整数次方
	while(lW * 2 <= lWidth)
	{
		lW = lW * 2;
		wp++;
	}
	
	while(lH * 2 <= lHeight)
	{
		lH = lH * 2;
		hp++;
	}
	
	// 分配内存
	double *dpf = new double[lW * lH];
	double *dpF = new double[lW * lH];
	
	// 时域赋值
	for(i = 0; i < lH; i++)
	{
		// 列
		for(j = 0; j < lW; j++)
		{
			// 指向DIBi行j列象素的指针
			lpSrc = lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
			
			// 将象素值赋值给时域数组
			dpf[j + i * lW] = *(lpSrc);
		}
	}
	
	for(i = 0; i < lH; i++)
		// 对y方向进行沃尔什-哈达玛变换
		WALSH(dpf + lW * i, dpF + lW * i, wp);
		
	// 保存计算结果
	for(i = 0; i < lH; i++)
	{
		for(j = 0; j < lW; j++)
		{
			dpf[j * lH + i] = dpF[j + lW * i];
		}
	}
	
	for(j = 0; j < lW; j++)
		// 对x方向进行沃尔什-哈达玛变换
		WALSH(dpf + j * lH, dpF + j * lH, hp);
	
	// 行
	for(i = 0; i < lH; i++)
	{
		// 列
		for(j = 0; j < lW; j++)
		{
			// 计算频谱
			dTemp = fabs(dpF[j * lH + i] * 1000);
			
			if (dTemp > 255)
			{
				// 超过255直接设置为255
				dTemp = 255;
			}
			
			// 指向DIBi行j列象素的指针
			lpSrc = lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
			
			// 更新源图像
			* (lpSrc) = (BYTE)(dTemp);
		}
	}
	
	//释放内存
	delete dpf;
	delete dpF;

	// 返回
	return TRUE;
}



/*************************************************************************
 *
 * 函数名称:
 *   DIBDct()
 *
 * 参数:
 *   CDib  *pDib       - 指向CDib类的指针
 *
 * 返回值:
 *   BOOL               - 成功返回TRUE,否则返回FALSE。
 *
 * 说明:
 *   该函数用来对图像进行二维离散余弦变换。
 *
 ***********************************************************************
 */
BOOL WINAPI DIBDct(CDib *pDib)
{
	
	// 指向源图像的指针
	unsigned char*	lpSrc;
	
	//图象的宽度和高度
	LONG    lWidth;
	LONG    lHeight;

	// 循环变量
	LONG	i;
	LONG	j;
	
	// 离散余弦变换的宽度和高度,必须为2的整数次方
	LONG	lW = 1;
	LONG	lH = 1;
	
	int		wp = 0;
	int		hp = 0;
	
	// 中间变量
	double	dTemp;

	//得到图象的宽度和高度
	CSize   SizeDim;
	SizeDim = pDib->GetDimensions();
	lWidth = SizeDim.cx;
	lHeight = SizeDim.cy;

	// 图像每行的字节数
	LONG	lLineBytes;
	
	//得到实际的Dib图象存储大小
	CSize   SizeRealDim;
	SizeRealDim = pDib->GetDibSaveDim();

	// 计算图像每行的字节数
	lLineBytes = SizeRealDim.cx;

   //图像数据的指针
	LPBYTE  lpDIBBits = pDib->m_lpImage;	
		
	// 保证离散余弦变换的宽度和高度为2的整数次方
	while(lW * 2 <= lWidth)
	{
		lW = lW * 2;
		wp++;
	}
	
	while(lH * 2 <= lHeight)
	{
		lH = lH * 2;
		hp++;
	}
	
	// 分配内存
	double *dpf = new double[lW * lH];
	double *dpF = new double[lW * lH];
	
	// 时域赋值
	for(i = 0; i < lH; i++)
	{
		for(j = 0; j < lW; j++)
		{
			// 指针指向位图i行j列的象素
			lpSrc = lpDIBBits + lLineBytes * ( i) + j;
//			lpSrc = lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
			// 将象素值赋给时域数组
			dpf[j + i * lW] = *(lpSrc);
		}
	}
	
	for(i = 0; i < lH; i++)
		// y方向进行离散余弦变换
		DCT(&dpf[lW * i], &dpF[lW * i], wp);

	// 保存计算结果
	for(i = 0; i < lH; i++)
		for(j = 0; j < lW; j++)
			dpf[j * lH + i] = dpF[j + lW * i];
		
	
	for(j = 0; j < lW; j++)
		// x方向进行离散余弦变换
		DCT(&dpf[j * lH], &dpF[j * lH], hp);
	
	// 频谱的计算
	for(i = 0; i < lH; i++)
	{
		for(j = 0; j < lW; j++)
		{
			dTemp = fabs(dpF[j*lH+i]);
			
			// 是否超过255
			if (dTemp > 255)
				// 如果超过,设置为255
				dTemp = 255;
		
			// 指针指向位图i行j列的象素
			lpSrc = lpDIBBits + lLineBytes * ( i) + j;
//			lpSrc = lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
			
			// 更新源图像
			* (lpSrc) = (BYTE)(dTemp);
		}
	}
	
	// 释放内存
	delete dpf;
	delete dpF;

	// 返回
	return TRUE;
}


/*************************************************************************
 *
 * 函数名称:
 *   DIBOHOTELLING()
 *
 * 参数:
 *   CDib  *pDib       - 指向CDib类的指针
 *
 * 返回值:
 *   BOOL               - 成功返回TRUE,否则返回FALSE。
 *
 * 说明:
 *   该函数用霍特林变换来对图像进行旋转。
 *
 ***********************************************************************
 */

BOOL WINAPI DIBHOTELLING(CDib *pDib)
{
	
	// 指向源图像的指针
	unsigned char*	 lpSrc;

	// 循环变量
	LONG	i;
	LONG	j;
	
	//图象的宽度和高度
	LONG    lWidth;
	LONG    lHeight;

	// 图像每行的字节数
	LONG	lLineBytes;

	// 经过变换后图象最大可能范围
	LONG    lMaxRange;
	
	//  物体坐标的均值
    LONG    AverEx;
	LONG    AverEy;
	
	//  物体总的象素数
	LONG    ToaCount;

	// 坐标值的协方差矩阵
	double  Matr4C[2][2];

	// 存放协方差矩阵的特征向量
	double  QMatrix[2][2];
	
	//  三对角阵的主对角和次对角线元素
	double  MainCross[2];
	double  HypoCross[2];
	
	// 中间变量
	double	dTemp;
	LONG    lTempI;
	LONG    lTempJ;
		
	//得到图象的宽度和高度
	CSize   SizeDim;
	SizeDim = pDib->GetDimensions();
	lWidth = SizeDim.cx;
	lHeight = SizeDim.cy;	
	
	//得到实际的Dib图象存储大小
	CSize   SizeRealDim;
	SizeRealDim = pDib->GetDibSaveDim();

	// 计算图像每行的字节数
	lLineBytes = SizeRealDim.cx;

   //图像数据的指针
	LPBYTE  lpDIBBits = pDib->m_lpImage;	
			
	// 估计图象经过旋转后可能最大的宽度和高度
	if(lWidth>lHeight)
		lMaxRange = lWidth;
	else
		lMaxRange =lHeight;
	
	// 赋初值
	AverEx=0.0;
	AverEy=0.0;
	ToaCount = 0;
	Matr4C[0][0] = Matr4C[0][1] = Matr4C[1][0] = Matr4C[1][1] = 0.0;
	
	// 分配内存
	double *F = new double[lWidth*lHeight];
	
	// 行
	for(i = 0; i < lHeight; i++)
	{
		// 列
		for(j = 0; j < lWidth; j++)
		{
			// 给旋转后坐标轴的每个点赋零值(灰度值255对应显示白色)
			F[i*lWidth + j] = 255;

			// 指向位图i行j列象素的指针
			lpSrc = lpDIBBits + lLineBytes*i + j;
						
			// 值小于255(非背景色白色)的象素认为物体的一部分
			// 并将其坐标值x和y看作二维随机矢量
			if((*lpSrc) < 255)
			{				
				// 属于物体象素的Y坐标和X坐标累计值
				AverEx=AverEx+i;
				AverEy=AverEy+j;

				// 物体总的象素数加一
				ToaCount++;
                   
                // 随机矢量协方差矩阵的累计值
				Matr4C[0][0] = Matr4C[0][0] + i*i;
                Matr4C[0][1] = Matr4C[0][1] + i*j;
				Matr4C[1][0] = Matr4C[1][0] + j*i;
				Matr4C[1][1] = Matr4C[1][1] + j*j;
			}
		}
	}
	
	
	// 计算随机矢量的均值
	AverEx = AverEx/ToaCount;
	AverEy = AverEy/ToaCount;

	//  计算随机矢量的协方差矩阵
    Matr4C[0][0] = Matr4C[0][0]/ToaCount - AverEx*AverEx;
	Matr4C[0][1] = Matr4C[0][1]/ToaCount - AverEx*AverEy;
	Matr4C[1][0] = Matr4C[1][0]/ToaCount - AverEx*AverEy;
	Matr4C[1][1] = Matr4C[1][1]/ToaCount - AverEy*AverEy;

    // 规定迭代的计算精度
	double Eps = 0.000001;
	
	// 将协方差矩阵化作三对角对称阵
    THREECROSS(*Matr4C, 2, *QMatrix, MainCross, HypoCross);
	
	// 求协方差矩阵的特征值和特征矢向量
	BSTQ(2, MainCross,HypoCross, *Matr4C, Eps, 50);
    
	// 将特征列向量转化称特征列向量
    dTemp = Matr4C[0][1];
	Matr4C[0][1] = Matr4C[1][0];
	Matr4C[1][0] = dTemp;

	// 对特征列向量进行归一化
	for(i=0;i<=1;i++)
	{
		dTemp = pow(Matr4C[i][0],2) + pow(Matr4C[i][1],2);
		dTemp = sqrt(dTemp);
		Matr4C[i][0] = Matr4C[i][0]/dTemp;
		Matr4C[i][1] = Matr4C[i][1]/dTemp;
	}
	
	// 查找经霍特林变换后的坐标点在原坐标系中的坐标    
    for(i = -lMaxRange+1; i < lMaxRange; i++)
	{
		for(j = -lMaxRange+1; j < lMaxRange; j++)
		{
			//  将新坐标值映射到旧的坐标系
			int Cx = (int)(i*Matr4C[0][0]-j*Matr4C[0][1])+AverEx;
			int Cy = (int)(-i*Matr4C[1][0]+j*Matr4C[1][1])+AverEy;
			
			//  映射值是否属于源图象
			if( Cx>=0 && Cx<lHeight && Cy>=0 && Cy<lWidth )
			{
				lpSrc = lpDIBBits + lLineBytes*Cx + Cy;

				// 映射值是否属于原来的物体
				if(*(lpSrc)<255)
				{
					//  将新坐标系原点平移到中心,以便显示
					lTempI=(LONG)(lHeight/2)+j;
					lTempJ=(LONG)(lWidth/2)+i;

					// 看如果能够进行显示,赋值给数组,进行存储
					if( lTempI>=0 && lTempI<lHeight && lTempJ>=0 && lTempJ<lWidth )
						F[lTempJ+ (lTempI) * lWidth]=*(lpSrc);
				}

			}		
		}
	}
	
	// 行
	for(i = 0; i < lMaxRange; i++)
	{
		// 列
		for(j = 0; j < lMaxRange; j++)
		{
			// 霍特林变换后的象素值
		    dTemp = F[i * lMaxRange + j] ;
			
			// 指向位图i行j列象素的指针
			lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
			
			// 更新源图像
			* (lpSrc) = (BYTE)(dTemp);
		}
	}
	
	// 释放内存
	delete F;

	// 返回
	return TRUE;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -