【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 randomfigure(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\pi2π ] 范圍內均勻隨機采樣一個角度,然后在 [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))??可以看到很明顯的不均勻。所以是不對的!
三、圓盤采樣
??我們知道圓的面積是 πr2\pi r^2πr2,圓環的面積是 π(r12?r22)\pi ({r_1}^2 - {r_2}^2)π(r1?2?r2?2),在極限情況下,圓環的面積是 π((r1+Δr)2?r12)\pi ((r_1 + \Delta r)^2 - {r_1}^2)π((r1?+Δr)2?r1?2),其實就是周長 2πr2\pi r2πr,那么我們可以發現,在角度均勻采樣的前提下,同樣的 Δr\Delta rΔr 會因為 rrr 大小的不同而導致面積不同,所以概率密度就不均勻了,我們想要概率密度均勻,那么采樣的均勻性應該和面積線性相關,也就是對 r2r^2r2 進行線性均勻采樣,這樣算出來的陰線長度 rrr 才是對的,這樣才能保證,隨機采樣出來的每一個極小圓盤面積是相同的。
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))總結
以上是生活随笔為你收集整理的【PBRT】圆盘均匀采样,python实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 西门子S7系列PLC的主要种类及应用软件
- 下一篇: 华为虚拟机eNSP命令大全(所有命令)