函数DWT():完成任意层次的小波变换。
函数IDWT():完成任意层次的小波逆变换。
输入图像要求必须是单通道浮点图像,对图像大小也有要求(1层变换:w,h必须是2的倍数;2层变换:w,h必须是4的倍数;3层变换:w,h必须是8的倍数......),变换后的结果直接保存在输入图像中。
1、函数参数:图像指针pImage,变换层数nLayer。
2、一个函数直接完成多层次二维小波变换,尽量减少下标运算,避免不必要的函数调用,以提高执行效率。
3、变换过程中,使用了一个指针数组pData用于保存每行数据的起始位置,pRow和pColumn用于保存一行和一列临时数据,用于奇偶分离或合并,内存消耗较少。
代码:全选
上述代码只能对单通道进行变换,并且对图像位深和大小也有要求,还是不太好用。没关系,就这两个函数,可以对任意大小的彩色图像进行任意层次的小波变换,给段代码:
代码:全选
2、一个函数直接完成多层次二维小波变换,尽量减少下标运算,避免不必要的函数调用,以提高执行效率。
3、变换过程中,使用了一个指针数组pData用于保存每行数据的起始位置,pRow和pColumn用于保存一行和一列临时数据,用于奇偶分离或合并,内存消耗较少。
// 二维离散小波变换(单通道浮点图像)
void DWT(IplImage *pImage, int nLayer)
{
// 执行条件
if (pImage)
{
if (pImage->nChannels == 1 &&
pImage->depth == IPL_DEPTH_32F &&
((pImage->width >> nLayer) << nLayer) == pImage->width &&
((pImage->height >> nLayer) << nLayer) == pImage->height)
{
int i, x, y, n;
float fValue = 0;
float fRadius = sqrt(2.0f);
int nWidth = pImage->width;
int nHeight = pImage->height;
int nHalfW = nWidth / 2;
int nHalfH = nHeight / 2;
float **pData = new float*[pImage->height];
float *pRow = new float[pImage->width];
float *pColumn = new float[pImage->height];
for (i = 0; i < pImage->height; i++)
{
pData[i] = (float*) (pImage->imageData + pImage->widthStep * i);
}
// 多层小波变换
for (n = 0; n < nLayer; n++, nWidth /= 2, nHeight /= 2, nHalfW /= 2, nHalfH /= 2)
{
// 水平变换
for (y = 0; y < nHeight; y++)
{
// 奇偶分离
memcpy(pRow, pData[y], sizeof(float) * nWidth);
for (i = 0; i < nHalfW; i++)
{
x = i * 2;
pData[y][i] = pRow[x];
pData[y][nHalfW + i] = pRow[x + 1];
}
// 提升小波变换
for (i = 0; i < nHalfW - 1; i++)
{
fValue = (pData[y][i] + pData[y][i + 1]) / 2;
pData[y][nHalfW + i] -= fValue;
}
fValue = (pData[y][nHalfW - 1] + pData[y][nHalfW - 2]) / 2;
pData[y][nWidth - 1] -= fValue;
fValue = (pData[y][nHalfW] + pData[y][nHalfW + 1]) / 4;
pData[y][0] += fValue;
for (i = 1; i < nHalfW; i++)
{
fValue = (pData[y][nHalfW + i] + pData[y][nHalfW + i - 1]) / 4;
pData[y][i] += fValue;
}
// 频带系数
for (i = 0; i < nHalfW; i++)
{
pData[y][i] *= fRadius;
pData[y][nHalfW + i] /= fRadius;
}
}
// 垂直变换
for (x = 0; x < nWidth; x++)
{
// 奇偶分离
for (i = 0; i < nHalfH; i++)
{
y = i * 2;
pColumn[i] = pData[y][x];
pColumn[nHalfH + i] = pData[y + 1][x];
}
for (i = 0; i < nHeight; i++)
{
pData[i][x] = pColumn[i];
}
// 提升小波变换
for (i = 0; i < nHalfH - 1; i++)
{
fValue = (pData[i][x] + pData[i + 1][x]) / 2;
pData[nHalfH + i][x] -= fValue;
}
fValue = (pData[nHalfH - 1][x] + pData[nHalfH - 2][x]) / 2;
pData[nHeight - 1][x] -= fValue;
fValue = (pData[nHalfH][x] + pData[nHalfH + 1][x]) / 4;
pData[0][x] += fValue;
for (i = 1; i < nHalfH; i++)
{
fValue = (pData[nHalfH + i][x] + pData[nHalfH + i - 1][x]) / 4;
pData[i][x] += fValue;
}
// 频带系数
for (i = 0; i < nHalfH; i++)
{
pData[i][x] *= fRadius;
pData[nHalfH + i][x] /= fRadius;
}
}
}
delete[] pData;
delete[] pRow;
delete[] pColumn;
}
}
}
// 二维离散小波恢复(单通道浮点图像)
void IDWT(IplImage *pImage, int nLayer)
{
// 执行条件
if (pImage)
{
if (pImage->nChannels == 1 &&
pImage->depth == IPL_DEPTH_32F &&
((pImage->width >> nLayer) << nLayer) == pImage->width &&
((pImage->height >> nLayer) << nLayer) == pImage->height)
{
int i, x, y, n;
float fValue = 0;
float fRadius = sqrt(2.0f);
int nWidth = pImage->width >> (nLayer - 1);
int nHeight = pImage->height >> (nLayer - 1);
int nHalfW = nWidth / 2;
int nHalfH = nHeight / 2;
float **pData = new float*[pImage->height];
float *pRow = new float[pImage->width];
float *pColumn = new float[pImage->height];
for (i = 0; i < pImage->height; i++)
{
pData[i] = (float*) (pImage->imageData + pImage->widthStep * i);
}
// 多层小波恢复
for (n = 0; n < nLayer; n++, nWidth *= 2, nHeight *= 2, nHalfW *= 2, nHalfH *= 2)
{
// 垂直恢复
for (x = 0; x < nWidth; x++)
{
// 频带系数
for (i = 0; i < nHalfH; i++)
{
pData[i][x] /= fRadius;
pData[nHalfH + i][x] *= fRadius;
}
// 提升小波恢复
fValue = (pData[nHalfH][x] + pData[nHalfH + 1][x]) / 4;
pData[0][x] -= fValue;
for (i = 1; i < nHalfH; i++)
{
fValue = (pData[nHalfH + i][x] + pData[nHalfH + i - 1][x]) / 4;
pData[i][x] -= fValue;
}
for (i = 0; i < nHalfH - 1; i++)
{
fValue = (pData[i][x] + pData[i + 1][x]) / 2;
pData[nHalfH + i][x] += fValue;
}
fValue = (pData[nHalfH - 1][x] + pData[nHalfH - 2][x]) / 2;
pData[nHeight - 1][x] += fValue;
// 奇偶合并
for (i = 0; i < nHalfH; i++)
{
y = i * 2;
pColumn[y] = pData[i][x];
pColumn[y + 1] = pData[nHalfH + i][x];
}
for (i = 0; i < nHeight; i++)
{
pData[i][x] = pColumn[i];
}
}
// 水平恢复
for (y = 0; y < nHeight; y++)
{
// 频带系数
for (i = 0; i < nHalfW; i++)
{
pData[y][i] /= fRadius;
pData[y][nHalfW + i] *= fRadius;
}
// 提升小波恢复
fValue = (pData[y][nHalfW] + pData[y][nHalfW + 1]) / 4;
pData[y][0] -= fValue;
for (i = 1; i < nHalfW; i++)
{
fValue = (pData[y][nHalfW + i] + pData[y][nHalfW + i - 1]) / 4;
pData[y][i] -= fValue;
}
for (i = 0; i < nHalfW - 1; i++)
{
fValue = (pData[y][i] + pData[y][i + 1]) / 2;
pData[y][nHalfW + i] += fValue;
}
fValue = (pData[y][nHalfW - 1] + pData[y][nHalfW - 2]) / 2;
pData[y][nWidth - 1] += fValue;
// 奇偶合并
for (i = 0; i < nHalfW; i++)
{
x = i * 2;
pRow[x] = pData[y][i];
pRow[x + 1] = pData[y][nHalfW + i];
}
memcpy(pData[y], pRow, sizeof(float) * nWidth);
}
}
delete[] pData;
delete[] pRow;
delete[] pColumn;
}
}
}
上述代码只能对单通道进行变换,并且对图像位深和大小也有要求,还是不太好用。没关系,就这两个函数,可以对任意大小的彩色图像进行任意层次的小波变换,给段代码:
// 小波变换层数
int nLayer = 2;
// 输入彩色图像
IplImage *pSrc = cvLoadImage("Lena.jpg", CV_LOAD_IMAGE_COLOR);
// 计算小波图象大小
CvSize size = cvGetSize(pSrc);
if ((pSrc->width >> nLayer) << nLayer != pSrc->width)
{
size.width = ((pSrc->width >> nLayer) + 1) << nLayer;
}
if ((pSrc->height >> nLayer) << nLayer != pSrc->height)
{
size.height = ((pSrc->height >> nLayer) + 1) << nLayer;
}
// 创建小波图象
IplImage *pWavelet = cvCreateImage(size, IPL_DEPTH_32F, pSrc->nChannels);
if (pWavelet)
{
// 小波图象赋值
cvSetImageROI(pWavelet, cvRect(0, 0, pSrc->width, pSrc->height));
cvConvertScale(pSrc, pWavelet, 1, -128);
cvResetImageROI(pWavelet);
// 彩色图像小波变换
IplImage *pImage = cvCreateImage(cvGetSize(pWavelet), IPL_DEPTH_32F, 1);
if (pImage)
{
for (int i = 1; i <= pWavelet->nChannels; i++)
{
cvSetImageCOI(pWavelet, i);
cvCopy(pWavelet, pImage, NULL);
// 二维离散小波变换
DWT(pImage, nLayer);
// 二维离散小波恢复
// IDWT(pImage, nLayer);
cvCopy(pImage, pWavelet, NULL);
}
cvSetImageCOI(pWavelet, 0);
cvReleaseImage(&pImage);
}
// 小波变换图象
cvSetImageROI(pWavelet, cvRect(0, 0, pSrc->width, pSrc->height));
cvConvertScale(pWavelet, pSrc, 1, 128);
cvResetImageROI(pWavelet); // 本行代码有点多余,但有利用养成良好的编程习惯
cvReleaseImage(&pWavelet);
}
// 显示图像pSrc
// ...
cvReleaseImage(&pSrc);
相关推荐
快速小波变换 线性小波 带注释 opencv 源码
基于openCV的小波变换和逆变换,实现对输入图像的多层小波变换和逆变换重构,适用于图像处理、融合、识别等。
基于小波变换的图像融合 快速提升小波变换 基于opencv 源代码
opencv小波变换,基于哈尔函数的尺度向量和小波向量分别为:hf=[1/sqr2,1/sqr2],hs=[1/sqr2,1/sqr2]
基于opencv的图像小波变换 并实现图像融合和图像复原等功能
基于小波变换的图像融合与图像去噪,一定可以运行的,对学习小波的同学有帮助哦,安装opencv就可以啦。希望对大家有用。
基于opencv实现了对给定图像Gabor小波变换;尺度、方向、高斯窗口等参数可调
C++编程实现图像的小波变换去噪系统
基于多分辨率分析的图像分割技术是当前图像处理的重要内容, 提出了小波变换多分辨率分析方法与改进分水岭分割算法相结合的综合分割方法。此方法利用逐层影射和小波反变换可以得到高分辨率图像, 与在原始图像上直接...
基于小波变换和部分最小二乘的掌纹识别的分析和算法分析
基于小波变换的图像拼接,VC++版,可直接运行。
区域生长实现图像分割,小波变换对过分割的进行融合,OPENCV实现图像操作,在程序里的SHIYANWU里
人脸识别需要图像预处理,其中去除光照是最难的步骤,基于小波变换的图像处理能够有效地去除光照。
利用小波变换具有易于消除噪声、运算方便、能够体现图像特征等优点, 研究了基于 小波变换的目标识别方法。首先采用二次B 样条小波滤波器组对样本图像进行小波变换, 提取多 尺度边缘, 然后提取不变矩, 以此作为图像的...
基于openCV实现的图像小波变换和逆变换功能函数源代码,可以在你的工程项目中直接调用,适用于图像融合分析分类识别等计算机视觉领域。
介绍了一种新的基于小波变换的图像去噪算法。
VC++的MFC框架实现了多种小波变换,可以构造不同的小波基如Haar小波等,分解与重建,并在此基础上实现图像融合。
针对现有煤岩界面识别方法存在普适性差、可靠性差等问题,提出了一种基于图像多小波变换的煤岩界面识别方法。对煤岩图像进行多小波变换,提取不同频带多小波系数在固定窗口大小下的标准差作为纹理测度并生成归一化多...
基于OPENCV和MFC的图像处理程序,包括Canny边缘检测、尺寸任意大小缩放、任意角度旋转、傅里叶变换、小波变换等。
小波变换对车牌的识别,基于opencv3.该程序用了100张车牌图片进行统计了小波变换后车牌的均值和方差。