均匀分布产生高斯分布

简介

上图像处理课的小作业,顺便复习概率论!!

这里只用了三种方法,未完待续。。。

方法和证明

已经写成word了,不想再打一遍了awsl。

逆变换法

在这里插入图片描述

Box-Muller算法

在这里插入图片描述

拒绝采样

在这里插入图片描述

代码

逆变换代码

clc;
clear;

% 验证高斯噪声--------------
ep = 1e-3;  %间隔
x = -4 : ep : 4;
num = length(x);
U = rand(1, num);
gaussian = @(u) sqrt(2) * erfinv(u);	%高斯分布的逆累积分布函数
y = gaussian(2 * U - 1);
[f, xi] = ksdensity(y, x);				%绘制概率分布
% 作图
figure(1);
plot(x, f);


% 添加高斯噪声--------------
img = imread('lena.bmp');
Nvar = [0 50];	% 均值0,标准差50
rate = 0.5;		% 50%的区域加噪声
img_processed = add_Guassian_noise(img, Nvar, rate);
% 原图
figure(2);
subplot(1, 2, 1);
imshow(img);
title('src');
% 处理后
subplot(1, 2, 2);
imshow(img_processed);
title('dst');

function dst = add_Guassian_noise(src, Nvar, rate)
% src --> raw img to be processed
% Nvar --> [mean, std]
% rate --> the rate of noise
	[r, c] = size(src);
	src = double(src);
	flag = (rand(r,c) > rate);
	U = rand(r, c);
	noise = Nvar(2) * sqrt(2) * erfinv(2 * U - 1) + Nvar(1);
	dst = src + noise .* flag;
	dst = uint8(dst);
	
end

Box-Muller算法代码

clc;
clear;

% 验证高斯噪声---------------
ep = 1e-3;  %间隔
x = -4 : ep : 4;
num = length(x);
U1 = rand(1, num);
U2 = rand(1, num);
y = sqrt(-2 * log(U1)) .* cos(2*pi*U2);		%Box-Muller公式
[f, xi] = ksdensity(y, x);
figure(1);
plot(x, f);

% 添加高斯噪声--------------
img = imread('lena.bmp');
Nvar = [0 50];		% 均值0,标准差50
rate = 0.5;			% 50%的区域加噪声
img_processed = add_Gaussian_noise(img, Nvar, rate);
% 作图
figure(2);
subplot(1, 2, 1);
imshow(img);
title('src');

subplot(1, 2, 2);
imshow(img_processed);
title('dst');

function dst = add_Gaussian_noise(src, Nvar, rate)
% src --> raw img to be processed
% Nvar --> [mean, std]
% rate --> the rate of noise
	[r, c] = size(src);
	src = double(src);
	flag = (rand(r,c) > rate);
	U1 = rand(r, c);
	U2 = rand(r, c);
	noise = Nvar(2) * sqrt(-2 * log(U1)) .* cos(2 * pi * U2) + Nvar(1);
	dst = src + noise .* flag;
	dst = uint8(dst);
	
end

拒绝采样代码

clc;
clear;

% 检验高斯分布------------
ep = 1e-3;
x = -5 : ep : 5;	%five sigma
top = 4 * 1 / 10;	%由于均匀分布U~(-5,5),则p=0.1;但高斯分布最大值0.4,因此k取4。
sample_num = 1e5;	%采样点1e5个
U = rand(1, sample_num) * 10 - 5;
gaussian = @(x) 1/sqrt(2*pi) * exp(-x.^2 / 2);
sample_id = (rand(1, sample_num) * top) <= gaussian(U);		%接受的id
sample = U(sample_id);
[f, xi] = ksdensity(sample, x);
figure(1);
plot(x, f);

% 添加高斯噪声--------------
img = imread('lena.bmp');
Nvar = [0 50];
rate = 0.5;
img_processed = add_Guassian_noise(img, Nvar, rate);
% 作图
figure(2);
subplot(1, 2, 1);
imshow(img);
title('src');

subplot(1, 2, 2);
imshow(img_processed);
title('dst');

