OpenCv基础(一):噪声的添加和过滤

来源:互联网 发布:悬疑片推荐知乎 编辑:程序博客网 时间:2024/05/20 23:05

这是图像处理的第一章,简单地说一下OpenCv的基础功能

  • 图像的读取
  • 图像的显示
  • 访问图像的像素值

这一节,我将会介绍一下各种噪声的类型,并且添加两三种常见的噪声

将图像读入到Mat后,有三种方式访问Mat中的数据:

  • 通过指针
  • 使用迭代器
  • 调用at

相信大家已经对这些基础中的基础了解的很不错了,所以我就直接开始介绍主题,噪声
(以下的介绍为其他博客找到的)

图像噪声

图像噪声是图像在获取或传输的过程中受到随机信号的干扰,在图像上出现的一些随机的、离散的、孤立的像素点,这些点会干扰人眼对图像信息的分析。图像的噪声通常是比较复杂的,很多时候将其看成是多维随机过程,因而可以借助于随即过程描述噪声,即使用概率分布函数和概率密度函数。

图像的噪声很多,性质也千差万别, 可以通过不同的方法给噪声分类。
按照产生的原因:

  • 外部噪声
  • 内部噪声

    这种分类方法,有助于理解噪声产生的源头,但对于降噪算法只能起到原理上的帮组。

噪声和图像信号的关系,可以分为:

  • 加性噪声,加性噪声和图像信号强度不相关,这类噪声可以看着理想无噪声图像f和噪声的和。
  • 乘性噪声,乘性噪声和图像信号是相关的,往往随图像信号的变化而变化。 而为了分析处理的方便,常常将乘性噪声近似认为是加性噪声,而且总是假定信号和噪声是互相独立的。

按照概率密度函数(PDF)分类:

  • 高斯噪声,高斯噪声模型经常被用于实践中。
  • 脉冲噪声(椒盐噪声),图像上一个个点,也可称为散粒和尖峰噪声。
  • 伽马噪声
  • 瑞利噪声
  • 指数分布噪声
  • 均匀分布噪声
    这种分类方法,引入了数学模型,对设计过滤算法比较有帮助。

给图像添加噪声

按照指定的噪声类型,生成一个随机数,然后将这个随机数加到源像素值上,并将得到的值所放到[0,255]区间即可。

C++11 随机数发生器

我在噪声的加成上用的是C++11新标准下的随机数生成方法
新的随机数生成器被抽象成了两个部分:随机数生成引擎和要生成的随机数符合的分布。
随机数引擎有三种:

  • linear_congruential_engine 线性同余算法
  • mersenne_twister_engine 梅森旋转算法
  • subtract_with_carry_engine 带进位的线性同余算法

第一种最常用,而且速度比较快;第二种号称最好的伪随机数生成器

std::random_device rd; // 随机数种子std::mt19937 mt(rd()); // 随机数引擎std::normal_distribution<> d(5,20); // 高斯分布std::map<int,int> hist;for(int n = 0; n < 10000; n ++)    ++hist[std::round(d(mt))]; // 生成符合高斯分布的随机数

以上为生成符合高斯分布的随机数

添加图像噪声

使用C++的随机数发生器为图像添加两种噪声:椒盐噪声和高斯噪声。
对了,记得要用这个随机数产生的话,请#include<random>,用法请自行百度
椒盐噪声是图像中离散分布的白点或者黑点,测试代码如下:

void addSaltNoise(Mat &m, int num){    // 随机数产生器    std::random_device rd; //种子    std::mt19937 gen(rd()); // 随机数引擎    auto cols = m.cols * m.channels();    for (int i = 0; i < num; i++)    {        auto row = static_cast<int>(gen() % m.rows);        auto col = static_cast<int>(gen() % cols);        auto p = m.ptr<uchar>(row);        p[col++] = 255;        p[col++] = 255;        p[col] = 255;    }}

高斯噪声是一种加性噪声,为图像添加高斯噪声的代码如下:

//添加高斯噪声//用指针进行像素点的访问void addGaussianNoise(Mat & img, const int& mu,const int & sigma){    auto cols = img.cols*img.channels();    auto rows = img.rows;    // 产生Gauss分布随机数发生器    std::random_device rd;    std::mt19937 gen(rd());    std::normal_distribution<> gaussR(mu, sigma);    for (int i = 0; i < rows; i++)    {        auto p = img.ptr<uchar>(i);        for (int j = 0; j < cols; j++)        {            auto tmp = p[j] + gaussR(gen);            tmp = tmp > 255 ? 255 : tmp;            tmp = tmp < 0 ? 0 : tmp;            p[j] = tmp;        }    }}

以下为运行结果:
这里写图片描述

左边是原始图片,中间是椒盐噪声模糊之后的图像,最后是高斯模糊之后的图像

使用滤波器去除噪声

根据噪声类型的不同,选择不同的滤波器过滤掉噪声。通常,对于椒盐噪声,选择中值滤波器(Median Filter),在去掉噪声的同时,不会模糊图像;对于高斯噪声,选择均值滤波器(Mean Filter),能够去掉噪声,但会对图像造成一定的模糊。
在OpenCV中,对应于均值滤波器的函数是blur,该函数需要5个参数,通常只设置前3个后两个使用默认值即可。
blur(m, m2, Size(5, 5));第一个参数是输入的图像,第二个参数是输出的图像,第三个参数是滤波器的大小,这里使用的是5×5 5×5的矩形。

对应于中值滤波器的函数是medianBlur(m1, m3, 5);前两个参数是输入输出的图像,第三个参数是滤波器的大小,由于是选取的是中值,滤波器的大小通常是一个奇数。

下图是对有噪声图像使用滤波器后的结果,中间的是原始图像,左边的是使用均值滤波器过滤高斯噪声后的结果;右边的是使用中值滤波器过滤椒盐噪声后的结果。可以明显的看出,这两种滤波器都能够很好的去掉图像的噪声,但会对图像造成一定的模糊,尤其是均值滤波器造成的模糊比较明显。

这里写图片描述

PS:好了,差不多如此,借鉴了很多别人博客的东西,希望这一周能够多总结一下opencv的东西。