Вызов случайного числа, генерирующего функцию-член, не производит полностью случайных чисел

Я создаю приложение wxWidget с C++, где в начале программы я хочу, чтобы окно приложения содержало пиксели со случайными цветами, такими как:

Random coloured pixels

в приведенном выше приложении есть 3600 пикселей (60 x 60), и я дал каждому пикселю случайный цвет RGB с помощью uniform_int_distribution

цвета для пикселей на изображении выше генерируются в данный момент с помощью следующей функции в моем коде:

void random_colors(int ctable[][3], int n)
{
  // construct a trivial random generator engine from a time-based seed:
  unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
  std::default_random_engine generator (seed);
  std::uniform_int_distribution<int> distribution(0,255);
  for(int i=0; i<n; i++)
  {
      for(int j=0; j<3; j++)
      {
        ctable[i][j] = distribution(generator);
      }
  }
}

Я делаю это, давая этой функции таблицу с размерами 3600 x 3, и эта функция заполнит значения для цветов.

этот путь, однако, не то, что я хочу. Я хочу создать класс под названием somNode каждая somNode-объект представляет пиксель на картинке (со значениями RGB в качестве атрибута массива элементов). В этом somNode - класс у меня есть функция-член с помощью uniform_int_distribution давать при построении каждого somNode свой собственный случайный цвет RGB. Это функция, которая создает случайный цвет для каждого somNode:

void rand_node_colour(int nodeWeights[])
{
  // construct a trivial random generator engine from a time-based seed:
  unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
  std::default_random_engine generator (seed);
  std::uniform_int_distribution<int> distribution(0,255);
  for(int i=0; i<3; i++)
  {
    nodeWeights[i] = distribution(generator);
  }
}

the nodeWeights массив элементов представляет RGB-значение somNode. Теперь, когда я создаю эту "сом-сетку", что у меня есть на изображении выше (3600 пикселей, соответствующих 3600 somNodes) Я использую следующий код (взгляните на som-конструктор):

#include "somNode.h"
#include <vector>

class som
{
    public:
        double learning_rate;
        std::vector<somNode> somGrid;
    public:
        som(double lrate);
        void epoch();
        void trainOnce();

};

/*
* Initialize the som grid
*/
som::som(double lrate)
{
    learning_rate = lrate;
    // Create the som grid
    for(int i=0; i<60; i++)
    {
        for(int j=0; j<60; j++)
        {
            int xL = j*10;
            int xR = (j+1)*10;
            int yT = i*10;
            int yB = (i+1)*10;
            somGrid.push_back(somNode(xL, xR, yB, yT));
        }
    }
}

// Train som by one epoch
void som::epoch()
{

}

// Train som by one color
void som::trainOnce()
{

}

Итак, у меня есть vector<somNode> somGrid куда я толкаю все эти 3600 somNodes, когда я их построить. Когда каждый узел построен somNode функции-члена rand_node_colour вызывается, который создает RGB-значение.

когда, Однако, я реализую этот код вместо того, который я использовал сначала, я получаю этот результат:

enter image description here

вы можете видеть, что есть четкая картина, так что что-то здесь не так. Мой вопрос: что происходит в генерации случайных чисел, когда создаются сомноды? Почему он не дает того же результата, что и код, который я использовал выше?

P. S. Вот это somNode.cpp:

#include <random>
#include <iostream>
#include <chrono>
#include<cmath>

void rand_node_colour(int nodeWeights[]);

/*
* This class represent a node in the som-grid
*/
class somNode
{
    public:
        // Weight of the node representing the color
        int nodeWeights[3];
        // Position in the grid
        double X, Y;
        // corner coorinates for drawing the node on the grid
        int x_Left, x_Right, y_Bottom, y_Top;

    public:
        // Constructor
        somNode(int xL, int xR, int yB, int yT);
        void editWeights(int r, int g, int b);
        double getDistance(int r, int g, int b);
};


somNode::somNode(int xL, int xR, int yB, int yT)
{
    // Set the corner points
    x_Left = xL;
    x_Right = xR;
    y_Bottom = yB;
    y_Top = yT;
    // Initialize random weights for node
    rand_node_colour(nodeWeights);
    // Calculate the node's position (center coordinate)
    X = x_Left + (double)((x_Right - x_Left)/double(2));
    Y = y_Bottom + (double)((y_Top - y_Bottom)/double(2));
}

void somNode::editWeights(int r, int g, int b)
{
    nodeWeights[0] = r;
    nodeWeights[1] = g;
    nodeWeights[2] = b;
}

double somNode::getDistance(int r, int g, int b)
{
    return sqrt(pow(nodeWeights[0]-r, 2) + pow(nodeWeights[1]-g, 2) + pow(nodeWeights[2]-b, 2));
}


void rand_node_colour(int nodeWeights[])
{
  // construct a trivial random generator engine from a time-based seed:
  unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
  std::default_random_engine generator (seed);
  std::uniform_int_distribution<int> distribution(0,255);
  for(int i=0; i<3; i++)
  {
    nodeWeights[i] = distribution(generator);
  }
}

1 ответов


проблема здесь в том, что вы постоянно воссоздаете и сеете генератор случайных чисел в rand_node_colour. Вы называете это в узкой петле, так что вы можете получить то же самое время, что означает, что семя будет таким же, и это означает, что случайные числа будут одинаковыми.

что вам нужно сделать, это семя генератор один раз, а затем продолжать использовать его случайный выход. Простой способ исправить код - сделать его static в функции sos он инициализируется только один раз и каждый последующий вызов к функции будет продолжаться дальше вместо того, чтобы запускать генератор во всем. Если мы это сделаем, код станет

void rand_node_colour(int nodeWeights[])
{
  // construct a trivial random generator engine from a time-based seed:
  static std::default_random_engine generator (std::chrono::system_clock::now().time_since_epoch().count());
  std::uniform_int_distribution<int> distribution(0,255);
  for(int i=0; i<3; i++)
  {
    nodeWeights[i] = distribution(generator);
  }
}