【PBRT】圆盘均匀采样,python实现

  圆盘内的均匀采样问题,是一个很有意思,也很常被考到的问题。在一个圆形内,均匀采点,怎么保证均匀且随机
  有三种方法:1、正方形采样;2、极坐标采样(错误!);3、圆盘采样

一、正方形采样(Reject Method)

  最容易想到的方法就是在正方形内采样,比如要在圆心为原点,半径为1的圆内均匀采样,可以在 x 从 [-1, 1],y 从 -[-1, 1] 的正方形内均匀采样,然后把不在圆内的点剔除即可。python代码如下:

import numpy as np
from pylab import *
import matplotlib.pyplot as plt
import random

figure(figsize=(12, 12), dpi = 80)
subplot(1, 1, 1)

# 画圆
theta = np.linspace(0, 2 * np.pi, 800)
x,y = np.cos(theta), np.sin(theta)
plot(x, y, color = 'red', linewidth = 2.0)

# 画随机点
a = []
b = []

for i in range(10000):
    a.append(random.uniform(-1, 1))
    b.append(random.uniform(-1, 1))

plt.xlim(xmax = 1, xmin = -1)
plt.ylim(ymax = 1, ymin = -1)

scatter(a, b, s = 1.5, color = (0., 0.5, 0.))

show()

  代码在正方形内,随机取了 10000 个二维坐标点,然后绘制出点和圆。可以看到随机且均匀,但是很明显的就是效率问题,有大量的点是要被扔掉的,所以不可取。不过此方法虽然效率低,但是可以作为 ground truth

二、极坐标采样

  还有一种很容易想到但是不对的方法,就是按照极坐标采样,也就是先按照角度在 [0, 2 π 2\pi 2π ] 范围内均匀随机采样一个角度,然后在 [0, 1] 上随机均匀采样一个长度,就可以得到一个点在圆中的位置。代码如下:

# 和上边只有 for 循环内不一样
for i in range(10000):
    theta = random.uniform(0, 2 * np.pi)
    r = random.uniform(0, 1)
    a.append(r * math.cos(theta))
    b.append(r * math.sin(theta))

  可以看到很明显的不均匀。所以是不对的!

三、圆盘采样

  我们知道圆的面积是 π r 2 \pi r^2 πr2,圆环的面积是 π ( r 1 2 − r 2 2 ) \pi ({r_1}^2 - {r_2}^2) π(r12r22),在极限情况下,圆环的面积是 π ( ( r 1 + Δ r ) 2 − r 1 2 ) \pi ((r_1 + \Delta r)^2 - {r_1}^2) π((r1+Δr)2r12),其实就是周长 2 π r 2\pi r 2πr,那么我们可以发现,在角度均匀采样的前提下,同样的 Δ r \Delta r Δr 会因为 r r r 大小的不同而导致面积不同,所以概率密度就不均匀了,我们想要概率密度均匀,那么采样的均匀性应该和面积线性相关,也就是对 r 2 r^2 r2 进行线性均匀采样,这样算出来的阴线长度 r r r 才是对的,这样才能保证,随机采样出来的每一个极小圆盘面积是相同的

for i in range(10000):
    theta = random.uniform(0, 2 * np.pi)
    r = math.sqrt(random.uniform(0, 1 ** 2))
    a.append(r * math.cos(theta))
    b.append(r * math.sin(theta))
  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值