学習OpenCV 2——乱数発生
乱数の生成はプログラミングでよく用いられる操作であり,特に初期化を行う際にはランダム値を付与する必要がある.CおよびC++で乱数を生成する方法、例えばrand()、srand()などはOpenCVでも使用可能である.また、OpenCVでは、C++の乱数系RNG、Cの乱数系CvRNGなど、関連する関数も用意されており、使い勝手が向上しています.以下、一つ一つ紹介します.
説明キーワードの前にcvを持っているのはすべてCの中の書き方で、cvを持っていないのはC++の中の書き方で、例えばCvRNGとRNG、その本質はすべて同じです. 計算機で生成された乱数はいずれも擬似乱数であり,シードseedと特定のアルゴリズムに基づいて計算される.したがって,シードが一定であればアルゴリズムが一定であれば,生成される乱数は同じ である.完全に繰り返される乱数を生成するには,システム時間で種子を作ることができる.OpenCVではGetTickCount()、Cではtime() すべての結果は最後尾のスクリーンショットを参照してください.
1.OpenCVのC++バージョン乱数
1.1 RNG
RNGクラスはopencvにおけるC++の乱数発生器である.64ビットのint乱数を生成します.現在、均一分布とGauss分布によって乱数を生成することができる.乱数の生成にはMultiply−With−CArryアルゴリズムとZigguratアルゴリズムを用いた.
1.1.1乱数を生成
RNGは3種類の乱数RNG(int seed)を生成することができ、シードseedを使用して64ビットの乱数を生成し、デフォルト-1 RNG::uniform()は均一に分布する乱数RNGを生成する::gaussian()はガウス分布の乱数を生成する
RNG::uniform(a,b)は、[a,b]の範囲の均一な分布の乱数を返します.a,bのデータ型は一致し、int、float、doubleのいずれかでなければなりません.デフォルトはintです.
RNG::gaussian( σ) 平均値が0、標準差が0を返します.σの各見出しページがあります.
平均値を生成する場合はλ,標準偏差はσの乱数は、λ+ RNG::gaussian( σ)
実際、rngはRNGオブジェクトであり、ランダム整数でもある.
1.1.2次の乱数を返します
前回は1つの乱数しか返されず、実際にはシステムがランダム配列を生成しています.乱数を連続的に取得する場合は、RNGクラスを再定義する必要はありません.ランダム配列の次の乱数を取り出すだけです.
RNG::nextは次の64ビットのランダム整数RNGを返します::operatorは次の指定されたタイプのランダム数を返します
1.1.3行列RNG::fill()を乱数で埋め込む
void fill( InputOutputArray mat, int distType, InputArray a, InputArray b, bool saturateRange=false );
InputOutputArray入出力マトリクスは、最大4チャネルまでサポートされ、4チャネルを超えるとreshape()で構造を変更します.
int distType UNIFORMALまたはNORMAL、均一分布とガウス分布を表す
InputArray a disTypeはUNIFORMであり、aは下界(閉区間)を表す.disTypeはNORMAL,a平均
InputArrayb disTypeはUNIFORMであり、bは上界(開区間)を表す.disTypeはNORMAL,b標準差
bool saturateRange=falseは均一分布に対してのみ有効である.本物の場合、乱数を生成する範囲をデータ型の範囲に変換してから乱数を生成します.
偽の場合、乱数が発生してから、データ型の有効区間に切り捨てられます.以下のfillM 1とfillM 2の例を見て結果を見てください
1.2 randu( )
作用:均一分布の乱数を返し、配列または行列randu(dst,low,high)を埋め込む.dst–出力配列またはマトリクス;low–区間下界(閉区間);high-区間上界(開区間)
1.3 randn( )
作用:ガウス分布の乱数を返し、配列または行列を埋め込む
randn(dst, mean, stddev)
dst–出力配列またはマトリクス;mean–平均値;stddev-標準差
1.4 randShuffle( )
作用:元の配列(行列)を乱すrandShuffle(InputOutputArraydst,入出力配列(一次元)double iterFactor=1.交換値の行列の位置を決める係数...RNG*rng=0)(オプション)乱数発生器、0はデフォルトの乱数発生器、すなわちseed=-1を用いることを示す.rngは乱す方法を決定する
2.OpenCVのCバージョン乱数
2.1 CvRNG
役割:64ビットのランダム整数を生成します.RNGを参照してください.C++バージョンのRNGはCvRNGに代わりました
2.2 cvRandArr( )
作用:CvRNGで発生した乱数で配列(行列)void cvRandArrを充填する(CvRNG*rng、cvRNGによって初期化されたRNG状態CvArr*arr、出力配列int dist_type、CV_RAND_UNIまたはCV_RAND_NORMAL CvScalar param 1は、乱数範囲の閉境界である場合に均一に分布する.正規分布ランダム数の平均です
CvScalar param 2)均一分布であれば乱数範囲の開上境界である.正規分布であれば乱数の標準差です
2.3 cvRandInt( )
unsigned int cvRandInt(CvRNG*rng)作用:cvRandIntは均一分布のランダム32-bit符号なし整数値を返し、RNG状態を更新する.C実行ライブラリのrand()関数とよく似ていますが、常に32ビット数が生成され、rand()は0からRAND_を返します.MAX(オペレーティングプラットフォームに依存する2**16または2**32)間の数.
2.4 cvRandReal( )
double cvRandReal(CvRNG*rng)作用:均一分布のランダム浮動小数点数を返し、範囲[0,1]
3.C言語乱数
ここでは最も基本的な2つのrand()とsrand()を紹介します
int rand(void); デフォルトシード「1」を使用して、0~RAND_を生成MAX間の擬似乱数.
RAND_MAX定数はstdlibで定義.hヘッダファイルにあります.void srand (unsigned int seed); シードseedを使用して0~RAND_を生成MAX間の擬似乱数
rangとsrandの唯一の違いはseedを設定するかどうかです.
randとsrandを用いて乱数小結1を生成し,乱数はランダムシードが一定の計算方法に基づいて計算した数値である.したがって,計算方法が一定であれば,ランダムシードが一定であれば,発生するランダム数は変わらない.2、デフォルトではランダムシードはシステムクロック(すなわちタイミング/カウンタの値)から来ており、全く繰り返さないランダムシードを得るにはtime()3、[a,b)間のランダム整数を取るには:(rand()%(b-a)+a[0,N]間のランダム浮動小数点数を取るには:rand()/((double)(RAND_MAX)/N)を取るには[a,b)間のランダム浮動小数点数を取るには:rand()/((double)(RAND_MAX)/(b-a)+(b)
4.完全なプログラムと結果
プログラム参照http://blog.csdn.net/zyttae/article/details/41719349
原文の中の不明確なところを説明し,いくつかの新しい内容を補充した.
異なるシードを設定すると、異なる結果が得られます.そうしないと、結果は変わりません.
説明
1.OpenCVのC++バージョン乱数
1.1 RNG
RNGクラスはopencvにおけるC++の乱数発生器である.64ビットのint乱数を生成します.現在、均一分布とGauss分布によって乱数を生成することができる.乱数の生成にはMultiply−With−CArryアルゴリズムとZigguratアルゴリズムを用いた.
1.1.1乱数を生成
RNGは3種類の乱数RNG(int seed)を生成することができ、シードseedを使用して64ビットの乱数を生成し、デフォルト-1 RNG::uniform()は均一に分布する乱数RNGを生成する::gaussian()はガウス分布の乱数を生成する
RNG::uniform(a,b)は、[a,b]の範囲の均一な分布の乱数を返します.a,bのデータ型は一致し、int、float、doubleのいずれかでなければなりません.デフォルトはintです.
RNG::gaussian( σ) 平均値が0、標準差が0を返します.σの各見出しページがあります.
平均値を生成する場合はλ,標準偏差はσの乱数は、λ+ RNG::gaussian( σ)
// RNG , “-1”
RNG rng;
// 64
int N1 = rng;
/*------------- uniform gaussian---------*/
// double 0.000000, uniform(int,int), , 0
double N1a = rng.uniform(0,1);
// [0,1) double
double N1b = rng.uniform((double)0,(double)1);
// [0,1) float , double 。
double N1c = rng.uniform(0.f,1.f);
// [0,1) double 。
double N1d = rng.uniform(0.,1.);
// ( 。。)
//double N1e = rng.uniform(0,0.999999);
// 0, 2
double N1g = rng.gaussian(2);
実際、rngはRNGオブジェクトであり、ランダム整数でもある.
1.1.2次の乱数を返します
前回は1つの乱数しか返されず、実際にはシステムがランダム配列を生成しています.乱数を連続的に取得する場合は、RNGクラスを再定義する必要はありません.ランダム配列の次の乱数を取り出すだけです.
RNG::nextは次の64ビットのランダム整数RNGを返します::operatorは次の指定されたタイプのランダム数を返します
RNG rng;
int N2 = rng.next(); // , N1.next();
//
int N2a = rng.operator uchar(); //
int N2b = rng.operator schar(); //
int N2c = rng.operator ushort(); //
int N2d = rng.operator short int(); //
int N2e = rng.operator int(); //
int N2f = rng.operator unsigned int(); //
int N2g = rng.operator float(); //
int N2h = rng.operator double(); // double
int N2i = rng.operator ()(); // rng.next( )
int N2j = rng.operator ()(100); // [0,100)
1.1.3行列RNG::fill()を乱数で埋め込む
void fill( InputOutputArray mat, int distType, InputArray a, InputArray b, bool saturateRange=false );
InputOutputArray入出力マトリクスは、最大4チャネルまでサポートされ、4チャネルを超えるとreshape()で構造を変更します.
int distType UNIFORMALまたはNORMAL、均一分布とガウス分布を表す
InputArray a disTypeはUNIFORMであり、aは下界(閉区間)を表す.disTypeはNORMAL,a平均
InputArrayb disTypeはUNIFORMであり、bは上界(開区間)を表す.disTypeはNORMAL,b標準差
bool saturateRange=falseは均一分布に対してのみ有効である.本物の場合、乱数を生成する範囲をデータ型の範囲に変換してから乱数を生成します.
偽の場合、乱数が発生してから、データ型の有効区間に切り捨てられます.以下のfillM 1とfillM 2の例を見て結果を見てください
// [1,1000) int fillM
Mat_<int>fillM(3,3);
rng.fill(fillM,RNG::UNIFORM,1,1000);
cout << "filM = " << fillM << endl << endl;
Mat fillM1(3,3,CV_8U);
rng.fill(fillM1,RNG::UNIFORM,1,1000,TRUE);
cout << "filM1 = " << fillM1 << endl << endl;
Mat fillM2(3,3,CV_8U);
rng.fill(fillM2,RNG::UNIFORM,1,1000,FALSE);
cout << "filM2 = " << fillM2 << endl << endl;
//fillM1 [0,,255) , 255;
//fillM2 , , 255,
// 1, 3 double fillN
Mat_<double>fillN(3,3);
rng.fill(fillN,RNG::NORMAL,1,3);
cout << "filN = " << fillN << endl << endl;
以前のこれらの方法はすべてRNGクラスに基づいており、RNGクラスを先に定義する必要があり、以下の方法は必要なく、seedを定義できないだけで、重複しないランダム配列を生成することはできない.1.2 randu( )
作用:均一分布の乱数を返し、配列または行列randu(dst,low,high)を埋め込む.dst–出力配列またはマトリクス;low–区間下界(閉区間);high-区間上界(開区間)
Mat_<int>randuM(3,3);
randu(randuM,Scalar(0),Scalar(255));
cout << "randuM = " << randuM << endl << endl;
// randu rng.fill , rng rng
1.3 randn( )
作用:ガウス分布の乱数を返し、配列または行列を埋め込む
randn(dst, mean, stddev)
dst–出力配列またはマトリクス;mean–平均値;stddev-標準差
Mat_<int>randnM(3,3);
randn(randnM,0,1);
cout << "randnM = " << randnM << endl << endl;
// randu rng.fill , rng rng
1.4 randShuffle( )
作用:元の配列(行列)を乱すrandShuffle(InputOutputArraydst,入出力配列(一次元)double iterFactor=1.交換値の行列の位置を決める係数...RNG*rng=0)(オプション)乱数発生器、0はデフォルトの乱数発生器、すなわちseed=-1を用いることを示す.rngは乱す方法を決定する
Mat randShufM =(Mat_<double>(2,3) << 1,2,3,4,5,6);
randShuffle(randShufM,7,0);
cout << "randShufM = " << endl<<randShufM<< endl << endl;
2.OpenCVのCバージョン乱数
2.1 CvRNG
役割:64ビットのランダム整数を生成します.RNGを参照してください.C++バージョンのRNGはCvRNGに代わりました
2.2 cvRandArr( )
作用:CvRNGで発生した乱数で配列(行列)void cvRandArrを充填する(CvRNG*rng、cvRNGによって初期化されたRNG状態CvArr*arr、出力配列int dist_type、CV_RAND_UNIまたはCV_RAND_NORMAL CvScalar param 1は、乱数範囲の閉境界である場合に均一に分布する.正規分布ランダム数の平均です
CvScalar param 2)均一分布であれば乱数範囲の開上境界である.正規分布であれば乱数の標準差です
CvMat* cvM = cvCreateMat(3,3,CV_16U); // 3×3
cvRandArr(&cvRNG,cvM,CV_RAND_UNI,cvScalarAll(0),cvScalarAll(255)); // cvM ,[0,255)
//cout << "cvM = " << cvM << endl << endl; //cvM ,
cout<<"cvM = ";
for(int i=0;i<3;i++)
{
for(int j= 0;j<3;j++)
{
cout<<(int)cvGetReal2D(cvM,i,j)<<" "; // ?
}
cout<<endl;
}
cout<<endl;
2.3 cvRandInt( )
unsigned int cvRandInt(CvRNG*rng)作用:cvRandIntは均一分布のランダム32-bit符号なし整数値を返し、RNG状態を更新する.C実行ライブラリのrand()関数とよく似ていますが、常に32ビット数が生成され、rand()は0からRAND_を返します.MAX(オペレーティングプラットフォームに依存する2**16または2**32)間の数.
int cvInt = cvRandInt(&cvRNG);
cout << "cvInt = " << cvInt << endl << endl;
2.4 cvRandReal( )
double cvRandReal(CvRNG*rng)作用:均一分布のランダム浮動小数点数を返し、範囲[0,1]
double cvDouble = cvRandReal(&cvRNG);
cout << "cvDouble = " << cvDouble << endl<< endl;
3.C言語乱数
ここでは最も基本的な2つのrand()とsrand()を紹介します
int rand(void); デフォルトシード「1」を使用して、0~RAND_を生成MAX間の擬似乱数.
RAND_MAX定数はstdlibで定義.hヘッダファイルにあります.void srand (unsigned int seed); シードseedを使用して0~RAND_を生成MAX間の擬似乱数
rangとsrandの唯一の違いはseedを設定するかどうかです.
// [0,10)
printf("
rand1 =" );
for (int i=0; i<10; i++)
{
printf("%d ", rand()%10);
}
printf("
srand1 =" );
srand(8);
for (int i=0; i<10; i++)
{
printf("%d ", rand()%10);
}
printf("
srand2 =" );
// time()
srand((unsigned)time(NULL));
for (int i=0; i<10; i++)
{
printf("%d ", rand()%10);
}
printf("
" );
randとsrandを用いて乱数小結1を生成し,乱数はランダムシードが一定の計算方法に基づいて計算した数値である.したがって,計算方法が一定であれば,ランダムシードが一定であれば,発生するランダム数は変わらない.2、デフォルトではランダムシードはシステムクロック(すなわちタイミング/カウンタの値)から来ており、全く繰り返さないランダムシードを得るにはtime()3、[a,b)間のランダム整数を取るには:(rand()%(b-a)+a[0,N]間のランダム浮動小数点数を取るには:rand()/((double)(RAND_MAX)/N)を取るには[a,b)間のランダム浮動小数点数を取るには:rand()/((double)(RAND_MAX)/(b-a)+(b)
4.完全なプログラムと結果
プログラム参照http://blog.csdn.net/zyttae/article/details/41719349
原文の中の不明確なところを説明し,いくつかの新しい内容を補充した.
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <iostream>
#include <iostream>
#include "cv.h"
#include "highgui.h"
using namespace cv;
using namespace std;
int main(int argc,char** argv)
{
/***********************************OpenCV C++ ******************************************/
/*==================================== ================================================
*RNG 3
*RNG(int seed) seed 64 , -1
*RNG::uniform()
*RNG::gaussian()
* seed: , , 。 ,
* , “-1”。
* getTickCount() 64 , 。RNG(getTickCount())
===================================================================================================*/
// RNG , “-1”
RNG rng;
// 64
int N1 = rng;
/*------------- uniform gaussian---------*/
// double 0.000000, uniform(int,int), , 0
double N1a = rng.uniform(0,1);
// [0,1) double
double N1b = rng.uniform((double)0,(double)1);
// [0,1) float , double 。
double N1c = rng.uniform(0.f,1.f);
// [0,1) double 。
double N1d = rng.uniform(0.,1.);
// ( 。。)
//double N1e = rng.uniform(0,0.999999);
// 0, 2
double N1g = rng.gaussian(2);
cout << "N1 = " << N1 << endl;
cout << "N1a = " << N1a << endl;
cout << "N1b = " << N1b << endl;
cout << "N1c = " << N1c << endl;
cout << "N1d = " << N1d << endl;
//cout << "N1e = " << N1e << endl;
cout << "N1g = " << N1g << endl;
/*================================ ==============================================
* ,rng , 。 ,
* ,
*RNG:: next 64
*RNG:: operator
================================================================================================*/
// 64 , n1
int N2 = rng.next(); // N1.next();
//
int N2a = rng.operator uchar();
int N2b = rng.operator schar();
int N2c = rng.operator ushort();
int N2d = rng.operator short int();
int N2e = rng.operator int();
int N2f = rng.operator unsigned int();
int N2g = rng.operator float();
int N2h = rng.operator double();
int N2i = rng.operator ()(); // rng.next( )
int N2j = rng.operator ()(100); // [0,100)
cout << "N2 = " << N2 << endl;
cout << "N2a = " << N2a << endl;
cout << "N2b = " << N2b << endl;
cout << "N2c = " << N2c << endl;
cout << "N2d = " << N2d << endl;
cout << "N2e = " << N2e << endl;
cout << "N2f = " << N2f << endl;
cout << "N2g = " << N2g << endl;
cout << "N2h = " << N2h << endl;
cout << "N2i = " << N2i << endl;
cout << "N2j = " << N2j << endl<< endl;
/*======================================= ( )==========================================
*void RNG:: fill( InputOutputArray mat, , 4 , 4 reshape()
int distType, UNIFORM NORMAL
InputArray a, disType UNIFORM,a ( );disType NORMAL,a
InputArray b, disType UNIFORM,b ( );disType NORMAL,b
bool saturateRange=false) 。 , ,
; , , 。
fillM1 fillM2
===========================================================================================================*/
// [1,1000) int fillM
Mat_<int>fillM(3,3);
rng.fill(fillM,RNG::UNIFORM,1,1000);
cout << "filM = " << fillM << endl << endl;
Mat fillM1(3,3,CV_8U);
rng.fill(fillM1,RNG::UNIFORM,1,1000,TRUE);
cout << "filM1 = " << fillM1 << endl << endl;
Mat fillM2(3,3,CV_8U);
rng.fill(fillM2,RNG::UNIFORM,1,1000,FALSE);
cout << "filM2 = " << fillM2 << endl << endl;
//fillM1 [0,,255) , 255;
//fillM2 , , 255,
// CV_8U 0~255
// , FALSE( )
// 1, 3 double fillN
Mat_<double>fillN(3,3);
rng.fill(fillN,RNG::NORMAL,1,3);
cout << "filN = " << fillN << endl << endl;
/*=====================================randu( )=====================================================
/* ,
* randu(dst, low, high)
* dst –
* low – ( )
* high - ( )
====================================================================================================*/
Mat_<int>randuM(3,3);
randu(randuM,Scalar(0),Scalar(255));
cout << "randuM = " << randuM << endl << endl;
// randu rng.fill , rng rng
/*======================================randn( )======================================================
/* ,
* randn(dst, mean, stddev)
* dst –
* mean –
* stddev -
======================================================================================================*/
Mat_<int>randnM(3,3);
randn(randnM,0,1);
cout << "randnM = " << randnM << endl << endl;
// randu rng.fill , rng rng
/*======================================randShuffle( )=================================================
/* ,
* randShuffle( InputOutputArray dst, ( )
* double iterFactor=1., ...
* RNG* rng=0 ) ( ) ,0 , seed=-1
* rng
=======================================================================================================*/
Mat randShufM =(Mat_<double>(2,3) << 1,2,3,4,5,6);
randShuffle(randShufM,7,0);
cout << "randShufM = " << endl<<randShufM<< endl << endl;
/******************************OpenCV C++ *************************************************/
/*===================================CvRNG============================================================
* 64 , RNG。C++ RNG CvRNG
========================================================================================================*/
CvRNG cvRNG;
/*======================================cvRandArr========================================================
* CvRNG ( )
*void cvRandArr( CvRNG* rng, cvRNG RNG
* CvArr* arr,
* int dist_type, CV_RAND_UNI CV_RAND_NORMAL
* CvScalar param1, ;
* CvScalar param2) ;
========================================================================================================*/
CvMat* cvM = cvCreateMat(3,3,CV_16U); // 3×3
cvRandArr(&cvRNG,cvM,CV_RAND_UNI,cvScalarAll(0),cvScalarAll(255)); // cvM ,[0,255)
//cout << "cvM = " << cvM << endl << endl; //cvM ,
cout<<"cvM = ";
for(int i=0;i<3;i++)
{
for(int j= 0;j<3;j++)
{
cout<<(int)cvGetReal2D(cvM,i,j)<<" "; // ?
}
cout<<endl;
}
cout<<endl;
/*=====================================cvRandInt======================================================
unsigned int cvRandInt( CvRNG* rng)
cvRandInt 32-bit RNG ;
C rand() , 32-bit rand()
0 RAND_MAX( 2**16 2**32, )
=====================================================================================================*/
int cvInt = cvRandInt(&cvRNG);
cout << "cvInt = " << cvInt << endl << endl;
/*====================================cvRandReal======================================================
double cvRandReal( CvRNG* rng)
, [0,1)
=====================================================================================================*/
double cvDouble = cvRandReal(&cvRNG);
cout << "cvDouble = " << cvDouble << endl<< endl;
/****************************** C ****************************************************
* OpenCV RNG CvRNG , C
****************************************************************************************************/
/*=====================================rand srand=================================================*
* int rand(void); “1”, 0 RAND_MAX 。RAND_MAX stdlib.h 。
* void srand (unsigned int seed); seed 0 RAND_MAX
* rang srand , seed。
*==================================================================================================*/
// [0,10)
printf("
rand1 =" );
for (int i=0; i<10; i++)
{
printf("%d ", rand()%10);
}
printf("
srand1 =" );
srand(8);
for (int i=0; i<10; i++)
{
printf("%d ", rand()%10);
}
printf("
srand2 =" );
// time()
srand((unsigned)time(NULL));
for (int i=0; i<10; i++)
{
printf("%d ", rand()%10);
}
printf("
" );
/*================= rand srand =======================================
1、 。 , , , 。
2、 ( / ), , time()
3、 [a,b) :(rand() % (b - a)) + a
[0,N) : rand() /((double)(RAND_MAX)/N)
[a,b) : rand() /((double)(RAND_MAX)/(b-a))+(b-a)
*============================================================================================================*/
system("pause");
return 0;
}
結果を下図に示す異なるシードを設定すると、異なる結果が得られます.そうしないと、結果は変わりません.