function dst = add_Guassian_noise(src, Nvar, rate)
% src --> raw img to be processed
% Nvar --> [mean, std]
% rate --> the rate of noise
	[r, c] = size(src);
	src = double(src);
	flag = (rand(r,c) < rate);
    sample_num = r * c;	%每次取样r*c个,得到接受的个数n
    noise = [];
    top = 4 * 1 / 10;
    while(length(noise) < sample_num)	%取样n达到r*c后退出循环
        U = 10 * rand(1, sample_num) - 5;
        gau = 1/sqrt(2*pi) * exp(-U.^2 / 2);
        sample_id = (rand(1, sample_num) * top <= gau);
        noise = [noise U(sample_id)];
    end
    noise = noise(1, 1:sample_num);
    noise = reshape(noise, [r, c]);
	noise = Nvar(2) * noise + Nvar(1);
	dst = src + noise .* flag;
	dst = uint8(dst);
end

效果

检验

在这里插入图片描述

算法效果

在这里插入图片描述

引用

  1. https://blog.csdn.net/renwudao24/article/details/44463489
  2. https://www.jianshu.com/p/cb916e1ba399
  3. https://blog.csdn.net/libing_zeng/article/details/81842245?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1
产生均匀随机数的迭代方法: 假设我们已经有了一个随机数生成器,可以生成 $[0,1]$ 之间均匀分布的随机数,那么我们可以通过反复调用该随机数生成器来得到多个均匀随机数。 例如,我们想要生成 $[a,b]$ 之间的均匀分布的随机数,可以先生成 $[0,1]$ 之间的均匀分布随机数 $x$,然后通过线性变换的方法将 $x$ 转换为 $[a,b]$ 之间的随机数: $$ y = a + x \cdot (b - a) $$ 其中 $a$ 和 $b$ 分别是区间的左右端点,$x$ 是 $[0,1]$ 之间的均匀分布的随机数,$y$ 是 $[a,b]$ 之间的均匀分布的随机数。 代码实现: ```c++ #include <iostream> #include <random> int main() { std::random_device rand_dev; // 从硬件获得种子 std::mt19937 generator(rand_dev()); // 用 Mersenne Twister 算法生成随机数 double a = 0.0, b = 1.0; for (int i = 0; i < 10; ++i) { double x = std::generate_canonical<double, 10>(generator); // 生成 [0,1] 之间均匀分布的随机数 double y = a + x * (b - a); // 线性变换 std::cout << y << std::endl; // 输出 [a,b] 之间均匀分布的随机数 } return 0; } ``` 产生高斯分布随机数的迭代方法: 高斯分布又称正态分布,是一种在统计学中广泛使用的概率分布。高斯分布的概率密度函数为: $$ f(x) = \frac{1}{\sqrt{2\pi}\sigma} \cdot e^{-\frac{(x-\mu)^2}{2\sigma^2}} $$ 其中 $\mu$ 是均值,$\sigma$ 是标准差。 我们可以使用 Box-Muller 变换或 Ziggurat 算法来生成高斯分布的随机数。 Box-Muller 变换是一种基于极坐标系的变换方法,它可以将两个独立的均匀分布的随机数转换为两个独立的正态分布的随机数。具体实现方法如下: - 生成两个独立的均匀分布的随机数 $u_1$ 和 $u_2$,取值范围为 $[0,1]$; - 计算极径 $r$ 和极角 $\theta$:$r = \sqrt{-2\ln u_1}$,$\theta = 2\pi u_2$; - 计算正态分布的随机数 $x$ 和 $y$:$x = \mu + \sigma r \cos\theta$,$y = \mu + \sigma r \sin\theta$。 其中 $\mu$ 和 $\sigma$ 分别是高斯分布的均值和标准差。 代码实现: ```c++ #include <iostream> #include <random> #include <cmath> int main() { std::random_device rand_dev; // 从硬件获得种子 std::mt19937 generator(rand_dev()); // 用 Mersenne Twister 算法生成随机数 double mu = 0.0, sigma = 1.0; for (int i = 0; i < 10; ++i) { double u1 = std::generate_canonical<double, 10>(generator); // 生成 [0,1] 之间均匀分布的随机数 double u2 = std::generate_canonical<double, 10>(generator); // 生成 [0,1] 之间均匀分布的随机数 double r = std::sqrt(-2.0 * std::log(u1)); double theta = 2.0 * M_PI * u2; double x = mu + sigma * r * std::cos(theta); // 正态分布的随机数 std::cout << x << std::endl; // 输出正态分布的随机数 } return 0; } ``` Ziggurat 算法是一种更高效的生成高斯分布随机数的算法,它利用了高斯分布的对称性和截尾性,可以在常数时间内生成高斯分布的随机数。不过实现比较复杂,这里不作详细介绍。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值