C++ OpenCV实现与添加椒盐噪声和高斯噪音

 更新时间:2023年09月13日 09:47:01   作者:锡兰_CC  
图像噪声是图像在获取或是传输过程中受到随机信号干扰,妨碍人们对图像理解及分析处理的信号,本文为大家整理了C++结合OpenCV为图像添加椒盐噪声和高斯噪音的代码,需要的可以收藏一下

一、什么是图像噪音

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

二、椒盐噪声

椒盐噪声是数字图像中的常见噪声,一般是由图像传感器、传输信道及解码处理等产生的黑白相见的亮暗点噪声,椒盐噪声常由图像切割产生。椒盐噪声是指两种噪声:盐噪声(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;
}

效果图

三、高斯噪声

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

#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;
}

效果图

以上就是C++ OpenCV实现与添加椒盐噪声和高斯噪音的详细内容,更多关于C++ OpenCV噪声的资料请关注脚本之家其它相关文章!

相关文章

  • c++ vector对象相关总结

    c++ vector对象相关总结

    这篇文章主要介绍了c++ vector对象的相关资料,帮助大家更好的理解和学习使用c++,感兴趣的朋友可以了解下
    2021-02-02
  • libevent库的使用方法实例

    libevent库的使用方法实例

    这篇文章主要介绍了libevent库的使用方法实例,有需要的朋友可以参考一下
    2013-12-12
  • C语言入门篇--充分理解操作符

    C语言入门篇--充分理解操作符

    本篇文章是基础篇,适合c语言刚入门的朋友,本文主要介绍了c语言的操作符基础理论,希望可以帮助大家快速入门c语言的世界,更好的理解c语言
    2021-08-08
  • c语言获取文件大小的示例

    c语言获取文件大小的示例

    在C语言中测试文件的大小,主要使用二个标准函数,下面是使用示例,需要的朋友可以参考下
    2014-02-02
  • C语言实现520表白代码 祝你表白成功!

    C语言实现520表白代码 祝你表白成功!

    这篇文章主要为大家详细介绍了C语言实现520表白代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-05-05
  • C语言操作符基础知识详解

    C语言操作符基础知识详解

    这篇文章主要以图文结合的方式为大家详细介绍了C语言位运算基础知识,感兴趣的小伙伴们可以参考一下,希望能给你带来帮助
    2021-10-10
  • QT计算时间差的方法详解

    QT计算时间差的方法详解

    这篇文章主要为大家详细介绍了利用QT实现计算两个时间的时间差的方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-12-12
  • C++实现与Lua相互调用的示例详解

    C++实现与Lua相互调用的示例详解

    这篇文章主要为大家详细介绍了C++实现与Lua相互调用的方法,文中的示例代码讲解详细,具有一定的学习价值,感兴趣的小伙伴可以了解一下
    2023-03-03
  • C++学习之异常机制详解

    C++学习之异常机制详解

    C++中的异常处理机制可以帮助我们处理程序在运行时可能会遇到的异常情况,比如内存分配错误、文件打开失败等。本文就和大家详细讲讲C++中异常机制的具体使用吧
    2023-04-04
  • C++ set到底是什么

    C++ set到底是什么

    这篇文章主要讨论C++ 中得set到底是什么?在C++当中,这几个东西的名字叫做vector、set和map,它们有一个共同的名字叫做STL(标准模板库)容器。下面来看看文章是怎么介绍得吧,需要的朋友可以参考一下哦
    2021-11-11

最新评论