`

基于opencv的小波变换

 
阅读更多

函数DWT():完成任意层次的小波变换。

函数IDWT():完成任意层次的小波逆变换。

输入图像要求必须是单通道浮点图像,对图像大小也有要求(1层变换:w,h必须是2的倍数;2层变换:w,h必须是4的倍数;3层变换:w,h必须是8的倍数......),变换后的结果直接保存在输入图像中。

1、函数参数:图像指针pImage,变换层数nLayer。
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带注释

    总结来说,这个基于OpenCV的快速小波变换实例涵盖了小波理论的基础知识,包括二代小波、快速小波变换的原理和实现,以及如何利用这些工具进行图像处理。源码注释为学习者提供了深入理解小波变换在实际项目中如何应用...

    VC++实现小波变换图像融合,基于小波变换的图像处理,C,C++

    在基于小波变换的图像融合中,首先对每个源图像进行小波分解,得到不同尺度和方向的细节信息。然后,根据一定的融合规则(如加权平均、最大值选择等)对这些细节信息进行组合。最后,通过逆小波变换恢复出融合后的...

    opencv小波变换

    opencv小波变换,基于哈尔函数的尺度向量和小波向量分别为:hf=[1/sqr2,1/sqr2],hs=[1/sqr2,1/sqr2]

    openCV 上的小波变换

    这些函数基于离散小波变换(Discrete Wavelet Transform, DWT)实现,允许用户对二维图像进行小波分解和重构。 1. `dwt2`函数:该函数用于执行二维离散小波变换。它接受输入图像和两个小波滤波器(低通滤波器和高通...

    基于小波变换的图像融合与图像去噪

    总的来说,基于小波变换的图像融合与去噪是图像处理中的重要技术,能够提升图像质量和分析效果。通过学习和运用这种技术,不仅可以增强对图像处理的理解,还能为科研和工程应用提供有力工具。而这个项目提供了一个...

    基于小波变换的快速图像融合

    ### 基于小波变换的快速图像融合技术解析 #### 一、引言 在图像处理领域,图像融合技术是一种将多幅图像合并成一幅更高质量图像的技术,旨在提高图像的信息量和清晰度。小波变换作为一种有效的信号处理方法,在...

    C++编程实现图像的小波变换去噪系统

    在图像处理领域,小波变换(Wavelet Transform)是一种强大的工具,尤其在图像去噪方面表现出色。小波变换能够将图像数据从空间域转换到频域,通过分析不同频率的成分来识别并去除噪声,同时保留图像的主要特征。本...

    c#小波变换算法c#小波变换算法

    - **Emgu CV**:基于OpenCV的.NET库,也提供了小波变换的功能。 - **自定义实现**:可以使用C#编写自己的小波变换算法,例如基于滤波器组的离散小波变换算法。 4. **`Filter.cs`文件可能包含的内容**: - **...

    OpenCV3 小波变换

    在OpenCV3中,小波变换主要通过`cv::dwt`函数实现,它基于离散小波变换(Discrete Wavelet Transform, DWT)。DWT将原始图像分解为不同频段的细节和低频信息,这些频段分别对应于图像的不同特征。小波变换的核心是...

    C++实现的图像小波变换_滤波_复原

    本项目是基于C++实现的图像小波变换、滤波以及图像恢复技术,旨在提供一个实用的图像处理解决方案。 小波变换(Wavelet Transform)是一种数学方法,它将图像信号分解成一系列不同尺度和位置的小波函数,这些小波...

    Opencv实现Gabor小波变换

    基于opencv实现了对给定图像Gabor小波变换;尺度、方向、高斯窗口等参数可调

    基于小波变换和部分最小二乘的掌纹识别

    ### 基于小波变换和部分最小二乘的掌纹识别 #### 一、引言 随着科技的发展,生物特征识别技术因其独特的优势而受到广泛关注,并已成为国际研究的热点领域之一。生物特征识别技术利用人体固有的生理或行为特征来...

    区域生长,小波变换,OPENCV

    在这个模块中,开发者可能会编写一系列的测试用例,以验证区域生长、小波变换和OpenCV的集成效果,检查算法的正确性和效率。测试用例通常包括各种边界情况和典型输入,确保算法在各种场景下都能稳定工作。 总的来说...

    VC++实现了基于图像小波变换的图像融合MFC

    在本文中,我们将深入探讨如何使用VC++的MFC(Microsoft Foundation Classes)框架来实现基于图像小波变换的图像融合技术。MFC是C++的一个类库,它为开发Windows应用程序提供了一种结构化的方式,使得程序员能够更...

    基于小波变换的图像分割研究

    基于多分辨率分析的图像分割技术是当前图像处理的重要内容, 提出了小波变换多分辨率分析方法与改进分水岭分割算法相结合的综合分割方法。此方法利用逐层影射和小波反变换可以得到高分辨率图像, 与在原始图像上直接...

    xiaobobianhuan.rar_C++小波变换_图像 小波变换_图像小波变换_小波_小波变换图像

    连续小波变换允许任意时刻的局部分析,而离散小波变换则更适合于计算机处理,因为它基于离散的数据和算法。 1. 连续小波变换:连续小波变换是通过将基本小波函数与信号在所有时间尺度和位置上进行卷积来实现的。...

    基于小波变换的图像拼接

    基于小波变换的图像拼接方法是其中一种常用且高效的技术手段,尤其适用于处理具有重叠区域的图像。 小波变换是一种信号分析工具,它可以将图像在时域和频域上同时进行分析,提供多分辨率的图像表示。在图像拼接中,...

    VC++实现图像的小波变换处理

    本文将深入探讨如何利用VC++编程语言实现小波变换,包括连续小波变换(Continuous Wavelet Transform, CWT)和离散小波变换(Discrete Wavelet Transform, DWT),以及基于小波变换的图像滤波处理。 **小波变换基础...

    小波变换VC6.0代码

    小波变换基于小波基函数,常见的有Haar小波、Daubechies小波、Morlet小波等。这些函数具有有限支撑、可缩放和可平移的特性,使其能适应各种复杂信号的表示。 3. **二维小波变换**: 在图像处理中,通常使用二维...

Global site tag (gtag.js) - Google Analytics