Tworzę aplikację wxWidget z C++, gdzie na początku programu chcę, aby okno aplikacji zawierało piksele o losowych kolorach:Wywołanie funkcji generowania liczb losowych nie generuje całkowicie losowych liczb.
w powyższym zgłoszeniu istnieje 3600 pikseli (60 x 60) i dały każdy piksel losowego koloru RGB stosując uniform_int_distribution
koloru dla pikseli w obrazie są generowane w momencie, używając następującej funkcji w moim kodzie:
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);
}
}
}
Wykonuję tę czynność, nadając tej funkcji tabelę o wymiarach 3600 x 3 i ta funkcja wypełnia wartości dla kolorów.
W ten sposób nie jest to, czego chcę. Chcę tylko utworzyć klasę o nazwie somNode
, gdzie każdy obiekt somNode
reprezentuje piksel na obrazie (z wartościami RGB jako atrybutem macierzy składowej). W tej klasie somNode
mam funkcję składającą się z uniform_int_distribution
, aby nadać każdemu z nich własny losowy kolor RGB. Jest to funkcja, która tworzy losową koloru dla każdej 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);
}
}
element tablicy oznacza RGB wartość somNode
. Teraz, gdy tworzę ten „som-grid”, co mam w powyższym (3600 pikseli odpowiadających 3600 somNode
s) Używam następujący kod obrazka (przyjrzeć SOM-konstruktora):
#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()
{
}
Więc mam vector<somNode> somGrid
, gdzie pcham wszystkie te 3600 somNode
s, kiedy je konstruuję. Po skonstruowaniu każdego węzła wywoływana jest funkcja składowa , która tworzy wartość RGB.
Kiedy jednak zaimplementować ten kod zamiast jednej użyłem najpierw uzyskać ten wynik:
Widać, że istnieje wyraźny wzór więc coś jest nie tak tutaj. Moje pytanie brzmi: Co dzieje się w generowaniu liczb losowych podczas tworzenia somNodes? Dlaczego nie daje tego samego wyniku co kod, którego użyłem powyżej?
P.S. tutaj jest 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);
}
}
Czy nazywasz 'random_colors' lub' rand_node_colour' kilka razy? Jeśli zrobisz to szybko, wiele połączeń może korzystać z tej samej wartości początkowej. –
Hi @JoachimPileborg tak, za każdym razem, gdy budowany jest 'somNode', nazywam' rand_node_colour'. Spójrz na konstruktor 'somNode'. Moim pomysłem było, aby przy każdej konstrukcji stworzyć losowy kolor dla węzła. Rozumiem ... jak mogę to naprawić? :) – jjepsuomi
Seed the gen. tylko raz w budowie, najlepiej przy użyciu 'std :: random_device'. Zobacz prosty przykład [tutaj] (http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution). – vsoftco