23.代码简单实现模拟噪声(图像噪声/一、二阶矩/功率谱密度/at函数/rand函数)-- OpenCV从零开始到图像(人脸 + 物体)识别系列


本文作者:小嗷

微信公众号:aoxiaoji

吹比QQ群:736854977

简书链接:https://www.jianshu.com/u/45da1fbce7d0


1.前言

本文你会找到以下问题的答案:

  1. 图像噪声
  2. 噪声来源
  3. 常见噪声介绍(高斯噪声,泊松噪声,乘性噪声,椒盐噪声)
  4. 一、二阶矩
  5. 功率谱密度
  6. 代码简单实现模拟噪声
  7. at()函数
  8. rand()函数

2.1 图像噪声

噪声在图像上常表现为一引起较强视觉效果的孤立像素点或像素块。一般,噪声信号与要研究的对象不相关,它以无用的信息形式出现,扰乱图像的可观测信息。通俗的说就是噪声让图像不清楚。

2.2 噪声来源

1.图像获取过程中

两种常用类型的图像传感器CCD和CMOS采集图像过程中,由于受传感器材料属性、工作环境、电子元器件和电路结构等影响,会引入各种噪声,如电阻引起的热噪声、场效应管的沟道热噪声、光子噪声、暗电流噪声、光响应非均匀性噪声。

2.图像信号传输过程中

由于传输介质和记录设备等的不完善,数字图像在其传输记录过程中往往会受到多种噪声的污染。另外,在图像处理的某些环节当输入的对象并不如预想时也会在结果图像中引入噪声。

简单来说:工厂环节 -> 运输到客户途中。

2.3 常见噪声介绍

图像常见噪声基本上有以下四种,高斯噪声,泊松噪声,乘性噪声,椒盐噪声。

下面五幅图分别代表了,原图,以及添加了高斯噪声,泊松噪声,乘性噪声,椒盐噪声的图像。

2.3.1 原图

1.噪声原图

2.3.2 高斯噪声(下图)

高斯噪声是指它的概率密度函数服从高斯分布(即正态分布)的一类噪声。如果一个噪声,它的幅度分布服从高斯分布,而它的功率谱密度又是均匀分布的,则称它为高斯白噪声。高斯白噪声的二阶矩不相关,一阶矩为常数,是指先后信号在时间上的相关性。(什么是二阶矩?什么是功率谱密度?)

产生原因:

1)图像传感器在拍摄时市场不够明亮、亮度不够均匀;

2)电路各元器件自身噪声和相互影响;

3)图像传感器长期工作,温度过高。

2.噪声

2.3.2.1 一、二阶矩

数学上,“矩”是一组点组成的模型的特定的数量测度。
在力学和统计学中都有用到“矩”。

如果这些点代表“质量”,那么:

零阶矩表示所有点的质量;
一阶矩表示质心;

二阶矩表示转动惯量。

如果这些点代表“概率密度”,那么:

零阶矩表示这些点的 总概率(也就是1);

一阶矩表示 期望;

二阶(中心)矩表示 方差;

三阶(中心)矩表示 偏斜度;

四阶(中心)矩表示 峰度;

这个数学上的概念和物理上的“矩”的概念关系密切。

参考网站:

https://en.wikipedia.org/wiki/Moment_%28mathematics%29

注意:(理解一下,就可以。大概以后处理一些不确定的概率问题,涉及统计学,需要详解)

2.3.2.1 功率谱密度

波的功率频谱???

功率

功率是指物体在单位时间内所做的功的多少,即功率是描述做功快慢的物理量。

功率谱是什么?(功率频谱大概就是功率谱傅里叶变换之后的玩意,小嗷猜的)

生活中很多东西之间都依靠信号的传播,信号的传播都是看不见的,但是它以波的形式存在着,这类信号会产生功率,单位频带的信号功率就被称之为功率谱。

(不懂什么是频带参考第21篇文章)

打个比方:这条路,1秒内通过的8个人。1次只能同时通过4个人。

那么1秒的功率是8个人,8/1=8;

再重新看这句话,把这类信号会产生功率(1秒内通过的8个人),单位频带(1次只能同时过4个人)的信号功率就被称之为功率谱。

它可以显示在一定的区域中信号功率随着频率变化的分布情况。

而频谱也是相似的一种信号变化曲线,在科学的领域里,功率谱和频谱有着一定的联系,但是它们之间还是不一样的,是有区别的。

3.功率谱

功率谱密度

在频谱分析中幅度和功率是由紧密联系的两个不同的物理量:

能量能表述为幅值的平方和,也能表述为功率在时间上的积分;

功率谱密度,是指用密度的概念表示信号功率在各频率点的分布情况,是对随机变量均方值的量度,是单位频率的平均功率量纲;

