一、什么是图像噪音

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

二、椒盐噪声

  椒盐噪声是数字图像中的常见噪声,一般是由图像传感器、传输信道及解码处理等产生的黑白相见的亮暗点噪声,椒盐噪声常由图像切割产生。椒盐噪声是指两种噪声:盐噪声(salt noise)及椒噪声(pepper noise)。盐噪声一般是白色噪声,椒噪声一般是黑色噪声,前者高灰度噪声,后者属于低灰度噪声,一般两种噪声同时出现,呈现在图像上就是黑白杂点。图像去除脉冲干扰及椒盐噪声最常用的算法是中值滤波,图像模拟添加椒盐噪声是通过随机获取像素值点并设置为高亮点来实现的。
  下面时

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <cstdlib>
using namespace cv;

// 向图像添加椒盐噪声的函数
Mat addSaltNoise(Mat srcImage, int n)
{
	Mat resultImage = srcImage.clone();

	// 循环添加椒盐噪声'n'次
	for (int k = 0; k < n; k++)
	{
		// 随机选择一个像素位置
		int i = rand() % resultImage.cols;
		int j = rand() % resultImage.rows;

		// 检查图像的通道数
		// 如果是灰度图像(1个通道),将像素值设置为255
		if (resultImage.channels() == 1)
			resultImage.at<uchar>(j, i) = 255;
		else // 如果是彩色图像(3个通道),将所有通道的值都设置为255
		{
			resultImage.at<Vec3b>(j, i)[0] = 255;
			resultImage.at<Vec3b>(j, i)[1] = 255;
			resultImage.at<Vec3b>(j, i)[2] = 255;
		}
	}

	return resultImage;
}

int main()
{
	// 从文件加载源图像
	Mat srcImage = imread("C://Users//86173//Desktop//cc.png");

	// 检查图像数据是否成功加载
	if (!srcImage.data)
		return -1;

	// 调用addSaltNoise函数,传入源图像和要添加的噪声像素数量
	Mat resultImage = addSaltNoise(srcImage, 5000);

	// 显示原始图像和带有噪声的图像
	imshow("srcImage", srcImage);
	imshow("resultImage", resultImage);

	// 等待按键输入,然后退出程序
	waitKey(0);
	return 0;
}

【OpenCV • c++】图像噪音 | 椒盐噪音 | 高斯噪音-LMLPHP

三、高斯噪声

  高斯噪声是指概率密度函数服从高斯分布(即正态分布)的一类噪声。如果一个噪声,它的幅度服从高斯分布,而它的功率谱密度又是分布均匀的,则称它为高斯白噪声。高斯白噪声的二阶矩不想关,一阶矩为常数,是指先后信号在时间上的相关性。高斯白噪声包括热噪声和散粒噪声。高斯噪声完全由其时变平均值和两瞬时的协方差函数来确定,若噪声为平稳的,则平均值与时间无关,而协方差函数则变成仅和所考虑的两瞬时之方差有关的相关函数,它在意义上等效于功率谱密度。高斯噪声可以由大量独立的脉冲产生,从而在任何有限时间间隔内,这些脉冲中的每一个脉冲值与所有脉冲值的总和相比都可以忽略不计。

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <cstdlib>
#include <limits>
#include <cmath>

using namespace cv;
using namespace std;

// 生成高斯分布的随机数
double generateGaussianNoise(double mu, double sigma)
{
    // 定义一个特别小的值
    const double epsilon = numeric_limits<double>::min();

    static double z0, z1;
    static bool flag = false;

    flag = !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 <= epsilon);

    // flag为真构造高斯随机变量X
    z0 = sqrt(-2.0 * log(u1)) * cos(2 * CV_PI * u2);
    z1 = sqrt(-2.0 * log(u1)) * sin(2 * CV_PI * u2);

    return z1 * sigma + mu;
}

// 为图像添加高斯噪声
Mat addGaussianNoise(Mat& srcImage)
{
    Mat resultImage = srcImage.clone();    // 深拷贝,克隆
    int channels = resultImage.channels();    // 获取图像的通道
    int nRows = resultImage.rows;    // 图像的行数
    int nCols = resultImage.cols * channels;   // 图像的总列数

    // 判断图像的连续性
    if (resultImage.isContinuous())    // 判断矩阵是否连续,若连续,我们相当于只需要遍历一个一维数组
    {
        nCols *= nRows;
        nRows = 1;
    }

    for (int i = 0; i < nRows; i++)
    {
        for (int j = 0; j < nCols; j++)
        {
            // 添加高斯噪声
            int val = resultImage.ptr<uchar>(i)[j] + generateGaussianNoise(2, 0.8) * 32;

            if (val < 0)
                val = 0;

            if (val > 255)
                val = 255;

            resultImage.ptr<uchar>(i)[j] = (uchar)val;
        }
    }

    return resultImage;
}

int main()
{
    Mat srcImage = imread("C://Users//86173//Desktop//cc.png");

    if (!srcImage.data)
        return -1;

    imshow("srcImage", srcImage);

    Mat resultImage = addGaussianNoise(srcImage);

    imshow("resultImage", resultImage);

    waitKey(0);

    return 0;
}

【OpenCV • c++】图像噪音 | 椒盐噪音 | 高斯噪音-LMLPHP

【OpenCV • c++】图像噪音 | 椒盐噪音 | 高斯噪音-LMLPHP

更多专栏订阅推荐:

【OpenCV • c++】图像噪音 | 椒盐噪音 | 高斯噪音-LMLPHP

09-13 13:05