博客
关于我
图像降噪算法——小波硬阈值滤波(下)
阅读量:404 次
发布时间:2019-03-05

本文共 3291 字,大约阅读时间需要 10 分钟。

图像降噪算法——小波硬阈值滤波(下)

图像降噪算法——小波硬阈值滤波(下)

1. 基本原理

关于离散小波变换的原理在

中已经有了非常详细的总结,这里介绍下本博客利用离散小波变换进行降噪的原理(其实不能算是降噪,应该算是图像压缩),就是在小波变换之后,将输出系数进行由大到小的排序,然后将前10%大的通过小波反变换成图像,因为噪声不属于图像的主要信息,因此通过这种方法会有降噪的效果,这种算法又称为小波硬阈值滤波。

2. C++代码实现

这里是基于OpenCV、FFTW以及C++ Wavelet Libraries,这其中

(1)FFTW是一个基于C写的实现傅里叶变换和小波变换的基础库,链接戳,源码安装后用CmakeList链接到静态库文件即可。
(2)C++ Wavelet Libraries是利用FFTW封装的一个小波变换处理图像的库,下载链接戳,这里主要是用到了它的wavelet2d.cpp和wavelet2d.h两个文件。
我封装的小波变换的降噪算法如下:

Mat Denoise::WaveletFilter(const Mat &src, int num, int percentage){       //需要讲Mat数据结构转换为vector数据结构    vector
> dwtInput(src.rows, vector
(src.cols)); for(int i = 0; i
(i,j); } } //计算小波变换,输出结果是output vector
dwtLength; vector
dwtOutput, dwtFlag; dwt_2d(dwtInput, num, "db2", dwtOutput, dwtFlag, dwtLength); //******************************显示相关******************************// //通过dwtLength计算dim// vector
dwtDim;// dwt_output_dim_sym(dwtLength, dwtDim, num);//// //dim的后两位是显示尺寸,并将dwtOutput构造成display// int dwtRow = dwtDim[dwtDim.size()-2], dwtCol = dwtDim[dwtDim.size()-1];// vector
> dwtDisplay(dwtRow, vector
(dwtCol));// dispDWT(dwtOutput, dwtDisplay, dwtLength, dwtDim, num);//// //获取display中的最大值 double m = 0;// for(int i = 0; i < dwtRow; i++)// { // for(int j = 0; j < dwtCol; j++)// { // if(m < dwtDisplay[i][j])// m = dwtDisplay[i][j];// }// }//// //dst是用于显示的图像// Mat dst = Mat::zeros(dwtRow,dwtCol,CV_8UC1);// for(int i = 0; i < dwtRow; i++)// { // for(int j = 0; j < dwtCol; j++)// { // if(dwtDisplay[i][j] <= 0.0)// dwtDisplay[i][j] = 0.0;// if(i<=dwtDim[0] && j<=dwtDim[1])// dst.at
(i,j) = (uchar)(dwtDisplay[i][j]/m*255);// else// dst.at
(i,j) = (uchar)(dwtDisplay[i][j]);// }// }// imshow("dst", dst); //****************************************************************** //******************************滤波相关****************************** //开始滤波 int filterSize = int(dwtOutput.size() / percentage); vector
filter; for(auto it : dwtOutput) { filter.push_back(abs(it)); } sort(filter.begin(), filter.end(), greater
()); double threshold = filter.at(filterSize-1); for(int i = 0; i
(i,j) = (uchar)(dwtDisplay[i][j]/m*255);// else// dst2.at
(i,j) = (uchar)(dwtDisplay[i][j]);// }// }// imshow("dst2", dst2); //****************************************************************** //下面是进行小波反变换过程 vector
> idwtOutput(src.rows, vector
(src.cols)); idwt_2d(dwtOutput, dwtFlag, "db2", idwtOutput, dwtLength); int idwtRow = idwtOutput.size(); int idwtCol = idwtOutput[0].size(); //获取idwtOutput中的最大值 m = 0; for(int i = 0; i < idwtRow; i++) { for(int j = 0; j < idwtCol; j++) { if(m < idwtOutput[i][j]) m = idwtOutput[i][j]; } } //显示降噪后的图像 Mat img = Mat::zeros(idwtRow, idwtCol, CV_8UC1); for(int i = 0; i
(i,j) = (uchar)(idwtOutput[i][j]/m*255); } } return img;}

原图如下:

在这里插入图片描述
加入高斯噪声:在这里插入图片描述
进行图像小波变换:在这里插入图片描述
按照上述方法进行滤波:
在这里插入图片描述
进行图像小波反变换:
在这里插入图片描述

3. 结论

  1. 可以看到通过图像小波变换进行降噪的效果看上去还可以,起码比傅里叶变换的效果要好,但是呢,感觉小波变换的速度还是比较慢,实时运行应该比较困难;
  2. 本文采用的降噪算法其实比较简单,在这篇文献中《Image Denoising Review From Classical to State-of-the-art Approaches,2020》提到,对于转换域的降噪算法主要有两个关键点:1.转换到什么变换域(傅里叶?小波?脊波?);2.采用什么类型的阈值进行滤波,这篇文献中提到了六种设计阈值的方法,需要了解的同学可以参考下;
  3. 小波变化提取信息主要是在水平、垂直和对角线三个方向,在小波的基础上,还有curvelet、contourlet等一些更加高级的变化,之后有需要再进一步了解。

此外,这里我写一个各种算法的总结目录,对图像降噪算法感兴趣的同学欢迎参考

转载地址:http://sbszz.baihongyu.com/

你可能感兴趣的文章
MySQL 添加索引,删除索引及其用法
查看>>
mysql 状态检查,备份,修复
查看>>
MySQL 用 limit 为什么会影响性能?
查看>>
MySQL 用 limit 为什么会影响性能?有什么优化方案?
查看>>
MySQL 用户权限管理:授权、撤销、密码更新和用户删除(图文解析)
查看>>
mysql 用户管理和权限设置
查看>>
MySQL 的 varchar 水真的太深了!
查看>>
mysql 的GROUP_CONCAT函数的使用(group_by 如何显示分组之前的数据)
查看>>
MySQL 的instr函数
查看>>
MySQL 的mysql_secure_installation安全脚本执行过程介绍
查看>>
MySQL 的Rename Table语句
查看>>
MySQL 的全局锁、表锁和行锁
查看>>
mysql 的存储引擎介绍
查看>>
MySQL 的存储引擎有哪些?为什么常用InnoDB?
查看>>
Mysql 知识回顾总结-索引
查看>>
Mysql 笔记
查看>>
MySQL 精选 60 道面试题(含答案)
查看>>
mysql 索引
查看>>
MySQL 索引失效的 15 种场景!
查看>>
MySQL 索引深入解析及优化策略
查看>>