也就是说,对功率谱在频域上积分就可以得到信号的平均功率,而不是能量。能量谱密度是单位频率的幅值平方和量纲,能量谱密度曲线下面的面积才是这个信号的总能量。

于是,功率谱、能量谱、幅值谱之间的紧密关系主要表述为:能量谱是功率谱密度函数在相位上的卷积,也是幅值谱密度函数的平方在频率上的积分;功率谱是信号自相关函数的傅里叶变换,能量谱是信号本身傅立叶变换幅度的平方。

功率谱相关释义:

尽管并非一定要为信号或者它的变量赋予一定的物理量纲,下面的讨论中假设信号在时域内变化。上面能量谱密度的定义要求信号的傅里叶变换必须存在,也就是说信号平方可积或者平方可加。

一个经常更加有用的替换表示是功率谱密度(PSD),它定义了信号或者时间序列的功率如何随频率分布。这里功率可能是实际物理上的功率,或者更经常便于表示抽象的信号被定义为信号数值的平方,也就是当信号的负载为1欧姆(ohm)时的实际功率。

此瞬时功率(平均功率的中间值)可表示为:

4.

由于平均值不为零的信号不是平方可积的,所以在这种情况下就没有傅里叶变换。幸运的是维纳-辛钦定理(Wiener-Khinchin theorem)提供了一个简单的替换方法,如果信号可以看作是平稳随机过程,那么功率谱密度就是信号自相关函数的傅里叶变换。

功率谱和频谱的区别

1、计算

功率谱的计算需要信号先做自相关,然后再进行FFT运算。

频谱的计算则是将信号直接进行FFT就行了。

2、方式

功率谱是对信号研究,不过它是从能量的方面来对信号研究的。

而频谱也是用来形容信号的,只是的表示方式变了,从时域转变成了频域表示,也就是说一种信号的表示方式不同而已。

功率谱与频谱和的区别归根结底就是信号、功率、能量三者之间的关联。

5.功率谱

3、定义

功率谱的定义是在有限信号的情况下,单位频带范围内信号功率的变换状况,功率随频率而变化,从而表现成为功率谱,它是专门对功率能量的可用有限信号进行分析所表现的能量。它含有频谱的一些幅度信息,不过相位信息被舍弃掉了。

相比之下,频谱极为不严格,主要是体现信号的平均变换,要求的只是一段时间平均量。

所以经常说在频谱信号不同的情况下,它的功率谱很可能是一样的。

6.二维图

4、性质

功率谱虽然过程是随机的,但由于统计的是平均概念,就相当于平稳的随机过程,这个过程的功率谱则是一个确定性的函数。

而频谱的样本进行Fourier变换,尽管过程也是随机的,但是对于这个随机变化过程来说,频谱形成的是随机的频域序列,函数不确定。

5、要求

功率谱和频谱的功率极其幅度的概念也是有差别,并且它们的存在性要求也是不同的。功率谱的存在性要求变化收敛,而频谱的存在性只要求了是否收敛。

7.功率谱

功率谱和频谱有相同的地方,并且有着联系,可这些区别才是决定它们两个用处的重要之处。功率谱和频谱虽然都是对信号的研究,但是研究的方向不同,角度也不相同,并且它们的性质存在不同之处,功率谱的随机性更差一点,比较严谨,有确定的函数支撑;而频谱的要求更少一些,随机性颇强,导致了它的信号变化,不过这也是它的研究价值所在。

内容来源:土巴兔

注意:(理解一下,就可以。大概以后处理一些不确定的概率问题,涉及统计学,需要详解)

2.3.3 泊松噪声(下图)

泊松噪声,就是符合泊松分布的噪声模型,泊松分布适合于描述单位时间内随机事件发生的次数的概率分布。

如某一服务设施在一定时间内受到的服务请求的次数,电话交换机接到呼叫的次数、汽车站台的候客人数、机器出现的故障数、自然灾害发生的次数、DNA序列的变异数、放射性原子核的衰变数等等

8.泊松噪声

2.3.4 乘性噪声(下图)

乘性噪声一般由信道不理想引起,它们与信号的关系是相乘,信号在它在,信号不在他也就不在。

9.乘性噪声

2.3.5 椒盐噪声(下图)

椒盐噪声,椒盐噪声又称脉冲噪声,它随机改变一些像素值,是由图像传感器,传输信道,解码处理等产生的黑白相间的亮暗点噪声。

椒盐噪声往往由图像切割引起。

10.椒盐噪声

11.代码实现过程.png

图像噪声使图像在获取或是传输过程中收到随机信号干扰,妨碍人们对图像理解及分析处理的信号。很多时候将图像噪声看做多维随机过程,因而描述噪声的方法完全可以借用随机过程的描述,也就是使用随机过程的描述,也就是用它的高斯分布函数和概率密度分布函数。图像噪声的产生来自图像获取中的环境条件和传感元器件自身的质量,图像在传输过程中产生图像噪声的主要因素是所用的传输信道收到了噪声的污染。

