📄 fretrans.cpp
字号:
//图象的长宽大小
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 + -