如何随机选择最大化占用空间的样本点?

时间:2013-01-14 06:00:17

标签: c++ algorithm

我想生成可随机填充/覆盖空间的样本点(如附图中所示)。我认为他们有一种称为“准随机”的方法,可以生成这样的采样点。但是,这离我的知识有点远。有人可以提出建议或帮我找到可以这样做的图书馆吗?或者建议如何开始编写这样的程序?

Sample points cover the space

在图像中,256个采样点应用于给定空间,放置在随机位置以覆盖整个给定空间。

更新: 我只是尝试使用Halton Quasi-random Sequence中的一些代码,并与下面的朋友发布的伪随机结果进行比较。在我看来,Halton方法的结果更好。我想分享一些结果如下;

Pseudo-random and Halton's sequence

我写的代码是

#include "halton.hpp"
#include "opencv2/opencv.hpp"
int main()
{
    int m_dim_num = 2;
    int m_n = 50;
    int m_seed[2], m_leap[2], m_base[2];
    double m_r[100];
    for (int i = 0; i < m_dim_num; i++)
    {
        m_seed[i] = 0;
        m_leap[i] = 1;
        m_base[i] = 2+i;
    }

    cv::Mat out(100, 100, CV_8UC1);
    i4_to_halton_sequence( m_dim_num, m_n, 0, m_seed, m_leap, m_base, m_r);

    int displaced = 100;
    for (int i = 0; i < 100; i=i+2)
    {
        cv::circle(out, cv::Point2d((m_r[i])*displaced, (m_r[i+1])*displaced), 1, cv::Scalar(0, 255, 0), 1, 8, 0);
    }
    cv::imshow("test", out);
    cv::waitKey(0);

    return 0;
}

由于我对OpenCV不太熟悉,我在OpenCV(Mat)矩阵上用绘图编写了这段代码。 “i4_to_halton_sequence()”是我上面提到的库中的函数。

结果并不是更好,但可能会以某种方式用于我的工作。有人有另一个想法吗?

5 个答案:

答案 0 :(得分:6)

我将给出一个看起来有点半的答案。但是,这个主题已在文献中进行了广泛的研究,因此我将向您介绍维基百科和其他地方的一些摘要。

你想要的也被称为低差异序列(或准随机,正如你所指出的)。您可以在此处详细了解:http://en.wikipedia.org/wiki/Low-discrepancy_sequence。它对许多事物很有用,包括数值积分,最近模拟视网膜神经节马赛克。

有很多方法可以生成低差异序列(或伪准随机序列:p)。其中一些是ACM收集算法(http://www.netlib.org/toms/index.html)。

我认为最常见的是Sobol序列(来自ACM的算法659)。您可以在此处获取有关此内容的详细信息:http://en.wikipedia.org/wiki/Sobol_sequence

在大多数情况下,除非你真的投入其中,否则这些东西看起来非常可怕。为了快速获得结果,我将使用GNU的GSL(GNU科学库):http://www.gnu.org/software/gsl/

该库包括生成准随机序列的代码(http://www.gnu.org/software/gsl/manual/html_node/Quasi_002dRandom-Sequences.html),包括Sobol序列(http://www.gnu。组织/软件/ GSL /手动/ html_node / Quasi_002drandom-数发生器-examples.html)。

如果你仍然卡住,我可以在这里粘贴一些代码,但你最好不要深入研究GSL。

答案 1 :(得分:3)

这里是另一种覆盖整个空间的准随机方式。

由于您有256个点可以使用,您可以先将这些点绘制为16x16网格。

然后应用一些函数,为每个点提供一些随机偏移(比如0到±2到点的x和y坐标)。

答案 2 :(得分:0)

您可以创建等距点(所有点与其邻居具有相同的距离)然后,在第二步中,将每个点随机移动一点,使它们看起来“随机”。

我的第二个想法是:
1.从一个区域开始。
2.在您所在地区的“中间”创建一个随机点P rand 3.到那时将区域划分为4个区域。 P是左下方区域的右上角,右下区域的左上角,依此类推 4.对所有4个子区域重复步骤2..4。当然,不是永远,而是在你满意之前。

此算法确保每个“洞”(即新子区域)都填充一个点。

更新:由于步骤(2),您的初始区域应该是您所在区域的两倍。这确保了在边缘和角落处也有点。

答案 3 :(得分:0)

这称为"low discrepancy sequence"。链接的Wikipage解释了如何生成它们。

但我怀疑你已经知道这一点,因为你的图像非常类似于维基百科的2,3 Halton sequence example

答案 4 :(得分:-3)

你只需要库rand()函数:

#include <stdlib.h>
#include <time.h>

unsigned int N = 256; //number of points
int RANGE_X = 100; //x range to put sample points in
int RANGE_Y = 100;

void PutSamplePoint(int x, int y)
{
   //some your code putting sample point on field
}

int main()
{
    srand((unsigned)time(0)); //initialize random generator - uses current time as seed
    for(unsigned int i = 0; i < N; i++)
    {
        int x = rand() % RANGE_X; //returns random value in range [0, RANGE_X)
        int y = rand() % RANGE_Y;
        PutSamplePoint(x, y);
    }

    return 0;
}