關於噪聲生成,我們可以使用rand(256)這樣的函數生成256*256大小的隨機噪聲,這樣的噪聲我們稱為白噪聲。
不過白噪聲過於隨機,有時候並不能反映真實的噪聲,比如山丘,紋理等不那么“隨機”的起伏。
因此有人開發了柏林噪聲,該噪聲在圖形學中的地形,雲彩或火焰生成等方法中經常使用。
下面介紹下算法過程:
1. 首先定義網格大小和待生成圖像的大小。
2. 對網格每一個頂點生成隨機方向向量,就是下圖紅色的向量。
3. 遍歷圖像每一個像素,計算該像素到該像素所在網格四個頂點組成的向量d,就是下圖右邊藍色的向量。

4. 計算網格頂點隨機方向向量與3中求得的向量d的點積,得到方向權重。
5. 利用平滑函數對dx、dy平滑,得到比例系數sx、sy。平滑函數要符合f(0) = 0,f(0.5)=0.5,f(1)=1的方程,最好滿足二階導數連續。
6. 根據方向權重與平滑函數得到的系數對當前像素賦值。
matlab代碼如下:
clear all;close all;clc; n = 256; %噪聲圖像大小 cellsize = 10; %網格大小,不同的大小會產生不同尺度的噪聲 G = rand(2,n/cellsize+2,n/cellsize+2)-0.5; %每個網格頂點的隨機方向向量 img = zeros(n); for i=1:n for j=1:n indi = i/cellsize+1; indj = j/cellsize+1; floori = floor(indi); floorj = floor(indj); d00 = [indi indj] - [floori floorj]; %計算當前點到當前網格四個角點距離 d10 = [indi indj] - [floori+1 floorj]; d01 = [indi indj] - [floori floorj+1]; d11 = [indi indj] - [floori+1 floorj+1]; s = sum(G(:,floori,floorj).*d00'); %當前網格四個角點方向向量對當前點的方向權重 t = sum(G(:,floori+1,floorj).*d10'); u = sum(G(:,floori,floorj+1).*d01'); v = sum(G(:,floori+1,floorj+1).*d11'); dx = indi - floori; dy = indj - floorj; sy = 6*dy.^5-15*dy.^4+10*dy.^3; %符合f(0) = 0,f(0.5)=0.5,f(1)=1的方程,滿足二階導數連續 sx = 6*dx.^5-15*dx.^4+10*dx.^3; %用於描述網格內的起伏 a = s + (t-s)*sx; b = u + (v-u)*sx; img(i,j) = a + (b-a)*sy; end end imshow(img,[])
網格25生成的圖像:

網格10生成的圖像:

最后不同網格尺度生成的噪聲也能夠進行疊加,得到更多種類的噪聲。
參考:
https://blog.csdn.net/candycat1992/article/details/50346469
http://www.twinklingstar.cn/2015/2581/classical-perlin-noise/
