IDWT改进C++代码

本文分享了在处理长音频文件时,使用小波变换遇到的效率问题及解决方案。通过对原始IDWT算法进行优化,成功将处理时间从半小时缩短到10秒。详细介绍了优化后的IDWT代码实现,对比了优化前后的运行效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

https://blog.youkuaiyun.com/ebowtang/article/details/40433861#comments

之前通过学习上面链接的博客时,在实践中发现用小波变换处理一个5分钟左右的音频半小时都运行不不出来。因为上链接博主做验证是用了8个点做实验,所以看不出运行时间的差异。

经过对代码的调试,发现其IDWT代码时间复杂度很高(实际上IDWT应与DWT复杂度相同,但由于他代码的写法,导致了时间复杂度都不是一个数量级)于是自己做了改进。

改进后运行一个5分左右的音频文件只需要10秒左右 。IDWT代码如下

注: 改进思路就是小波分解重构公式。就是上链接里的一些分析图。不得不说他的图做得很好,对我的理解有很大帮助!!

// 一维小波反变换,重构出源信号
void  CWavelet::IDWT(
    double *pSrcCoef,//源分解系数
    int dstLen,//重构出来的系数的长度
    double *pDstData//重构出来的系数
    )
{
    int p = 0;
    int caLen = (dstLen + m_dbFilter.filterLen - 1) / 2;
    int k=0,flag=1;//flag 标志位
      for (int i = 0; i < dstLen; i++)
        {
            pDstData[i] = 0.0;
            if(i%2==0 && i!=0) k++;
            if(flag==1){
                flag=0;
                for(int j=2,c=0;j>=0;j=j-2,c++){

                    pDstData[i]+=m_dbFilter.Lo_R[j] * pSrcCoef[k+c] + m_dbFilter.Hi_R[j] * pSrcCoef[k + c + caLen];
                }

            }else{
                flag=1;
                for(int j=3,c=0;j>=0;j=j-2,c++){
                     pDstData[i] += m_dbFilter.Lo_R[j] * pSrcCoef[k + c] + m_dbFilter.Hi_R[j] * pSrcCoef[k + c + caLen];
                }
            }
        }
}

由于JPEG2000是一种比较复杂的图像压缩算法,其实现需要大量的数学和计算机图形学知识,因此在这里无法给出完整的C++实现代码。不过,以下是一个基本的C++函数,可以用于将图像压缩成JPEG2000格式: ```c++ void compress_jpeg2000(unsigned char* input_data, int width, int height, int num_channels, int quality, const char* output_file) { // 将输入数据转换为OpenCV的Mat格式 cv::Mat input_image(height, width, CV_MAKETYPE(CV_8U, num_channels), input_data); // 将图像转换为YCbCr颜色空间 cv::Mat ycbcr_image; cv::cvtColor(input_image, ycbcr_image, cv::COLOR_BGR2YCrCb); // 对每个通道分别进行离散小波变换(DWT) std::vector<cv::Mat> dwt_channels; cv::split(ycbcr_image, dwt_channels); for (int i = 0; i < num_channels; i++) { cv::Mat coeffs; cv::dwt(dwt_channels[i], coeffs, cv::DWT_5X3); dwt_channels[i] = coeffs; } // 对每个DWT系数进行量化 for (int i = 0; i < num_channels; i++) { cv::Mat& coeffs = dwt_channels[i]; for (int j = 0; j < coeffs.rows; j++) { for (int k = 0; k < coeffs.cols; k++) { coeffs.at<float>(j, k) = round(coeffs.at<float>(j, k) / quality) * quality; } } } // 对每个通道分别进行反离散小波变换(IDWT) for (int i = 0; i < num_channels; i++) { cv::Mat& coeffs = dwt_channels[i]; cv::Mat output_coeffs; cv::idwt(coeffs, cv::Mat(), output_coeffs, cv::DWT_5X3); dwt_channels[i] = output_coeffs; } // 将图像转换回RGB颜色空间 cv::Mat output_image; cv::merge(dwt_channels, output_image); cv::cvtColor(output_image, output_image, cv::COLOR_YCrCb2BGR); // 将输出图像保存为JPEG2000格式 cv::imwrite(output_file, output_image, {cv::IMWRITE_JPEG2000_COMPRESSION_PARAMS, quality}); } ``` 这个函数的参数包括: - `input_data`:输入图像数据的指针,按照BGR格式排列。 - `width`和`height`:输入图像的宽度和高度。 - `num_channels`:输入图像的通道数,通常为3。 - `quality`:压缩质量,取值范围为0到100。 - `output_file`:输出压缩后的JPEG2000文件名。 该函数的实现使用了OpenCV库,需要在编译时链接OpenCV库。此外,该函数只是一个简单的JPEG2000压缩示例,实际的JPEG2000实现要比这个复杂得多。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值