wavelib库 图像处理

article/2025/6/13 22:45:37

1. Wavelib图像处理核心功能

Wavelib虽主要针对1D信号,但可通过分通道处理实现图像操作:

  • 多级小波分解(DWT):提取低频(近似)和高频(细节)成分

  • 图像去噪:阈值处理高频系数

  • 边缘检测:增强水平/垂直细节分量

  • 压缩:保留显著系数,舍弃微小值

2. 图像处理步骤(以灰度图为例)

(1) 安装依赖

确保已正确编译Wavelib(参考前文),并安装OpenCV用于图像读写:

bash

pip install opencv-python  # Python接口(测试用)

或通过C++直接使用OpenCV:

cpp

#include <opencv2/opencv.hpp>
(2) 图像小波变换流程

3. C++代码示例

(1) 图像DWT/IDWT(2D分解)

cpp

#include "wavelib.h"
#include <opencv2/opencv.hpp>
#include <cstring>void image_dwt_denoise(cv::Mat& img, const char* wname, int levels) {// 1. 转换为双精度浮点cv::Mat img_f;img.convertTo(img_f, CV_64F);// 2. 初始化小波对象wave_object wave = wave_init(wname);if (!wave) {fprintf(stderr, "Wavelet initialization failed\n");return;}// 3. 初始化二维小波变换对象wt2_object wt = wt2_init(wave, "dwt", img.rows, img.cols, levels);if (!wt) {fprintf(stderr, "WT2 object initialization failed\n");wave_free(wave);return;}// 4. 配置参数(关键修改点)setDWT2Extension(wt, "sym");strcpy(wt->cmethod, "fft");  // 直接设置卷积方法// 5. 执行2D DWT分解double* coeffs = dwt2(wt, (double*)img_f.data);// 6. 系数处理(示例:软阈值去噪)int total_coeffs = img.rows * img.cols;double noise_sd = 0.0;for (int i = total_coeffs/4; i < total_coeffs/2; i++) { // 估算HH1子带噪声noise_sd += fabs(coeffs[i]);}noise_sd = (noise_sd / (total_coeffs/4)) / 0.6745;double threshold = noise_sd * sqrt(2 * log(total_coeffs));for (int i = 0; i < total_coeffs; i++) {if (fabs(coeffs[i]) < threshold) {coeffs[i] = 0.0;}}// 7. 执行2D IDWT重构double* reconstructed = (double*)malloc(total_coeffs * sizeof(double));idwt2(wt, coeffs, reconstructed);// 8. 转换回图像cv::Mat result(img.rows, img.cols, CV_64F, reconstructed);result.convertTo(img, img.type());// 9. 释放资源free(reconstructed);wt2_free(wt);wave_free(wave);
}int main() {cv::Mat img = cv::imread("input.jpg", cv::IMREAD_GRAYSCALE);if (img.empty()) {fprintf(stderr, "Failed to load image\n");return -1;}image_dwt_denoise(img, "db4", 2);cv::imwrite("denoised.jpg", img);return 0;
}
(2) 边缘增强

cpp

void edge_enhance(cv::Mat& img, float factor) {// ...(DWT后)// 增强水平/垂直细节分量(假设coeffs布局为LL, LH, HL, HH)int detail_start = lengths[0]; // 低频分量后的位置for (int i = detail_start; i < rows*cols; i++) {coeffs[i] *= factor; // 放大高频}// ...(IDWT重构)
}
(3)完整的Wavelib图像处理示例

包含图像加载、多级小波分解、阈值去噪、重构保存全流程.

