数字图像处理系列(三)---图像去噪
发布日期:2022-02-12 16:06:54 浏览次数:4 分类:技术文章

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

图像去噪


图像噪声介绍

1.什么是图像噪声

图像中各种妨碍人们对其信息接受的因素即可称为图像噪声(即图像数据中的干扰信息)

2.图像噪声的来源

  • 图像获取过程
  • 数字图像传输的过程

3.特点

  • 噪声的分布和大小不规则
  • 噪声和原图像有相关性
  • 噪声具有叠加性

4.分类

1.高斯噪声(它的幅度分布服从高斯分布,而它的功率谱密度又是均匀分布)

根据Box-Muller变换原理,建设随机变量U1、U2来自独立的处于(0,1)之间的均匀分布,则经过下面两个式子产生的随机变量Z0,Z1服从标准高斯分布

上式中Z0,Z1满足正态分布,其中均值为0,方差为1,变量U1和U2可以修改为下式:

2.椒盐噪声(强烈变化引起的突然产生不规则的白点和黑点)

通过随机获取像素点并设置为高亮度点和低灰度点来实现

代码如下

# include
#include
#include
using namespace std;using namespace cv;void salt_noise(Mat& image, Mat& salt_image, const int n);//椒盐噪声double addgassian_noise(double mu,double sigma);//高斯噪声的实现void gassian_noise(Mat& image, Mat& gassian_image);//高斯噪声int main(){ Mat image = imread("d:/texting.jpg", 0); if (image.empty()) { cout << "未找到文件" << endl; return -1; } Mat salt_image; salt_noise(image, salt_image, 5000); Mat gassian_image; gassian_noise(image, gassian_image); imshow("image", image); imshow("salt_image", salt_image); imshow("gassian_image", gassian_image); waitKey(0); return 0;}void salt_noise(Mat& image, Mat& salt_image, const int n){ salt_image = image.clone(); int i, j; for (int x=0; x < n; ++x) { i = rand() % image.rows; j = rand() % image.cols; if (salt_image.channels() == 1) { salt_image.at
(i, j) = 255; } else { salt_image.at
(i, j)[0] = 255; salt_image.at
(i, j)[1] = 255; salt_image.at
(i, j)[2] = 255; } } for (int x=0; x < n; ++x) { i = rand() % image.rows; j = rand() % image.cols; if (salt_image.channels() == 1) { salt_image.at
(i, j) = 0; } else { salt_image.at
(i, j)[0] = 0; salt_image.at
(i, j)[1] = 0; salt_image.at
(i, j)[2] = 0; } }}double addgassian_noise(double mu, double sigma){ //定义小值 const double min_number = numeric_limits
::min(); static double z0, z1; static bool flag = false; flag = !flag; if (!flag) return z1 * sigma + mu; double u1, u2; do { u1 = rand() * (1.0 / RAND_MAX); u2 = rand() * (1.0 / RAND_MAX); } while (u1 <= min_number); z0 = sqrt(-2.0 * log(u1)) * cos(2 * CV_PI * u2); z1 = sqrt(-2.0 * log(u1)) * sin(2 * CV_PI * u2); return z0 * sigma + mu;}void gassian_noise(Mat& image, Mat& gassian_image){ gassian_image = image.clone(); for (int row=0; row < image.rows; ++row) { for (int col=0; col < image.cols; ++col) { int x = int(gassian_image.at
(row, col) + addgassian_noise(2, 0.8) * 32); if (x < 0) x = 0; if (x > 255) x = 255; gassian_image.at
(row,col) = (uchar)x; } }}

效果如下:


局部运算

为了减少噪声到来的影响,因此很多时候我们采用很多的方法进行处理,而其中最有效的方法的使用局部运算,即使用像素和像素周围的像素进行运算,从而综合单个像素对于图像过于明显的影响。

1.邻域平均法(box模板)

使用以一个点为中心f(x,y)和其周围的n*n的像素进行取平均,然后再赋值给f(x,y),这样该位置就变成g(x,y)。即其就是一个平均的概念

代码如下:

