学習OpenCV 2——乱数発生

18299 ワード

乱数の生成はプログラミングでよく用いられる操作であり,特に初期化を行う際にはランダム値を付与する必要がある.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  ,      “-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; }
    結果を下図に示す
    異なるシードを設定すると、異なる結果が得られます.そうしないと、結果は変わりません.