#include "wavelib.h"
#include <opencv2/opencv.hpp>
#include <vector>
#include <cstring>
#include <cmath>// 验证输入参数
void validate_parameters(const double* coeffs, int rows, int cols, int levels) {if (!coeffs || rows <= 0 || cols <= 0 || levels <= 0) {throw std::invalid_argument("Invalid parameters");}int min_dim = std::min(rows, cols);int max_levels = static_cast<int>(std::log2(min_dim));if (levels > max_levels) {levels = max_levels;}size_t required_size = 0;for (int l = 1; l <= levels; ++l) {int sub_size = (rows >> l) * (cols >> l);required_size += (l == levels) ? 4 * sub_size : 3 * sub_size;}if (required_size > static_cast<size_t>(rows * cols)) {throw std::invalid_argument("Insufficient coefficients array size");}
}// 归一化并复制子带
void normalize_and_copy(const cv::Mat& src, cv::Mat& dst, cv::Rect roi) {cv::Mat norm;cv::normalize(src, norm, 0, 255, cv::NORM_MINMAX, CV_8UC1);norm.copyTo(dst(roi));
}void visualize_subbands(const double* coeffs, int rows, int cols, int levels,const std::string& output_path = "d:/subbands.jpg") {try {// 1. 参数校验validate_parameters(coeffs, rows, cols, levels);// 2. 计算最小可用尺寸int min_dim = std::min(rows, cols);int max_levels = static_cast<int>(std::log2(min_dim));levels = std::min(levels, max_levels);// 3. 创建显示画布(固定为原始尺寸)cv::Mat canvas(rows, cols, CV_8UC1, cv::Scalar(0));// 4. 系数偏移指针const double* ptr = coeffs;// 5. 处理LL频带(最深层)int ll_size = rows >> levels;cv::Mat ll(ll_size, ll_size, CV_64F, const_cast<double*>(ptr));ptr += ll_size * ll_size;normalize_and_copy(ll, canvas, cv::Rect(0, 0, ll_size, ll_size));// 6. 处理各层细节子带for (int l = levels; l >= 1; --l) {int band_size = rows >> l;  // 当前层子带尺寸int ll_pos = rows >> (l + 1); // 下一级LL位置(未使用)// LH (水平细节) - 右上cv::Mat lh(band_size, band_size, CV_64F, const_cast<double*>(ptr));ptr += band_size * band_size;normalize_and_copy(lh, canvas, cv::Rect(band_size, 0, band_size, band_size));// HL (垂直细节) - 左下cv::Mat hl(band_size, band_size, CV_64F, const_cast<double*>(ptr));ptr += band_size * band_size;normalize_and_copy(hl, canvas, cv::Rect(0, band_size, band_size, band_size));// HH (对角细节) - 右下cv::Mat hh(band_size, band_size, CV_64F, const_cast<double*>(ptr));ptr += band_size * band_size;normalize_and_copy(hh, canvas, cv::Rect(band_size, band_size, band_size, band_size));}// 7. 保存结果if (!cv::imwrite(output_path, canvas)) {throw std::runtime_error("Failed to save: " + output_path);}} catch (const std::exception& e) {std::cerr << "Error: " << e.what() << std::endl;}
}// 图像小波变换处理主函数
void wavelet_image_processing(cv::Mat& img, const char* wname, int levels,bool denoise=true, bool visualize=false) {// 1. 参数校验if (img.empty() || levels <= 0) {fprintf(stderr, "Invalid parameters\n");return;}// 2. 转换为双精度浮点cv::Mat img_f;img.convertTo(img_f, CV_64F);// 3. 初始化小波对象wave_object wave = wave_init(wname);if (!wave) {fprintf(stderr, "Wavelet initialization failed for %s\n", wname);return;}// 4. 检查最大可用分解层数int max_level = (int)(log2(std::min(img.rows, img.cols) / log2(2)));levels = std::min(levels, max_level);printf("Using %d decomposition levels\n", levels);// 5. 初始化二维小波变换对象wt2_object wt = wt2_init(wave, "dwt", img.rows, img.cols, levels);if (!wt) {fprintf(stderr, "WT2 object initialization failed\n");wave_free(wave);return;}setDWT2Extension(wt, "sym");  // 对称延拓//strcpy(wt->method, "fft");  // 直接设置卷积方法// 6. 执行2D DWT分解double* dwt_coeffs = dwt2(wt, (double*)img_f.data);// 7. 可视化子带(调试用)if (visualize) {visualize_subbands(dwt_coeffs, img.rows, img.cols, levels, "d:/1111.png");}// 8. 系数处理(去噪)if (denoise) {// 估计噪声标准差(使用HH1子带)int hh1_size = (img.rows >> 1) * (img.cols >> 1);double* HH1 = dwt_coeffs + 3 * hh1_size; // HH1位置double noise_sd = 0.0;for (int i = 0; i < hh1_size; i++) {noise_sd += fabs(HH1[i]);}noise_sd = (noise_sd / hh1_size) / 0.6745;double threshold = noise_sd * sqrt(2 * log(img.rows * img.cols));printf("Noise SD: %.2f, Threshold: %.2f\n", noise_sd, threshold);// 对细节子带进行软阈值处理int coeff_pos = 0;for (int l = 1; l <= levels; l++) {int subband_size = (img.rows >> l) * (img.cols >> l);// 跳过近似子带(LL)if (l == levels) coeff_pos += subband_size;// 处理LH/HL/HH子带for (int i = 0; i < 3 * subband_size; i++) {double* coeff = &dwt_coeffs[coeff_pos + i];double abs_val = fabs(*coeff);if (abs_val > threshold) {*coeff = (*coeff > 0) ? (*coeff - threshold): (*coeff + threshold);} else {*coeff = 0.0;}}coeff_pos += 3 * subband_size;}}// 9. 执行2D IDWT重构double* reconstructed = (double*)malloc(img.rows * img.cols * sizeof(double));idwt2(wt, dwt_coeffs, reconstructed);// 10. 转换回原图像类型cv::Mat result(img.rows, img.cols, CV_64F, reconstructed);result.convertTo(img, img.type());// 11. 释放资源free(reconstructed);wt2_free(wt);wave_free(wave);
}int main(int argc, char** argv) {// 参数设置const char* input_path = "C:/Users/Administrator/Desktop/test.jpeg";const char* output_path = "d:/output.jpg";int levels =  2;const char* wname =  "db4";// 读取图像(支持彩色和灰度)cv::Mat img = cv::imread(input_path, cv::IMREAD_ANYCOLOR);if (img.empty()) {fprintf(stderr, "Failed to load image: %s\n", input_path);return -1;}// 分通道处理if (img.channels() == 1) {wavelet_image_processing(img, wname, levels, true, true);} else {std::vector<cv::Mat> channels;cv::split(img, channels);for (auto& channel : channels) {wavelet_image_processing(channel, wname, levels, true, true);}cv::merge(channels, img);}// 保存结果if (!cv::imwrite(output_path, img)) {fprintf(stderr, "Failed to save image: %s\n", output_path);return -1;}printf("Processing completed. Result saved to %s\n", output_path);return 0;
}

编译:

g++ wavelet_image.cpp -o wavelet_image \-I/path/to/wavelib/include \-L/path/to/wavelib -lwavelib \`pkg-config --cflags --libs opencv4` \-lm -O2

4. 关键问题解决

Q1: 如何处理彩色图像?
  • 方法:分RGB通道独立处理

cpp

std::vector<cv::Mat> channels;
cv::split(img, channels);
for (auto& ch : channels) {image_dwt(ch, "db4", 2);
}
cv::merge(channels, img);
Q2: 如何选择小波基和分解层数?
  • 小波基

    • haar:计算快,适合边缘检测

    • db4/sym8:平衡时频局部化,适合去噪

  • 层数:通常选2-3层,过多会导致低频信息丢失

Q3: 系数矩阵布局?

Wavelib的2D DWT输出按频带排列:

+---------+---------+
| LL (低频) | HL (水平细节) |
+---------+---------+
| LH (垂直细节) | HH (对角细节) |
+---------+---------+

5. 性能优化建议

  1. 使用整数运算:对8位图像,可先转换为int16减少计算量

  2. 并行化:OpenMP加速多通道处理

    cpp

    #pragma omp parallel for
    for (int ch = 0; ch < 3; ch++) {process_channel(channels[ch]);
    }
  3. 内存复用:避免频繁分配/释放内存

6. 扩展应用

  • JPEG 2000压缩:模仿其量化策略

  • 纹理分析:提取不同尺度的能量特征

  • 融合算法:多图像的小波域融合


http://www.hkcw.cn/article/GUHbiVEMtP.shtml

相关文章

江科大IIC读取MPU6050hal库实现

hal库相关函数 初始化结构体 typedef struct {uint32_t ClockSpeed; /*通讯速度*/uint32_t DutyCycle; /*快速模式下的占空比*/uint32_t OwnAddress1; /*设备地址1*/uint32_t AddressingMode; /*设备地址模式*/uint32_t DualAddressMode; /*双地址模式…

CTFHub-RCE 命令注入-过滤运算符

观察源代码 代码里面可以发现过滤了运算符&#xff0c;我们可以尝试分号&#xff1b; 判断是Windows还是Linux 源代码中有 ping -c 4 说明是Linux 查看有哪些文件 127.0.0.1;ls 打开flag文件 cat这个php文件 127.0.0.1;cat flag_257413168915334.php 可是发现 文本内容显示…

基带传输实验-码型变换

基带传输实验 码型变换 因图片过多且显示失败&#xff0c;故提供源文件共大家按需自行下载&#xff1a;我用夸克网盘分享了「实验报告1.docx」&#xff0c;点击链接即可保存。打开「夸克APP」在线查看&#xff0c;支持多种文档格式转换。 链接&#xff1a;https://pan.quark.c…

中交四航局三公司被罚没7769万元 违规售石料受重罚

5月31日,中交四航局第三工程有限公司因在广连高速TJ02标从化段施工过程中与他人合谋私自出售合法施工产生的石料,被广州市规划和自然资源局处以两项行政处罚,合计罚没金额达77697872元。两项处罚决定日期均为2025年5月23日。根据行政处罚决定书文号穗规划资源从资罚﹝2025﹞…

不必到处扣“恒大”的帽子 无端指责需叫停

恒大或许没想到,多年后会以一种奇特的方式登上热搜。上周,某车企大佬的一番言论引发广泛关注。他提到“汽车产业里的恒大已经出现,只不过还没爆。”这句话在汽车消费市场和金融二级市场中引起巨大反响。这一言论之所以引起热议,一方面是因为恒大暴雷事件给人们留下了深刻印…

Ubuntu 22.04 安装 IsaacLab 2.1.0

安装流程参考 IsaacLab 官方文档 Quickstart Guide — Isaac Lab Documentation 1. 创建虚拟环境 conda create -n isaaclab python3.10 conda activate isaaclab 2. 安装 pytorch&#xff0c;按照官方说明&#xff0c;没什么特殊需求直接用 cuda 11.8 即可 pip install to…

演员贾冰减肥成功瘦到脱相 与妻同框似父女

许久没有同框的贾冰夫妇,在端午节晒出了恩爱合照。5月31日,贾冰太太胡凡凡分享了两人的照片庆祝节日,许久不见的贾冰瘦了许多,妻子写道,从此家中多了一个瘦子。由于贾冰长相显老,与妻子同框时看起来像父女。贾冰在评论区与老婆互动,他开玩笑说:“一次少做点米饭,人家吃…

印度多地因暴雨灾害造成18死 数千人受灾

近日,印度东北部和南部多个地区遭遇强降雨引发的山体滑坡和洪水。过去两天内,至少18人在灾害中丧生,数千人受到影响。阿萨姆邦灾害管理局表示,持续的洪水已经影响了六个地区的超过一万居民。为了应对灾情,当局设立了两个救援营地和一个物资配送中心。根据天气预报,未来两…

天河五山花园楼下拟开网吧引争议 学校家长忧心忡忡

晨光透过榕树叶洒下斑驳光影,空气清新的早晨,五山小学的孩子们背着书包结伴涌入学校。这条绿树成荫的上学路本是让学校和家长都放心的路,但近期由于路过的五山新天地商场拟新开一个“网吧”,变得让人忧心:网吧往往人员流动性大、成分复杂,社区和学生的安全如何保障?青少…

今年端午节粽子刮起低卡风 健康轻食成新宠

临近端午,粽子成为餐桌上的主角。除了传统的咸甜口味之争,“低卡”“低脂”也成为今年粽子市场的新卖点。在沈阳市铁西区的一家生鲜超市内,各式粽子的促销柜台前排满了前来选购的顾客。十色糙米粽子、粗粮低脂无糖粽子等主打“低糖”“低卡”的粽子受到消费者欢迎。销售人员…

[项目亮点(待结合自行设计的组件)]Vue中自定义设计——扩展性原则并以开源的vuedraggable为例

在 Vue 中设计具有良好扩展性的自定义组件&#xff0c;需要遵循一系列设计原则&#xff0c;以确保组件在不同场景下的适应性和可维护性。以下是关键原则及一个示例&#xff0c;帮助您理解如何实现这一目标。 &#x1f9ed; Vue 组件扩展性设计原则 开闭原则&#xff08;Open/Cl…

【AcWing】899. 编辑距离

文章目录 一、题目1、原题链接2、题目描述 二、解题报告1、思路分析2、时间复杂度3、代码详解 一、题目 1、原题链接 902. 最短编辑距离 2、题目描述 二、解题报告 1、思路分析 思路参考来源y总 dp[i][j]表示将a[1~i]变为b[1~j]中所有方案的操作次数最少的一个&#xff1b;按…

Linux基本指令/下

目录 1.echo、cat与printf 2. > 操作符 与 >> 操作符 3. < 操作符 4.消息传送 linux文件深入 5.文件类型 6.mv命令 7.时间相关指令 8.查找命令 9.grep命令 10.zip/unzip/tar命令 11.scp命令 12.bc命令 13.uname 指令 14.快捷键大全 15.关机/重启/睡…

从gitee仓库中恢复IDEA项目某一版本

神奇的功能&#xff01;&#xff01;&#xff01;代码改乱了&#xff0c;但是还有救&#xff01; 打开终端&#xff0c;输入git log 复制想要恢复版本的提交哈希值&#xff0c;打开终端输入git reset --hard <哈希值> &#xff0c;就能修复到那时的提交版本了

排污许可证原始数据(1989-2025.5)

1156 排污许可证原始数据&#xff08;1989-2025.5&#xff09; “污染”年度发文数及主题分布 数据来源 本数据来源于全国排污许可证管理信息平台&#xff0c;由数据皮皮侠团队人工整理&#xff0c;全部内容真实有效。 时间跨度 1989-2025.5 数据范围 省、地级市企业 数…

华为云Flexus+DeepSeek征文|华为云 Flexus X 加速 Dify 平台落地:高性能、低成本、强可靠性的云上选择

目录 前言 1 一键部署 Dify 平台的完整步骤 1.1 选择模板 1.2 参数配置 1.3 资源栈设置 1.4 配置确认与部署 2 Flexus X 服务器的技术优势 2.1 柔性算力随心配 2.2 一直加速一直快 2.3 越用越省降本多 2.4 安全可靠更放心 3 Flexus X 在 Dify 解决方案中的性能体验…

【题解-洛谷】P9422 [蓝桥杯 2023 国 B] 合并数列

题目&#xff1a;P9422 [蓝桥杯 2023 国 B] 合并数列 题目描述 小明发现有很多方案可以把一个很大的正整数拆成若干正整数的和。他采取了其中两种方案&#xff0c;分别将他们列为两个数组 { a 1 , a 2 , ⋯ a n } \{a_1, a_2, \cdots a_n\} {a1​,a2​,⋯an​} 和 { b 1 , …

在Windows本地部署Dify详细操作

Dify官网文档&#xff1a;产品简介 - Dify Docs 1.硬件要求 2.部署方式选择 本次我选择Docker Compose 部署&#xff0c;接下来我将根据官方文档指引&#xff0c;在windows电脑上完成dify本地部署 3.DockerCompose本地部署Dify 3.1 安装WSL2 官方安装WSL2的操作说明入口&…

《彩云追月》音乐会尽展民乐柔美 传统与现代交融

5月30日晚,北京演艺集团旗下北京民族乐团在北京艺术中心上演了民族音乐会《彩云追月》。作为北京演艺集团第十一届“五月演出季”的收官项目,本场音乐会在著名指挥家张冰冰的执棒下,为观众呈现了一场融合传统与现代、柔美与激情的民乐之旅。音乐会以北京民族乐团原创作品《长…

深入理解交叉熵损失函数——全面推演各种形式

带你从不一样的视角综合认识交叉熵损失&#xff0c;阅读这篇文章&#xff0c;帮你建立其分类问题&#xff0c;对比学习&#xff0c;行人重识别&#xff0c;人脸识别等问题的联系&#xff0c;阅读这篇文章相信对你阅读各种底层深度学习论文有帮助。 引言 1. 重新理解全连接层&…