您的位置:首页 > 其它

图像处理 二维小波变换

2015-06-04 21:35 471 查看
编程环境:windows下结合opencv库

//二维图像小波变换
/*
nLayer:变换尺度
type:小波类型
*/
void ImageDWT(IplImage* src, IplImage* dst, int nLayer, char* type);


//通用的二维小波变换
/*
nLayer:小波变换的层数
type:选取的小波名称
可用为: "haar","db4","sym4"
使用Mallat算法,并利用傅里叶变换来快速执行卷积运算
src与dst深度均为IPL_DEPTH_8U
*/
void ImageDWT(IplImage* src, IplImage* dst, int nLayer, char* type)
{
if (!src || !dst)
{
return;
}
//判断src与dst的长度宽度是否为2的倍数
if (((dst->width >> nLayer) << nLayer != dst->width)
|| ((dst->height >> nLayer) << nLayer != dst->height)
|| (src->nChannels != 1)
|| (dst->nChannels != 1)
|| (nLayer <= 0))
{
return;
}

CvMat* pMatData = NULL;//用于保存计算过程中的向量
CvMat* pMatCA = NULL;
CvMat* pMatCD = NULL;
CvMat* pMatDst = cvCreateMat(dst->height, dst->width, CV_64FC1);//结果矩阵
CvMat tmp;
int nWidth = dst->width;
int nHeight = dst->height;
int nHalfW = nWidth / 2;
int nHalfH = nHeight / 2;
int i, x, y;
double* *pfDst = (double**)(malloc(sizeof(double*) * pMatDst->height));//pMatDst数据的起始地址
double* pfCA;//CA数据起始地址
double* pfCD;//CD数据起始地址
double* pfData;//Data数据起始地址

//保存图像数据每行的起始地址
for (y = 0; y < nHeight; y++)
{
pfDst[y] = (double*)(pMatDst->data.ptr + y * pMatDst->step);
}

//预先填充pMatDst
cvZero(pMatDst);
cvGetSubRect(pMatDst, &tmp, cvRect(0, 0, src->width, src->height));
cvScale(src, &tmp);

while (nLayer > 0)
{
//行变换
pMatData = cvCreateMat(1, nWidth, CV_64FC1);
pMatCA =  cvCreateMat(1, nHalfW, CV_64FC1);
pMatCD =  cvCreateMat(1, nHalfW, CV_64FC1);
y = 0;
for (y = 0; y < nHeight; y++)
{
pfCA = (double*)(pMatCA->data.ptr);
pfCD = (double*)(pMatCD->data.ptr);
pfData = (double*)(pMatData->data.ptr);
//获取每一行数据
for (i = 0; i < nWidth; i++)
{
pfData[i] = pfDst[y][i];
}
cvDWT(pMatData, pMatCA, pMatCD, type);//对每一行数据进行一维快速小波变换
//将小波变换结果拼接到一起并设置到pMatDst中
for (i = 0; i < nWidth; i++)
{
if (i < nHalfW)
{
pfDst[y][i] = pfCA[i];
}
else
{
pfDst[y][i] = pfCD[i - nHalfW];
}
}
}
cvReleaseMat(&pMatData);
cvReleaseMat(&pMatCA);
cvReleaseMat(&pMatCD);

//列变换
pMatData = cvCreateMat(1, nHeight, CV_64FC1);
pMatCA =  cvCreateMat(1, nHalfH, CV_64FC1);
pMatCD =  cvCreateMat(1, nHalfH, CV_64FC1);
y = 0;
for (x = 0; x < nWidth; x++)
{
pfCA = (double*)(pMatCA->data.ptr);
pfCD = (double*)(pMatCD->data.ptr);
pfData = (double*)(pMatData->data.ptr);
//获取每一列数据
for (i = 0; i < nHeight; i++)
{
pfData[i] = pfDst[i][x];
}
cvDWT(pMatData, pMatCA, pMatCD, type);//对每一列数据进行一维快速小波变换
//将小波变换结果拼接到一起并设置到dst中
for (i = 0; i < nHeight; i++)
{
if (i < nHalfH)
{
pfDst[i][x] = pfCA[i];
}
else
{
pfDst[i][x] = pfCD[i - nHalfH];
}
}
}
cvReleaseMat(&pMatData);
cvReleaseMat(&pMatCA);
cvReleaseMat(&pMatCD);

//一层变换后的宽度长度缩小
nWidth = nHalfW;
nHeight = nHalfH;
nHalfW = nHalfW / 2;
nHalfH = nHalfH / 2;
nLayer--;
}
//缩放以便显示
cvScale(pMatDst, dst);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: