2015-10-06 39 views
4

我正在尋找一種能產生與藍噪聲相似的點放置結果的算法。無限藍噪聲

enter image description here

但是,它需要一個無限平面工作。在給出邊界框的情況下,它返回所有落入其中的點的位置。任何幫助,將不勝感激。我做了很多研究,沒有找到適合我需要的東西。

+0

這張照片取自[José's Sketchbook](http://www.joesfer.com/?p=108)?無論如何,由於正確的圖案由左側的圖塊組成,因此您只需手動計算左側圖塊中的點,然後跟蹤使用哪個圖塊以及多少次。 – usr2564301

+0

我第一次聽到Robert Ulichney在1987年出版的「數字半色調」一書中的「藍噪聲」一詞。他可能已經發明瞭這個術語,我不確定。在任何情況下,本書都有一些用於將灰度級別轉換爲藍色噪聲模式的好算法,但有一整章專門討論了該主題。算法應該是非常高效的。 –

回答

5

最後我設法得到了結果。與藍噪聲特性 生成點分佈的

一種方式是通過泊松磁盤分佈

的裝置從所述紙快速泊松磁盤採樣在 任意尺寸,羅伯特·布里森算法繼我有:

enter image description here

步驟男人

步驟0初始化n維背景網格以存儲 樣本並加速空間搜索。我們選取單元格大小爲r/sqrt(n)爲界的 ,以便每個網格單元最多包含一個樣本,因此網格可以實現爲一個簡單的n維 整數數組:缺省值-1指示無樣本,非負 整數給出了位於單元格中的樣本的索引

第1步。選擇從 域中統一隨機選擇的初始樣本x0。將其插入到背景網格中,並使用此索引(零)初始化「活動列表」(樣本索引數組)。

第2步。當活動列表不爲空時,從 (例如i)中選擇一個隨機索引。在xi周圍半徑r和2r之間生成多達k個點,均勻地從 球形環面選擇。對於 轉彎中的每個點,檢查它是否在現有樣本的距離r內(使用 背景網格僅測試附近的樣本)。如果一個點遠離現有樣本足夠遠,則將其作爲下一個樣本發出並將其添加到 活動列表中。如果在k次嘗試後沒有找到這樣的點,取而代之的是 將i從活動列表中刪除。

請注意,爲了簡單起見,我跳過了第0步。儘管運行時間仍然合理。它是<.5s。實施這一步肯定會提高性能。


以下是Processing中的示例代碼。它是一種建立在Java之上的語言,因此語法非常相似。爲了您的目的翻譯它不應該很難。

import java.util.List; 
import java.util.Collections; 

List<PVector> poisson_disk_sampling(int k, int r, int size) 
{ 
    List<PVector> samples = new ArrayList<PVector>(); 
    List<PVector> active_list = new ArrayList<PVector>(); 
    active_list.add(new PVector(random(size), random(size))); 

    int len; 
    while ((len = active_list.size()) > 0) { 
    // picks random index uniformly at random from the active list 
    int index = int(random(len)); 
    Collections.swap(active_list, len-1, index); 
    PVector sample = active_list.get(len-1); 
    boolean found = false; 
    for (int i = 0; i < k; ++i) { 
     // generates a point uniformly at random in the sample's 
     // disk situated at a distance from r to 2*r 
     float angle = 2*PI*random(1); 
     float radius = random(r) + r; 
     PVector dv = new PVector(radius*cos(angle), radius*sin(angle)); 
     PVector new_sample = dv.add(sample); 

     boolean ok = true; 
     for (int j = 0; j < samples.size(); ++j) { 
     if (dist(new_sample.x, new_sample.y, 
       samples.get(j).x, samples.get(j).y) <= r) 
     { 
       ok = false; 
       break; 
     } 
     } 
     if (ok) { 
     if (0 <= new_sample.x && new_sample.x < size && 
      0 <= new_sample.y && new_sample.y < size) 
     { 
      samples.add(new_sample); 
      active_list.add(new_sample); 
      len++; 
      found = true; 
     } 
     } 
    } 
    if (!found) 
     active_list.remove(active_list.size()-1); 
    } 

    return samples; 
} 


List<PVector> samples; 
void setup() { 
    int SIZE = 500; 
    size(500, 500); 
    background(255); 
    strokeWeight(4); 
    noLoop(); 

    samples = poisson_disk_sampling(30, 10, SIZE); 
} 

void draw() { 
    for (PVector sample : samples) 
    point(sample.x, sample.y); 

} 

但是,它需要一個無限平面工作。

您可以使用參數size控制框的大小。 r控制點之間的相對距離。 k控制在拒絕電流前應嘗試多少新樣本。該文件建議k=30

+0

謝謝你的快速回答。這看起來很有希望。雖然我誤解了你的部分代碼,或者我在解釋結束時不太清楚。當我說無限的飛機時,我的意思是我可以在各個地點提供儘可能多的邊界框,並且它們內部的點總是排成一行。如果我誤解了你的代碼,請解釋一下。 –

+0

@BryanBrownTheDudeFromCI,所以你的意思是你的方法應該採用幾個邊界框作爲輸入,它應該返回所有這些樣本? – svs

+0

是的。就像我可以添加多個框,但不是一次。一次一個。並且每個盒子可以允許點彼此流動,如果盒子彼此相鄰則不會重疊。或者如果部分框重疊,則返回相同的點。 現在查看您的代碼,我認爲可以使用種子並擴大搜索範圍以使其正常工作。謝謝你的幫助! :) –