📄 restore.cpp
字号:
// ************************************************************************
// 文件名:restore.cpp
//
// 图像复原API函数库:
//
// DIBNoRestriction() - 图像模糊
// DIBInverseFilter() - 图像逆滤波复原
// DIBNoiseDegeneration() - 图像模糊加噪
// DIBWinnerFilter() - 图像维纳滤波
// DIBMotionDegeneration() - 图像运动模糊
// DIBMotionRestore() - 图像运动模糊复原
//
// *************************************************************************
#include "stdafx.h"
#include "GlobalApi.h"
#include "Cdib.h"
#include <math.h>
#include <direct.h>
#include <complex>
using namespace std;
#define SWAP(a,b) tempr=(a);(a)=(b);(b)=tempr
/*************************************************************************
*
* 函数名称:
* DIBNoRestriction()
*
* 参数:
* CDib *pDib - 指向CDib类的指针
*
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数用来对DIB图像进行模糊操作。
*
************************************************************************/
BOOL WINAPI DIBNoRestriction(CDib *pDib)
{
// 指向源图像的指针
BYTE * lpSrc;
//图象的宽度和高度
LONG lWidth;
LONG lHeight;
// 图像每行的字节数
LONG lLineBytes;
//得到图象的宽度和高度
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;
//循环变量
long i;
long j;
//临时变量
double temp;
// 实际进行付立叶变换的宽度和高度
LONG lW = 1;
LONG lH = 1;
int wp = 0;
int hp = 0;
// 保证离散傅立叶变换的宽度和高度为2的整数次方
while(lW * 2 <= lLineBytes)
{
lW = lW * 2;
wp++;
}
while(lH * 2 <= lHeight)
{
lH = lH * 2;
hp++;
}
//用来存储源图象和变换核的时域数据
complex<double> *pCTSrc,*pCTH;
//用来存储源图象和变换核的频域数据
complex<double> *pCFSrc,*pCFH;
//图像归一化因子
double MaxNum;
//输入图象的长和宽必须为2的整数倍
if(lW != (int) lLineBytes)
{
return false;
}
if(lH != (int) lHeight)
{
return false;
}
// 为时域和频域的数组分配空间
pCTSrc = new complex<double> [lHeight*lLineBytes];
pCTH = new complex<double> [lHeight*lLineBytes];
pCFSrc = new complex<double> [lHeight*lLineBytes];
pCFH = new complex<double> [lHeight*lLineBytes];
// 将数据存入时域数组
for (j = 0; j < lHeight; j++)
{
for(i = 0; i < lLineBytes; i++)
{
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (unsigned char *)lpDIBBits + lLineBytes * j + i;
pCTSrc[ lLineBytes*j + i ] = complex<double>((double)*lpSrc , 0);
pCFSrc[ lLineBytes*j + i ] = complex<double>(0.0 , 0.0);
if(i < 5 && j < 5)
{
pCTH[ lLineBytes*j + i ] = complex<double>(0.04 , 0.0);
}
else
{
pCTH[ lLineBytes*j + i ] = complex<double>(0.0 , 0.0);
}
pCFH[ lLineBytes*j + i ] = complex<double>(0.0 , 0.0);
}
}
//对源图像进行FFT
::DIBFFT_2D(pCTSrc, lLineBytes, lHeight, pCFSrc);
//对变换核图像进行FFT
::DIBFFT_2D(pCTH, lLineBytes, lHeight, pCFH);
//频域相乘
for (i = 0;i <lHeight*lLineBytes;i++)
{
pCFSrc[i] = pCFSrc[i]*pCFH[i];
}
//对结果图像进行反FFT
IFFT_2D(pCFSrc, pCTSrc, lLineBytes, lHeight);
//确定归一化因子
MaxNum = 0.0;
for (j = 0;j < lHeight ;j++)
{
for(i = 0;i < lLineBytes ;i++)
{
temp = sqrt(pCTSrc[ lLineBytes*j + i ].real() * pCTSrc[ lLineBytes*j + i ].real()
+pCTSrc[lLineBytes*j + i ].imag() * pCTSrc[ lLineBytes*j +i].imag());
//选择归一化因子
if( MaxNum < temp)
MaxNum = temp;
}
}
//转换为图像
for (j = 0;j < lHeight ;j++)
{
for(i = 0;i < lLineBytes ;i++)
{
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (unsigned char *)lpDIBBits + lLineBytes * j + i;
*lpSrc = (unsigned char) (pCTSrc[(lLineBytes)*j + i].real()*255.0/MaxNum);
}
}
//释放存储空间
delete pCTSrc;
delete pCTH;
delete pCFSrc;
delete pCFH;
// 返回
return true;
}
/*************************************************************************
*
* 函数名称:
* DIBInverseFilter()
*
* 参数:
* CDib *pDib - 指向CDib类的指针
*
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE
*
* 说明:
* 该函数用来对DIBNoRestriction()生成的DIB图像进行复原操作。
*
************************************************************************/
BOOL WINAPI DIBInverseFilter (CDib *pDib)
{
// 指向源图像的指针
BYTE * lpSrc;
//图象的宽度和高度
LONG lWidth;
LONG lHeight;
// 图像每行的字节数
LONG lLineBytes;
//得到图象的宽度和高度
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;
//循环变量
long i;
long j;
//临时变量
double tempre, tempim, a, b, c, d;
// 实际进行付立叶变换的宽度和高度
LONG lW = 1;
LONG lH = 1;
int wp = 0;
int hp = 0;
// 保证离散傅立叶变换的宽度和高度为2的整数次方
while(lW * 2 <= lLineBytes)
{
lW = lW * 2;
wp++;
}
while(lH * 2 <= lHeight)
{
lH = lH * 2;
hp++;
}
//用来存储源图象和变换核的时域数据
complex<double> *pCTSrc,*pCTH;
//用来存储源图象和变换核的频域数据
complex<double> *pCFSrc,*pCFH;
//图像归一化因子
double MaxNum;
//输入退化图象的长和宽必须为2的整数倍
if(lW != (int) lLineBytes)
{
return false;
}
if(lH != (int) lHeight)
{
return false;
}
// 为时域和频域的数组分配空间
pCTSrc = new complex<double> [lHeight*lLineBytes];
pCTH = new complex<double> [lHeight*lLineBytes];
pCFSrc = new complex<double> [lHeight*lLineBytes];
pCFH = new complex<double> [lHeight*lLineBytes];
// 将退化图象数据存入时域数组
for (j = 0; j < lHeight; j++)
{
for(i = 0; i < lLineBytes; i++)
{
// 指向退化图像倒数第j行,第i个象素的指针
lpSrc = (unsigned char *)lpDIBBits + lLineBytes * j + i;
pCTSrc[ lLineBytes*j + i ] = complex<double>((double)*lpSrc , 0);
pCFSrc[ lLineBytes*j + i ] = complex<double>(0.0 , 0.0);
if(i < 5 && j < 5)
{
pCTH[ lLineBytes*j + i ] = complex<double>(0.04 , 0.0);
}
else
{
pCTH[ lLineBytes*j + i ] = complex<double>(0.0 , 0.0);
}
pCFH[ lLineBytes*j + i ] = complex<double>(0.0 , 0.0);
}
}
//对退化图像进行FFT
::DIBFFT_2D(pCTSrc, lLineBytes, lHeight, pCFSrc);
//对变换核图像进行FFT
::DIBFFT_2D(pCTH, lLineBytes, lHeight, pCFH);
//频域相除
for (i = 0;i <lHeight*lLineBytes;i++)
{
a = pCFSrc[i].real();
b = pCFSrc[i].imag();
c = pCFH[i].real();
d = pCFH[i].imag();
//如果频域值太小,不予考虑
if (c*c + d*d > 1e-3)
{
tempre = ( a*c + b*d ) / ( c*c + d*d );
tempim = ( b*c - a*d ) / ( c*c + d*d );
}
pCFSrc[i]= complex<double>(tempre , tempim);
}
//对复原图像进行反FFT
IFFT_2D(pCFSrc, pCTSrc, lLineBytes, lHeight);
//确定归一化因子
MaxNum=300;
//转换为复原图像
for (j = 0;j < lHeight ;j++)
{
for(i = 0;i < lLineBytes ;i++)
{
// 指向复原图像倒数第j行,第i个象素的指针
lpSrc = (unsigned char *)lpDIBBits + lLineBytes * j + i;
*lpSrc = (unsigned char) (pCTSrc[(lLineBytes)*j + i].real()*255.0/MaxNum);
}
}
//释放存储空间
delete pCTSrc;
delete pCTH;
delete pCFSrc;
delete pCFH;
// 返回
return true;
}
/*************************************************************************
*
* 函数名称:
* DIBNoiseDegeneration()
*
* 参数:
* CDib *pDib - 指向CDib类的指针
*
* 返回值:
* BOOL - 模糊加噪操作成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数用来对DIB图像进行模糊加噪操作。
*
************************************************************************/
BOOL WINAPI DIBNoiseDegeneration (CDib *pDib)
{
// 指向源图像的指针
BYTE * lpSrc;
//图象的宽度和高度
LONG lWidth;
LONG lHeight;
// 图像每行的字节数
LONG lLineBytes;
//得到图象的宽度和高度
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;
//循环变量
long i;
long j;
//转换为图像,加噪
unsigned char NoisePoint;
//临时变量
double temp;
//图像归一化因子
double MaxNum;
// 实际进行付立叶变换的宽度和高度
LONG lW = 1;
LONG lH = 1;
int wp = 0;
int hp = 0;
// 保证离散傅立叶变换的宽度和高度为2的整数次方
while(lW * 2 <= lLineBytes)
{
lW = lW * 2;
wp++;
}
while(lH * 2 <= lHeight)
{
lH = lH * 2;
hp++;
}
//用来存储源图象和变换核的时域数据
complex<double> *pCTSrc,*pCTH;
//用来存储源图象和变换核的频域数据
complex<double> *pCFSrc,*pCFH;
// 为时域和频域的数组分配空间
pCTSrc = new complex<double> [lHeight*lLineBytes];
pCTH = new complex<double> [lHeight*lLineBytes];
pCFSrc = new complex<double> [lHeight*lLineBytes];
pCFH = new complex<double> [lHeight*lLineBytes];
for (j = 0;j < lHeight ;j++)
{
for(i = 0;i < lLineBytes ;i++)
{
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (unsigned char *)lpDIBBits + lLineBytes * j + i;
// 将象素值存储到时域数组中
pCTSrc[ lLineBytes*j + i ] = complex<double>((double)*lpSrc , 0);
// 频域赋零值
pCFSrc[ lLineBytes*j + i ] = complex<double>(0.0 , 0.0);
// 用来对图象做退化的系统
if(i < 5 && j <5 )
{
pCTH[ lLineBytes*j + i ] = complex<double>(0.04 , 0.0);
}
else
{
pCTH[ lLineBytes*j + i ] = complex<double>(0.0 , 0.0);
}
// 频域赋零值
pCFH[ lLineBytes*j + i ] = complex<double>(0.0 , 0.0);
}
}
//对源图像进行FFT
::DIBFFT_2D(pCTSrc, lLineBytes, lHeight, pCFSrc);
//对变换核图像进行FFT
::DIBFFT_2D(pCTH, lLineBytes, lHeight, pCFH);
//频域相乘
for (i = 0;i <lHeight*lLineBytes;i++)
{
pCFSrc[i] = pCFSrc[i]*pCFH[i];
}
//对结果图像进行反FFT
IFFT_2D(pCFSrc, pCTSrc, lLineBytes, lHeight);
//确定归一化因子
MaxNum = 0.0;
for (j = 0;j < lHeight ;j++)
{
for(i = 0;i < lLineBytes ;i++)
{
temp = sqrt(pCTSrc[ lLineBytes*j + i ].real() * pCTSrc[ lLineBytes*j + i ].real()
+pCTSrc[lLineBytes*j + i ].imag() * pCTSrc[ lLineBytes*j +i].imag());
//选择归一化因子
if( MaxNum < temp)
MaxNum = temp;
}
}
//生成伪随机数种子
srand((unsigned)time(NULL));
//转换为图像,并加入伪随机噪声
for (j = 0;j < lHeight ;j++)
{
for(i = 0;i < lLineBytes ;i++)
{
// 产生的噪声
NoisePoint = rand()/2048-8;
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (unsigned char *)lpDIBBits + lLineBytes * j + i;
// 时域加噪,存储象素值
*lpSrc = (unsigned char) (pCTSrc[(lLineBytes)*j + i].real()*255.0/MaxNum + NoisePoint);
//如果象素值过大,直接赋值255
if(*lpSrc > 255)
*lpSrc = 255 ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -