什么叫高斯噪声,并附用OpenCV函数fill()为图像添加高斯噪声的C++代码

图像处理开发需求、图像处理接私活挣零花钱,请加微信/QQ 2487872782
图像处理开发资料、图像处理技术交流请加QQ群,群号 271891601

高斯噪声是指噪声分布的概率密度函数服从高斯分布(正态分布)的一类噪声,其产生的主要原因是由于相机在拍摄时视场较暗且亮度不均匀造成的,同时相机长时间工作使得温度过高也会引起高斯噪声,另外电路元器件自身噪声和互相影响也是造成高斯噪声的重要原因之一。

图像的高斯噪声的概率密度函数如下:

 其中z表示像素值,μ表示高斯噪声的平均值(期望),σ是高斯噪声的标准差,\sigma ^{2}表示高斯噪声的方差。

高斯噪声的相关统计学性质,大家可以参见《概率论与数理统计》的相关章节,这里就不展开细说了。

在OpenCV中,可以用RNG类来产生均匀分布和正态分布(高斯分布)的随机数。RNG的英文全称是Random number generator。

我们可以用RNG类来的成员函数fill()来为图像添加高斯噪声,其函数原型如下:

C++: void RNG::fill(InputOutputArray mat, 
					int distType, 
					InputArray a, 
					InputArray b, 
					bool saturateRange=false )

参数意义如下:

mat:二维或多维矩阵,目前版本中,维数不能超过4。
distType:随机数的分布类型,有两种,即RNG::UNIFORM 或 RNG::NORMAL,前者表示均匀分布,后者表示正态分布(即高斯分布)。
a:随机分布的参数之一。在均匀分布中表示下限(包含),在正态分布(即高斯分布)中,表示均值。
b:分布规律参数之一。在均匀分布中表示上限(包含),在正态分布(即高斯分布)中,表示标准差。saturateRange:这个参数只对均匀分布时有用,具体意义如下:

pre-saturation flag; for uniform distribution only; if true, the method will first convert a and b to the acceptable value range (according to the mat datatype) and then will generate uniformly distributed random numbers within the range [saturate(a), saturate(b)], if saturateRange=false, the method will generate uniformly distributed random numbers in the original range [a, b) and then will saturate them, it means, for example, that theRNG().fill(mat_8u, RNG::UNIFORM, -DBL_MAX, DBL_MAX) will likely produce array mostly filled with 0’s and 255’s, since the range (0, 255) is significantly smaller than [-DBL_MAX, DBL_MAX).

翻译一下上面这段英文,意义如下:

saturateRange为是否对均匀分布的参数进行饱和预处理的标志。
如果值为true,则函数会把区间[a, b]转换到数据深度能表示的范围内,即[saturate(a), saturate(b)]。举个例子,假如数据类型为CV_8U,且[a, b]=[-50, 300],则函数会根据数据类型CV_8U所能表示的范围将区间[a, b]=[-50, 300]转换为[saturate(a), saturate(b)]=[saturate(-50), saturate(300)]=[0, 255]。
如果值为false,则会先按[a, b]=[-50, 300]区间生成均匀分布的随机数,再对超范围的随机数进行饱和处理。显然在这种情况下,0和255这两个值产生的概率要大于其它值。

用函数fill()产生按高斯分布的随机数矩阵后,将随机数矩阵与原图像相加即可得到添加了高斯噪声的图像。

代码如下:

代码中用到的图像下载链接:

链接:https://pan.baidu.com/s/13gKSTVRWbpkHvrTMSYtwBg 提取码:po9z 

//博主微信/QQ 2487872782
//有问题可以联系博主交流
//有图像处理需求也可联系博主
//图像处理技术交流QQ群 271891601
 
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include<opencv2/imgcodecs/imgcodecs.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include <iostream>
#include <time.h>  

using namespace cv;
using namespace std;
 
int main()
{
	//源图像  
	Mat img_input = imread("F:/material/images/P0005-BaoXiaofeng-02.jpg");
 
	Mat img_output(img_input.size(), img_input.type());
	Mat noise(img_input.size(), img_input.type());  

	RNG rng(time(NULL));
	rng.fill(noise, RNG::NORMAL, 10,  36);  /*产生高斯分布矩阵*/
	cv::add(img_input, noise, img_output);
 
	imshow("原图像", img_input);
	imshow("噪声图像", noise);
	imshow("加上高斯噪声后的图像", img_output);
 
 
	waitKey(0);
	return EXIT_SUCCESS;
}

值得注意的是:rng对象在初始化的时候需要一个随机种子值,我们用当前时间作为随机种子值。

运行结果如下图所示:

图像处理开发需求、图像处理接私活挣零花钱,请加微信/QQ 2487872782
图像处理开发资料、图像处理技术交流请加QQ群,群号 271891601

<think>首先,用户的问题是基于系统指令的。指令要求:所有行内数学表达式必须用$...$格式,独立公式用$$...$$格式,LaTeX语法正确,使用中文回答,生成相关问题,在引用的段落末尾添加引用标识如[^1]。 用户的问题是:“我想查找在C++添加随机高斯噪声的方法 请问C++添加随机高斯噪声的实现方法”。这是一个具体的查询,我需要参考提供的引用来回答。 提供的引用包括: - [^1]: 关于PCL点云添加高斯噪声的描述,但用户说这不是真正的噪声点,而是高斯挠动。 - [^2]: C++代码示例,使用rand()生成高斯噪声向量。 - [^3]: Python示例添加高斯噪声图像。 - [^4]: C++-OpenCV添加高斯噪声的描述。 用户明确提到:“上述引用仅供参考,不是用户真正的需求,请尽可能多的参考用户上一次的问题和你的回答。” 但在这个对话中,这是第一条消息,所以没有“上一次的问题”。用户说的是“用户上一次的问题”,但上下文是,这可能是一个连续对话的开始。在系统级指令中,有“参考站内引用”,但在这个消息中,它是给定的引用。 用户说:“上述引用仅供参考,不是用户真正的需求”,所以我应该基于这些引用,但专注于用户的核心需求:在C++添加随机高斯噪声的方法。 用户的需求是:在C++中实现添加随机高斯噪声的方法。我需要提供清晰的回答。 关键引用: - [^2] 提供了一个C++代码示例,使用rand()生成高斯噪声。 - [^4] 提到了OpenCV中的方法,使用cv::RNG。 - [^1] 是关于点云的,但用户可能对通用方法感兴趣。 - [^3] 是Python的,但原理类似。 在引用[^2]中,代码是: ```cpp #include <iostream> #include <cmath> #include <cstdlib> #include <ctime> std::vector<double> generateGaussianNoise(int size, double mean, double stddev) { std::vector<double> noise(size); srand(time(0)); // 初始化随机数生成器 for (int i = 0; i < size; ++i) { noise[i] = mean + stddev * std::rand() / (RAND_MAX); // 生成高斯噪声 } return noise; } int main() { int size = 100; // 噪声向量的大小 double mean = 0.0; // 噪声的均值 double stddev = 1.2; // 噪声的标准差 std::vector<double> noise = generateGaussianNoise(size, mean, stddev); // 输出噪声向量 for (double value : noise) { std::cout << value << " "; } std::cout << std::endl; return 0; } ``` 但是,在引用[^1]中提到,这种方法不是严格的高斯噪声,而是近似或高斯挠动。在其他地方,我知道rand()生成均匀分布,不是高斯分布。所以,我需要澄清这一点。 在C++中,生成高斯噪声的标准方法是使用更好的随机数生成器。例如,使用C++11的<random>库。 引用[^4]提到OpenCV的方法:使用cv::RNG。 我应该提供准确的方法。 步骤: 1. **解释高斯噪声**:高斯噪声是具有均值和标准差的正态分布噪声。 2. **在C++中的实现**: - 使用标准库<random>(C++11或更高)。 - 或者使用OpenCV(如果图像处理相关)。 3. **代码示例**:提供一个正确的例子。 4. **参考引用**:在适当的地方添加引用标识。 用户可能不是针对点云或图像,但引用主要是关于点云和图像的。用户说“添加随机高斯噪声”,可能通用。 我需要确保回答真实可靠。 在引用[^2]的代码中: `noise[i] = mean + stddev * std::rand() / (RAND_MAX);` 这实际上是生成均匀分布噪声,因为rand()是均匀分布。[0, RAND_MAX]上的均匀分布,乘以stddev加mean后,是均匀分布,不是高斯。 正确的方法是使用Box-Muller变换或C++11的std::normal_distribution。 我应该纠正这个错误。 在引用[^4]中,提到了OpenCV的cv::RNG,它可以生成高斯噪声。 最佳实践:推荐使用C++11的标准库。 所以,我的回答应该包括: - 简介:高斯噪声的定义。 - 方法:使用std::normal_distribution。 - 代码示例。 - 添加引用标识。 - 生成相关问题。 回答结构: 1. 澄清引用中的错误。 2. 提供正确方法。 3. 代码实现。 4. 相关问题。 使用中文回答。 数学表达式:如果有公式,用$...$或$$...$$。 例如,高斯分布PDF:$ f(x) = \frac{1}{\sigma \sqrt{2\pi}} e^{-\frac{(x-\mu)^2}{2\sigma^2}} $,但可能不需要。 在描述中,提到均值和标准差。 最终回答: - 解释:在C++添加随机高斯噪声,需要使用正态分布生成器。 - 引用现有资料中的错误:例如,引用[^2]的方法不正确。 - 提供正确代码。 - 链接到引用。 引用标识:在引用的段落末尾添加[^n]。 生成相关问题: - 例如,如何添加高斯噪声图像? - 点云中添加高斯噪声的方法? - 高斯噪声与其他噪声的比较? 用户的需求是通用C++方法,所以相关问题应与C++实现有关。 </think>### 在C++添加随机高斯噪声的实现方法 在C++添加随机高斯噪声,关键在于生成符合正态分布(高斯分布)的随机数。正态分布由均值 $\mu$ 和标准差 $\sigma$ 定义,其概率密度函数为 $f(x) = \frac{1}{\sigma \sqrt{2\pi}} e^{-\frac{(x-\mu)^2}{2\sigma^2}}$。在工程应用中,这通常用于模拟噪声扰动。 需要注意的是,引用[^2]中的示例代码(使用 `std::rand()` 生成噪声)存在错误:`std::rand()` 生成的是均匀分布噪声,而非高斯分布。均匀分布噪声的生成方式是 $\text{noise} = \text{mean} + \text{stddev} \times \text{rand()} / \text{RAND_MAX}$,这会导致噪声分布不满足高斯特性(均值和方差与实际不符)[^1][^2]。标准的高斯噪声生成应使用专门的随机数生成器,如 C++11 标准库的 `<random>` 或 OpenCV 的 `cv::RNG`。 下面我将详细介绍两种正确的实现方法,带完整代码示例。这两种方法均基于 C++11 或更高版本,确保数学正确性和高效性。 --- ### 方法 1: 使用 C++ 标准库 `<random>` 这是推荐的方法,使用 `std::normal_distribution` 生成高斯噪声,适用于通用场景(如信号处理或数据增强)。 **算法原理**: - 使用 `std::random_device` 初始化随机种子,确保随机性。 - `std::normal_distribution` 对象基于 Box-Muller 变换生成正态分布随机数,均值 $\mu$ 和标准差 $\sigma$ 可自定义。 - 输出噪声向量可叠加到原始数据上(如数组或图像像素)。 **代码示例**: ```cpp #include <iostream> #include <vector> #include <random> // 使用 C++11 的随机数库 // 生成高斯噪声向量 std::vector<double> generateGaussianNoise(int size, double mean, double stddev) { std::vector<double> noise(size); // 初始化随机数生成器 std::random_device rd; std::mt19937 gen(rd()); // Mersenne Twister 引擎 std::normal_distribution<> dist(mean, stddev); // 正态分布对象 for (int i = 0; i < size; ++i) { noise[i] = dist(gen); // 生成高斯噪声 } return noise; } int main() { int size = 100; // 噪声向量大小 double mean = 0.0; // 噪声均值 (例如, 0 表示中心噪声) double stddev = 1.0; // 噪声标准差 (例如, 1.0 表示强度) std::vector<double> noise = generateGaussianNoise(size, mean, stddev); // 输出噪声向量 (示例) for (double value : noise) { std::cout << value << " "; } std::cout << std::endl; return 0; } ``` **关键点**: - `std::normal_distribution` 确保生成的噪声严格符合高斯分布,误差控制在 $O(1/\sqrt{n})$ 以内。 - 适用于任意数据序列,时间复杂度为 $O(n)$,空间复杂度为 $O(n)$。 - 在图像处理中,可将噪声叠加到像素值上(需归一化处理),类似引用[^3]的 Python 原理。 --- ### 方法 2: 使用 OpenCV 库 如果处理图像或点云数据(如引用[^1]和[^4]的应用),OpenCV 的 `cv::RNG` 类提供了优化的高斯噪声生成方法。这适用于计算机视觉任务。 **算法原理**: - `cv::RNG` 基于 Multiply-with-Carry 算法,支持多通道高斯噪声生成。 - 方法 `fill()` 或直接调用 `gaussian()` 生成噪声,具有高效行能力。 - 均值和标准差参数可直接设置。 **代码示例**: ```cpp #include <opencv2/opencv.hpp> #include <vector> // 生成高斯噪声添加图像或数据 cv::Mat addGaussianNoise(const cv::Mat& input, double mean, double stddev) { cv::Mat noise = cv::Mat::zeros(input.size(), input.type()); cv::RNG rng(cv::getTickCount()); // 初始化随机数生成器 // 生成高斯噪声矩阵 rng.fill(noise, cv::RNG::NORMAL, mean, stddev); cv::Mat output; cv::add(input, noise, output); // 叠加噪声到原始数据 return output; } int main() { // 示例:加载图像添加噪声 cv::Mat image = cv::imread("input.jpg", cv::IMREAD_GRAYSCALE); if (image.empty()) { std::cerr << "Error loading image" << std::endl; return -1; } double mean = 0.0; // 噪声均值 double stddev = 25.0; // 噪声标准差 (值越大,噪声越强) cv::Mat noisyImage = addGaussianNoise(image, mean, stddev); cv::imwrite("noisy_image.jpg", noisyImage); return 0; } ``` **关键点**: - 适用于图像或点云数据,OpenCV 处理多通道噪声更高效(引用[^4]描述了类似方法)。 - 在点云中添加噪声时(如引用[^1]),需处理每个点的坐标:$p_{\text{noisy}} = p_{\text{original}} + \mathcal{N}(\mu, \sigma^2)$,确保是添加独立噪声点而非全局扰动[^1]。 - 性能优于纯标准库方法,尤其在 GPU 加速场景。 --- ### 常见问题与注意事项 1. **精度问题**:确保使用 `double` 或 `float` 类型避免舍入误差,噪声强度由 $\sigma$ 控制($\sigma$ 越大,噪声越明显)。 2. **种子初始化**:随机种子应用 `std::random_device` 或 `time(0)` 保证每次运行不同。 3. **引用对比**:引用[^2]的 `rand()` 方法不推荐,因为它生成均匀噪声;正确方法应优先使用 `<random>` 或 OpenCV[^1][^2][^4]。 4. **应用场景**: - 通用数据:使用方法 1。 - 图像/点云:使用方法 2(OpenCV 已优化)。 如需完整项目代码或更多优化(如行生成),请参考 OpenCV 文档或 C++ `<random>` 库指南。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

昊虹AI笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值