本站使用了 Pjax 等基于 JavaScript 的开发技术,但您的浏览器已禁用 JavaScript,请开启 JavaScript 以保证网站正常显示!

产生加性零均值高斯噪声

目标

本篇主要介绍了以下几点:

  1. 了解图像噪声,何为图像中的噪声。
  2. 何为加性均值高斯噪声。加性为什么意思?均值又表示了什么?高斯噪声有何特点?
  3. 如何产生加性零均值高斯噪声。如何产生正太分布?Box-Muller变换又是什么?
  4. 如何编程实现?

噪声

实际的图像经常会受到一些随机的影响而退化,可以理解为原图受到干扰和污染。通常就就把这个退化成为噪声(noise)。在我们采集、传输或者处理的过程中都有可能产生噪声,因此噪声的出现是多方面的原因。

在信号处理中我们用概率特征来描述噪声,即噪声出现的概率呈现为什么样子就为什么样子的噪声。就比如本篇的主角高斯噪声,其在信号中出现、分布的概率成高斯分布(正态分布)。也许你会疑问噪声概率分布应是无规律的,现实中也确实噪声严格上是不规律的分布,但是为了简化计算,人们常将噪声理想化,这种理想型的概率分布模型来描述的噪声称为白噪声。白噪声在信号中是典型的,其特点是具有常量功率谱。而高斯噪声属于白噪声的一个特例。

加性零均值高斯噪声

  • 加性

加性噪声的表示为以下表达式

$$ f(x, y) = g(x, y) + v(x,y) $$

g为原图像信号,v为噪声信号,两者关系是独立的,这表示原图信号如何变化与噪声无光,噪声不依赖于图像信号,这种独立与信号的噪声便称为加性噪声(additive noise)。

  • 零均值

均值为零,即噪声为高斯分布,高斯分公式中的均值为0,即高斯分布的对称轴为0。

产生原理步骤

(1)假定图像的灰阶范围是【0,G-1】。取$\sigma > 0$;它的值很小时,相应的噪声也小。
(2)针对每个水平相邻的像素$(x,y),(x,y+1)$产生一对位于【0,1】范围内的独立随机数 $\gamma, \phi$。
(3)计算
$$z_1 = \sigma cos(2\pi\phi)\sqrt{-2\ln\gamma}$$
$$z_2 = \sigma cos(2\pi\phi)\sqrt{-2\ln\gamma}$$

(4)置$f^,(x,y) = g(x,y) + z_1$ 和 $f^,(x,y + 1) = g(x,y+1) + z_2$,其中$g$是输入图像。
(5)置
$$f(x,y)=\begin{cases} 0 &{当f^,(x,y) < 0} \\G-1 &{当f^,(x,y) > G-1} \\f^,(x,y) &\text{其他} \end{cases}$$

$$f(x,y+1)=\begin{cases}0 &{当f^,(x,y+1) < 0}\\G-1 &{当f^,(x,y+1) > G-1}\\f^,(x,y+1) &\text{其他}\end{cases}$$

(6)跳转到步骤3,直到扫描完所有的像素。
何为Box-Muller变换,简单的说通过服从均匀分布的随机变量,来构建服从高斯分布的随机变量的一种方法。推导过程可以阅读知乎的这篇博文Box-Muller变换原理详解

代码实现

  • 头文件
#pragma once

// Copyright https://mangoroom.cn
// License(MIT)
// Author:mango
// gaussian_noise | 高斯噪声
// this is gaussian_noise.h

#include<opencv2/opencv.hpp>


namespace imageprocess
{
    void GaussionNoise(cv::Mat & image);

}//namespace imageproccess
  • 源文件
// Copyright https://mangoroom.cn
// License(MIT)
// Author:mango
// gaussian_noise | 高斯噪声
// this is gaussian_noise.cpp

#include"gaussian_noise.h"
#include<cmath>
#include<random>
#include<ctime>

void imageprocess::GaussionNoise(cv::Mat & image)
{
    // step1: Check the input paramter :检出输入参数
    
    assert(!image.empty());
    assert(3 == image.channels());    // only color image

    // step2: Initialize the value of sigma :初始化sigma值
    double sigma = 1;

    // step3: Initialize 2 random numbers gamma、phi for every pixel: 针对初始化2两个随机数gamma、phi
    std::default_random_engine random(time(NULL));
    std::uniform_real_distribution<double> dis(0, std::nextafter(1, DBL_MAX));

    for (size_t i = 0; i < image.rows - 1; i++)
    {
        for (size_t j = 0; j < image.cols; j++)
        {
            double gamma = dis(random);
            double phi = dis(random);

            // step4: Compute the normal distribution by Box-Muller transfer:通过Box-Muller变换求解正态分布
            double z1 = sigma * std::cos(2 * 3.1415 * phi) * std::sqrt(-2 * log(gamma));
            double z2 = sigma * std::sin(2 * 3.1415 * phi) * std::sqrt(-2 * log(gamma));
            
            // step5: Add the gaussion noise to pixels: 添加噪声到像素点
            for (size_t k = 0; k < 3; k++)
            {
                double f1 = image.at<cv::Vec3b>(i, j)[k] + z1;
                double f2 = image.at<cv::Vec3b>(i + 1, j)[k] + z2;
                image.at<cv::Vec3b>(i, j)[k] = cv::saturate_cast<uchar>(f1);
                image.at<cv::Vec3b>(i + 1, j)[k] = cv::saturate_cast<uchar>(f2);
            }    
        }
    }    
}
  • 测试文件
// Copyright https://mangoroom.cn
// License(MIT)
// Author:mango
// image proccess algorithm  | 图像处理算法
// this is main.cpp

#include"gaussian_noise.h"



int main()
{
    //cv::Mat src = cv::Mat(cv::Size(500, 300), CV_8UC3, cv::Scalar(200,200,200));

    cv::Mat src = cv::imread("./images/lena.jpg");
    
    imageprocess::GaussionNoise(src);

    cv::imshow("sigma=1", src);
    cv::waitKey(0);

    return 0;
}


运行结果

sigma=1.png
sigma=10.png
sigma=30.png

reference

【1】图像处理、分析与机器视觉4th
【2】Box-Muller变换原理详解-知乎


本文由芒果浩明发布,转载请注明来源。
本文链接:https://mangoroom.cn/opencv/create-additive-zero-mean-gaussion-noise.html


 继续浏览关于 图像处理图像处理算法噪声高斯 的文章

 本文最后更新于:2020/01/01 15:21:17,可能因经年累月而与现状有所差异

 引用转载请注明:芒果小屋 > opencv,算法,计算机视觉 > 产生加性零均值高斯噪声