给定一个(可能是开放的)具有密度纹理和多个点的网格,我需要根据网格上的密度分布这些点。
到目前为止,我已经制定了几个解决方案,其中一些有效,有些则无效。我尝试的算法之一是通过弹簧连接点并模拟分布直到平衡(或直到解决方案适合用户需求)。来源Retiling Polygonal Surfaces 不幸的是,对于更高的点数(> 2k),这有点慢,所以我需要一个可行的解决方案来获得更高的数字。
我已经有了一些想法,但我想听听是否有一些标准解决方案。我试过谷歌,但我使用的关键字(分布密度离散)只显示处理与我的其他问题的页面。如果你指出要搜索的正确词语,我会很高兴。
答案 0 :(得分:5)
通常,在具有任意密度函数的任意空间中,您可以通过rejection sampling得到合理的近似值。
D
。p
。r
范围内选择一个随机数[0,D)
。p
的密度大于r
,请接受p
作为您的一个点。我不确定这适用于您的案件有多容易。在网格上生成随机,均匀分布的点本身就像一个棘手的问题。我能想到的唯一解决方案是计算网格中每个三角形的面积,随机选择一个与其面积成比例的三角形,并在三角形内选择一个random point。我相信你可以在O(logN)的N个三角形上做这个选择。
但是考虑到你可能会抛出大部分这些点,这可能会比你当前的方法更糟糕,因为网格足够大且密度函数非常令人不快(即最大值远大于平均值)
与任何类型的随机抽样一样,在它开始类似于基础分布之前需要相当多的几点;一小部分点可能看起来或多或少随机。但是你可以通过某种准随机的点放置方法解决这个问题(即使使用大型集合,也可能会产生更好的结果)。
首先想到的是上述方法与@ BlackBear算法的混合。您可以计算每个三角形的面积和平均密度,并使用它来确定每个三角形必须包含的点数。然后,要将点实际放置在三角形内,请使用拒绝抽样方法。
答案 1 :(得分:4)
这是我的想法:
现在,矩形越小,得到的结果就越精确。我做了一个小测试程序(C#使用慢速方法,即位图上的GetPixel和SetPixel),这里是结果,假设10k点,256x256像素图像。图片显示该算法适用于2 ^ 2,10 ^ 2,50 ^ 2和90 ^ 2部分:
这是基准:
parts time
------------------------
2 00:00:00.7957087
10 00:00:00.6713345
50 00:00:00.5873524
90 00:00:00.4153544
答案 2 :(得分:0)
根据任意函数分布点云的问题与dithering灰度图像同构为黑白图像。 algorithms都具有与O(N)成比例的运行时复杂度(其中N是原始图像/位图/网格/中的点数),使用像拜耳矩阵ordered dithering这样的简单方法只执行一次每点浮点比较,更复杂的error diffusion方法运行更像O(24N),但产生更好的结果,产生更少的工件。
使用简单的高斯密度函数,简单的拜耳矩阵方法可以得到令人惊讶的良好结果,小到32x32矩阵:
在给定矩阵的情况下,可以直接生成基于矩阵的有序抖动:
matrix = generate_bayer(32);
for (y=0; y<height; y++) {
for (var x=0; x<width; x++) {
i = x % matrix.length;
j = y % matrix.length;
function_val = gaussian(x, y); #returns a value 0<=x<=1
scaled_val = function_val * matrix.length * matrix.length; #scale to the max element in the matrix
if (scaled_val > matrix[j][i]) {
draw_pixel(x, y);
}
}
}
生成矩阵稍微有些棘手,但这里是一种迭代方法,用于matricies,其边长是2的幂:
//size should be a power of 2, and is the length of a side of the matrix
function generate_bayer(size) {
base = [[0, 2],
[3, 1]];
old_matrix = base;
mult = 4;
//successively double the size of the matrix, using the previous one as the base
while (old_matrix.length < size) {
//generate a new matrix of the proper dimensions
new_size = old_matrix.length * 2;
matrix = new Array[new_size][new_size];
for (y=0; y<old_matrix.length; y++) {
for (x=0; x<old_matrix[y].length; x++) {
//fill in the new 4x4 submatrix
matrix[y*2] [x*2] = old_matrix[y][x] + (mult * base[0][0]);
matrix[y*2] [x*2 + 1] = old_matrix[y][x] + (mult * base[0][1]);
matrix[y*2 + 1][x*2] = old_matrix[y][x] + (mult * base[1][0]);
matrix[y*2 + 1][x*2 + 1] = old_matrix[y][x] + (mult * base[1][1]);
}
}
mult *= 4;
old_matrix = matrix;
}
return old_matrix;
}