先简单介绍一下相关API函数:

3.1 at()函数(在Mat)

at类中的at方法对于获取图像矩阵某点的RGB值或者改变某点的值很方便。

对于单通道的图像,则可以使用:

如:XXX.at<uchar>(i, j)=255(因为单通道(灰度图),由黑到白)
(坐标(i, j)上,像素点的值为白色)

对于多通道的图像(BGR),如

img.at<Vec3b>(14,25) [0]= 25;//B    
img.at< Vec3b >(14,25) [1]= 25;//G    
img.at< Vec3b >(14,25 [2]= 25;//R    

3.2 rand()函数

rand()函数是产生随机数的一个随机函数。

如:rand()%3是什么意思?

rand()是伪随机数生成函数,%是模运算,这个表达式的作用是随机生成012三个数字中的一个。

3.3 下面简单写写两种图像噪声,即椒盐噪声和高斯噪声。

3.4 椒盐噪声是什么?

椒盐噪声也称为脉冲噪声,是图像中经常见到的一种噪声,它是一种随机出现的白点或者黑点,可能是亮的区域有黑色像素或是在暗的区域有白色像素(或是两者皆有)。盐和胡椒噪声的成因可能是影像讯号受到突如其来的强烈干扰而产生、类比数位转换器或位元传输错误等。例如失效的感应器导致像素值为最小值,饱和的感应器导致像素值为最大值。

图像模拟添加椒盐噪声是通过随机获取像素点并设置为高亮度点和低灰度点来实现的

即:随机设置一些像素点为白色或者黑色。

图像添加椒盐噪声的程序如下:

//利用程序给原图像增加椒盐噪声
//图象模拟添加椒盐噪声是通过随机获取像素点斌那个设置为高亮度点来实现的

#include <cstdlib>  
#include <iostream>  
#include <opencv2\core\core.hpp>  
#include <opencv2\highgui\highgui.hpp>  
#include <opencv2\imgproc\imgproc.hpp>  

using namespace cv;
using namespace std;

Mat addSaltNoise(const Mat srcImage, int n);


int main()
{
    Mat srcImage = imread("D://原图.jpg");
    if (!srcImage.data)
    {
        cout << "读入图像有误!" << endl;
        system("pause");
        return -1;
    }
    imshow("原图像", srcImage);
    Mat dstImage = addSaltNoise(srcImage, 3000);
    imshow("添加椒盐噪声的图像", dstImage);
    //存储图像  
    imwrite("salt_pepper_Image.jpg", dstImage);
    waitKey();
    return 0;
}

Mat addSaltNoise(const Mat srcImage, int n)
{
    //克隆一张一摸一样的图
    Mat dstImage = srcImage.clone();
    for (int k = 0; k < n; k++)
    {
        //随机取值行
        //rand()是伪随机数生成函数,%是模运算,这个表达式的作用是随机生成012三个数字中的一个。
        int i = rand() % dstImage.rows;
        int j = rand() % dstImage.cols;
        //图像通道判定  
        if (dstImage.channels() == 1)
        {
            dstImage.at<uchar>(i, j) = 255;       //盐噪声  
        }
        else
        {
            dstImage.at<Vec3b>(i, j)[0] = 255;
            dstImage.at<Vec3b>(i, j)[1] = 255;
            dstImage.at<Vec3b>(i, j)[2] = 255;
        }
    }
    for (int k = 0; k < n; k++)
    {
        //随机取值行列  
        int i = rand() % dstImage.rows;
        int j = rand() % dstImage.cols;
        //图像通道判定  
        if (dstImage.channels() == 1)
        {
            dstImage.at<uchar>(i, j) = 0;     //椒噪声  
        }
        else
        {
            dstImage.at<Vec3b>(i, j)[0] = 0;
            dstImage.at<Vec3b>(i, j)[1] = 0;
            dstImage.at<Vec3b>(i, j)[2] = 0;
        }
    }
    return dstImage;
}

原图

12.原图.jpg

椒盐图

13.椒盐图

就是随机分布黑白像素点

3.5 高斯噪声(基于Box–Muller变换的正态随机数生成方法)

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

定理(Box-Muller变换):如果随机变量U1和U2是IID的,且U1,U2 ~Uniform[0, 1],则

14.高斯.PNG

Z0和Z1独立且服从标准正态分布。

如何来证明这个定理呢?这需要用到一些微积分中的知识,首先回忆一下二重积分化为极坐标下累次积分的方法:

15.高斯.PNG

假设现在有两个独立的标准正态分布 X~N(0,1) 和 Y~N(0,1),由于二者相互独立,则联合概率密度函数为

16.高斯.PNG

做极坐标变换,则x=Rcosθ,y=Rsinθ,则有

17.高斯.PNG

你可以看到这个结果可以看成是两个概率分布的密度函数的乘积,其中一个可以看成是[0, 2π]上均匀分布,将其转换为标准均匀分布则有θ ~Unif (0, 2π)=2π U2。

另外一个的密度函数为

18.高斯.PNG

则其累计分布函数CDF为

19.高斯.PNG

这个CDF函数的反函数可以写成

20.高斯.PNG

根据逆变换采样的原理,如果我们有个PDF为P(R)的分布,那么对齐CDF的反函数进行均匀采样所得的样本分布将符合P(R)的分布,而如果 u 是均匀分布的,那么 U1 = 1-u 也将是均匀分布的,于是用 U1 替换1-u,最后可得

21.高斯.PNG

结论得证。最后我们来总结一下利用Box-Muller变换生成符合高斯分布的随机数的方法:

22.高斯.PNG

图像添加高斯噪声的程序如下:

//给图像添加高斯噪声  
#include <cmath>  
#include <limits>  
#include <cstdlib>  
#include <iostream>  
#include <opencv2\core\core.hpp>  
#include <opencv2\highgui\highgui.hpp>  

using namespace cv;
using namespace std;

double generateGaussianNoise(double m, double sigma);
Mat addGaussianNoise(Mat &srcImag);

int main()
{
    Mat srcImage = imread("D://3.jpg");
    if (!srcImage.data)
    {
        cout << "读入图片错误!" << endl;
        system("pause");
        return -1;
    }
    imshow("原图像", srcImage);
    Mat dstImage = addGaussianNoise(srcImage);
    imshow("添加高斯噪声后的图像", dstImage);
    waitKey();
    return 0;
}

//生成高斯噪声  
double generateGaussianNoise(double mu, double sigma)
{
    //定义小值  
    const double epsilon = numeric_limits<double>::min();
    static double z0, z1;
    static bool flag = false;
    flag = !flag;
    //flag为假构造高斯随机变量X  
    if (!flag)
        return z1 * sigma + mu;
    double u1, u2;
    //构造随机变量  
    do
    {
        u1 = rand() * (1.0 / RAND_MAX);
        u2 = rand() * (1.0 / RAND_MAX);
    } while (u1 <= epsilon);
    //flag为真构造高斯随机变量  
    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;
}

//为图像添加高斯噪声  
Mat addGaussianNoise(Mat &srcImag)
{
    Mat dstImage = srcImag.clone();
    int channels = dstImage.channels();
    int rowsNumber = dstImage.rows;
    int colsNumber = dstImage.cols*channels;
    //判断图像的连续性  
    if (dstImage.isContinuous())
    {
        colsNumber *= rowsNumber;
        rowsNumber = 1;
    }
    for (int i = 0; i < rowsNumber; i++)
    {
        for (int j = 0; j < colsNumber; j++)
        {
            //添加高斯噪声  
            int val = dstImage.ptr<uchar>(i)[j] +
                generateGaussianNoise(2, 0.8) * 32;
            if (val < 0)
                val = 0;
            if (val>255)
                val = 255;
            dstImage.ptr<uchar>(i)[j] = (uchar)val;
        }
    }
    return dstImage;
}

效果图

23.效果图.PNG

4.总结与感想.png

  1. 本人是抱着玩一玩的心态,学习opencv(其实深度学习没有外界说的这么高深,小嗷是白板,而且有工作在身并且于代码无关)
  2. 大家可以把我的数学水平想象成初中水平,毕竟小嗷既不是代码靠吃饭又不是靠数学吃饭,毕业N年
  3. 写文章主要是为了后人少走点弯路,多交点朋友,一起学习
  4. 如果有好的图像识别群拉我进去QQ:631821577
  5. 就我一个白板,最后还是成的,你们别怕,慢慢来把

7.二维码

分享可以无数次,转载成自己文章QQ邮箱通知一下,未经授权请勿转载。

  • 邮箱:631821577@qq.com
  • QQ群:736854977
  • 有什么疑问公众号提问,下班或者周六日回答,ths

算算涉及知识:高数/矩阵分析/线性代数/统计学/OpenCV库/C++或者PY

(今天不懂知识点,基本来自统计学。上学到工作,小嗷摸都没摸统计学。)

怂的话,现在可以放弃。(当然,小嗷会每篇补一点相关的数学。)

线性代数网址(线性代数看视频吧,少年):

http://open.163.com/special/opencourse/daishu.html

代码链接:

https://pan.baidu.com/s/1BWts9jJGgY4Jm4xAa4-5XA

密码:17kb

推荐文件:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值