How to Use OpenCV to Test Pseudo Random Number Generator
by viilaamo.com
Making of
Random number testing with OpenCV
Typically most random number generators do generate equal distribution of numbers, i.e. if you generate million numbers from 1 to 10 you should get about 100 000 of each. This is no brainer.
More difficult is to get the distance distribution between same numbers to be smoothly degreasing towards the larger distance. In another words if you generate million numbers from 1 to 10, the amount of pairs of number 1 with distance of say 5 should be about equal to any number pair with distance of 5.
Here is a very simple OpenCV code that plots the distance distribution to a bitmap and saves it (self explanatory code - as usual).
//**************************// // Copyright: // // VIILAAMO.COM // // OpenCV random number test // //**************************// #include <vector> #include <stdio.h> #include <time.h> #include <opencv2/opencv.hpp> using namespace cv; using namespace std; #define BM_HEIGHT 1024 //must be power of 2 #define BM_WIDTH 1536 unsigned long distr[BM_HEIGHT][BM_WIDTH]; //This is just basic initialization void init(void) { for (int i=0; i<BM_HEIGHT; i++) for (int j=0; j<BM_WIDTH; j++) distr[i][j]=0; srand(clock()); } //Just a wrapper, if you change the rnd generator, no need to touch other code unsigned int getRandom() { return (rand()&(BM_HEIGHT-1)); //Change rand to your "favorite" random generator } //This function generates the random number distribution table void createRndTable(void) { unsigned long l=0; unsigned int i; for (l=0; l<(1<<30); l++) //1<<30 is about 10^9, { i = getRandom(); if (l-distr[i][0]<BM_WIDTH) distr[i][l-distr[i][0]]++; distr[i][0]=l; //first column is used to store the last hit } } //This function maps the values to 0..255 void normalizeRndTable(void) { unsigned long l=0; float c; unsigned int i,j; for (int i=0; i<BM_HEIGHT; i++) for (int j=1; j<BM_WIDTH; j++) if (l<distr[i][j]) l=distr[i][j]; c=(255.0/l); for (int i=0; i<BM_HEIGHT; i++) for (int j=0; j<BM_WIDTH; j++) { distr[i][j]=c*distr[i][j]; if(j==0) distr[i][j]=0; //erase first column } l=0; } //This function draws the values to an image void createRndMat(Mat &mat) { for (int i = 0; i < mat.rows; ++i) { for (int j = 0; j < mat.cols; ++j) { mat.at<uchar>(i, j)=distr[i][j]; } } } int main(int argv, char **argc) { init(); createRndTable(); normalizeRndTable(); Mat mat(BM_HEIGHT, BM_WIDTH, CV_8UC1); createRndMat(mat); vector<int> compression_params; compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION); compression_params.push_back(9); //We use lossless format to preserve the details imwrite("random_gray.png", mat, compression_params); return 0; }
Just search the net and you will see that there are all kinds of tools to test the anomalies of random number generators. All we need is our own eyes and this piece of code to do it!