/***********************************************************项目名称:使用均值滤波进行图像去噪*缺点: 1.图像模糊,2.计算量大**函数:void average_filter(Mat& src, Mat& dst,const int& Border);*      描述:无返回值,src是输入的图像,dst是改变后输出的图像,Border表示模板大小 Border*Border**作者:****日期:2020.04.06*修改:使用积分图技术进行减少计算量(未完成)***********************************************************/#include
#include
using namespace std;using namespace cv;void average_filter(Mat& src, Mat& dst,const int& Border);int main(void){ Mat image = imread("d:/模糊的图片.PNG", 0); if (image.empty()) { cout << "未找到指定的文件" << endl; return -1; } // 生成一个大小一样的全黑的图像 Mat average_image = Mat::zeros(image.size(), CV_8UC1); //模板的大小 const int border = 7; //自定义均值滤波函数 average_filter(image,average_image, border); Mat output_blur; //库的均值滤波函数 blur(image, output_blur, Size(7, 7)); imshow("image", image); imshow("average_image", average_image); imshow("output_blur", output_blur); waitKey(0); return 0;}void average_filter(Mat& src, Mat& dst, const int& Border){ int width = src.rows; int height = src.cols; cout << width << endl; cout << height << endl; int row,col; int sum=0;//表示模板内的像素的总和 for (row = 0; row < width ; ++row) { for (col =0; col < height; ++col) { if (row >= (Border - 1) / 2 && row < width - (Border - 1) / 2 && col >= (Border - 1) / 2 && col < height - (Border - 1) / 2) { for (int i = -(Border - 1) / 2; i <= (Border - 1) / 2; ++i) for (int j = -(Border - 1) / 2; j <= (Border - 1) / 2; ++j) { sum = sum+src.at
(row + i, col + j); } dst.at
(row, col) = sum / (Border * Border); sum = 0; } else { dst.at
(row, col) = src.at
(row, col); } } }}

2.中值滤波法

其步骤为:

  1. 将窗口中心与图中某个象素位置重合(和均值一样取n*n)
  2. 提取出该模板的个个像素灰度值
  3. 进行排序
  4. 取出中间的值
  5. 进行赋值给窗口的f(x,y),得到新的值g(x,y)

代码如下:

/***********************************************************项目名称:使用中值滤波进行图像去噪*缺点: 图像中点、线、尖角细节较多,则不宜采用中值滤波**函数:void median_filter(Mat& src, Mat& dst,const int& Border);*      描述:无返回值,src是输入的图像,dst是改变后输出的图像,Border表示模板大小 Border*Border**作者:****日期:2020.04.06*修改:使用多种排列的算法进行处理(未完成)***********************************************************/#include
#include
using namespace std;using namespace cv;void median_filter(Mat& src, Mat& dst, const int& Border);int main(void){ Mat image = imread("d:/模糊的图片.PNG", 0); if (image.empty()) { cout << "未找到指定的文件" << endl; return -1; } // 生成一个大小一样的全黑的图像 Mat median_image = Mat::zeros(image.size(), CV_8UC1); //模板的大小 const int border = 5; //自定义均值滤波函数 median_filter(image, median_image, border); Mat output_blur; //库的均值滤波函数 //blur(image, output_blur, Size(7, 7)); imshow("image", image); imshow("median_image", median_image); //imshow("output_blur", output_blur); waitKey(0); return 0;}void median_filter(Mat& src, Mat& dst, const int& Border){ int width = src.rows; int height = src.cols; cout << width << endl; cout << height << endl; int row, col; int* border = new int[Border * Border]; for (int i = 0; i < Border * Border; ++i) { border[i] = i; } for (int i = 0; i < Border * Border; ++i) { //cout<
<
= (Border - 1) / 2 && row < width - (Border - 1) / 2 && col >= (Border - 1) / 2 && col < height - (Border - 1) / 2) { for (int i = -(Border - 1) / 2; i <= (Border - 1) / 2; ++i) { for (int j = -(Border - 1) / 2; j <= (Border - 1) / 2; ++j) { //进行赋值到中间数组里面进行排序 border[(i+ (Border - 1) / 2)+(j+ (Border - 1) / 2) *Border]= src.at
(row + i, col + j); } } //进行排序 for (int i = 1; i < Border * Border; ++i) { for (int j = 1; j < Border * Border-i; ++j) { if (border[j - 1] > border[j]) { median = border[j - 1]; border[j - 1] = border[j]; border[j] = median; } median = 0; } } //排序完进行赋值 dst.at
(row, col) = border[(Border * Border - 1) / 2]; } else { dst.at
(row, col) = src.at
(row, col); } } }}

3.高斯滤波

模板运算的数学含义是卷积运算,使用高斯滤波来解决图像去噪的问题,只有基本掌握模板运算和高斯滤波的公式就可以。

代码如下:

//*************************************************//第三周作业:编写代码,实现高斯滤波,模板大小为3*3////Version: 0.1//author : ***//date   : 2020/03/29//***********************************************#include 
#include
#include
using namespace std;using namespace cv;double** getGuassionArray(int size, double sigma) { int i, j; double sum = 0.0; int center = size; //以第一个点的坐标为原点,求出中心点的坐标 double** arr = new double* [size];//建立一个size*size大小的二维数组 for (i = 0; i < size; ++i) arr[i] = new double[size]; for (i = 0; i < size; ++i) for (j = 0; j < size; ++j) { arr[i][j] = exp(-((i - center) * (i - center) + (j - center) * (j - center)) / (sigma * sigma * 2)); sum += arr[i][j]; } for (i = 0; i < size; ++i) for (j = 0; j < size; ++j) arr[i][j] /= sum; return arr;}//**********************************//第一个参数是_src表示输入//第二个参数是_dst表示输出void myGaussian(const Mat _src, Mat& _dst) { if (_src.empty()) { cout << "未找到有效文件" << endl; return; } double** arr; Mat tmp(_src.size(), _src.type()); for (int i = 0; i < _src.rows; ++i) for (int j = 0; j < _src.cols; ++j) { //保证边缘不进行处理 if ((i - 1) > 0 && (i + 1) < _src.rows && (j - 1) > 0 && (j + 1) < _src.cols) { arr = getGuassionArray(3, 1);//自定义得到的权值数组 tmp.at
(i, j)[0] = 0; tmp.at
(i, j)[1] = 0; tmp.at
(i, j)[2] = 0; for (int x = 0; x < 3; ++x) { for (int y = 0; y < 3; ++y) { tmp.at
(i, j)[0] += arr[x][y] * _src.at
(i + 1 - x, j + 1 - y)[0]; tmp.at
(i, j)[1] += arr[x][y] * _src.at
(i + 1 - x, j + 1 - y)[1]; tmp.at
(i, j)[2] += arr[x][y] * _src.at
(i + 1 - x, j + 1 - y)[2]; } } } } tmp.copyTo(_dst);}void main() { Mat image = imread("D:/图片/壁纸/动漫/1.jpg",1); Mat Gaussian; Mat image1; GaussianBlur(image, image1, Size(3, 3), 1); //自带的高斯滤波 myGaussian(image, Gaussian); imshow("原图", image); imshow("opencv自带的高斯滤波", image1); imshow("自定义高斯滤波", Gaussian); waitKey(0);}

转载地址:https://blog.csdn.net/weixin_46563862/article/details/105421567 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:数字图像处理系列(二)---空间域图像增强-点运算
下一篇:数字图像处理系列(四)---图像边缘检测

发表评论

最新留言

做的很好,不错不错
[***.243.131.199]2024年03月06日 18时25分05秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

webpack卸载_webpack的安装 2019-04-21
mysql主库线程_MySQL 主从扩展--主库的线程状态 2019-04-21
phpmyadmin管理mysql_LAMP实验二:使用phpMyAdmin管理MySQL 2019-04-21
mysql一秒最多写多少次_Mysql的两种“超过多少次”写法(力扣596) 2019-04-21
mysql el函数_MySQL中的常用函数 2019-04-21
mysql 备份 晓燕_mysql字符串函数 2019-04-21
mysql返回第n个值_获取mysql一组数据中的第N大的值 2019-04-21
java 获取请求的路径_JavaWeb-request获取请求路径的相关方法 2019-04-21
java 适应边框_带边框自适应宽度100%的解决办法 2019-04-21
router vue 页签文字_记一次基于vue的spa多页签实践经验 2019-04-21
估计的商是什么意思_商是什么意思,商的繁体字,商有几笔,商字几画 2019-04-21
java泛型改进_编写高质量代码:改善Java程序的151个建议(第7章:泛型和反射___建议93~97)... 2019-04-21
java读文件几种方式_JAVA读取文件的几种方式 2019-04-21
java arraylist常用方法_C#中数组、ArrayList、List、Dictionary的用法与区别浅析(存取数据)... 2019-04-21
如何实现java文档注释_JavaDoc注释与帮助说明文档 2019-04-21
Java一亿电话号码去重_20 亿个数字在 4G 内存中如何去重排序:快来试一试 BitMap... 2019-04-21
java判断ipv6地址类型_IPv6地址类型与格式 2019-04-21
linux java jdk_linux安装JDK 2019-04-21
java的showcase_java – 如何在Eclipse中导入ShowcaseView? 2019-04-21
JAVA中math的作用_Java中Random 和 Math 的概述及使用(二十六) 2019-04-21