分享

OpenCV学习(十一)之随机数生成器RNG

 Y忍冬草 2016-12-11

OpenCV中C++的RNG类可以压缩一个64位的i整数并可以得到scalar和array的随机数。目前的版本支持均匀分布随机数和Gaussian分布随机数。随机数的产生采用的是Multiply-With-Carry算法和Ziggurat算法。其构造函数的初始化可以传入一个64位的整型参数作为随机数产生器的初值。next可以取出下一个随机数,uniform函数可以返回指定范围的随机数,gaussian函数返回一个高斯随机数,fill则用随机数填充矩阵等等。

以下测试程序分别测试了RNG类中各个函数的用法以及解释了各个参数的意思,重点都在注释里。此外测试程序后半部分也大概介绍了c版本的随机数产生器,如cvRNG、cvRandArr、cvRandInt、cvRandReal等。由于理解还能力有限,个别函数还是不太清楚。

实验环境:VS2010 + OpenCV2.4.9.0

  1. #include <iostream>  
  2. #include "cv.h"  
  3. #include "highgui.h"  
  4.   
  5. using namespace cv;  
  6. using namespace std;  
  7.   
  8. int main(int argc,char** argv)  
  9. {  
  10.     RNG rng;  
  11.     // always produces 0  
  12.     //RNG::uniform(int,int)  
  13.     //因为只会去整数,所以只产生0  
  14.     double a = rng.uniform(0,1);  
  15.       
  16.     //produces double from[0,1)  
  17.     double a1 = rng.uniform((double)0,(double)1);  
  18.   
  19.     //produces float from[0,1)  
  20.     double b = rng.uniform(0.f,1.f);  
  21.   
  22.     //produces double from[0,1)  
  23.     double c = rng.uniform(0.,1.);  
  24.   
  25.     //may cause compiler error because of ambiguity:  
  26.     //RNG:: uniform(0,(int)0.999999) ? or RNG::unigorm((double)0,0.999999)  
  27.     //double d = rng.uniform(0,0.999999);所以先注释起来吧 O(∩_∩)O  
  28.     cout << "a = " << a << endl;  
  29.     cout << "a1 = " << a1 << endl;  
  30.     cout << "b = " << b << endl;  
  31.     cout << "c = " << c << endl;  
  32.     //cout << "d = " << d << endl;  
  33.   
  34.     /*-------- returns the next random number sampled from the Gaussian distribution------- 
  35.     *   double RNG:: gaussian( double sigma) 
  36.     *   sigma – standard deviation(标准差) of the distribution 
  37.     ------------------------------------------------------------------------------------*/  
  38.     double g = rng.gaussian(2);  
  39.     cout << "g = " << g << endl;  
  40.   
  41.     /*-------- returns the next random number(还不理解这个“下一个”是指什么?) ------------------- 
  42.     *   unsigned int RNG:: next() 
  43.     *   The method updates the state using the MWC algorithm and 
  44.         returns the next 32-bit random number 
  45.     ------------------------------------------------------------------------------------*/  
  46.     int n = rng.next();  
  47.     cout << "n = " << n << endl;  
  48.   
  49.     /*-------- RNG::operator T returns the next random number of the specified type --------- 
  50.     *   RNG:: operator uchar() 
  51.     *   RNG:: operator schar() 
  52.     *   RNG:: operator ushort() 
  53.     *   RNG:: operator short int() 
  54.     *   RNG:: operator int() 
  55.     *   RNG:: operator unsigned int() 
  56.     *   RNG:: operator float() 
  57.     *   RNG:: operator double() 
  58.     *   返回指定类型的下一个随机数。对于int型,返回可用数据类型范围内的随机数,对于float型, 
  59.         返回[0,1)范围的随机数 
  60.     ------------------------------------------------------------------------------------*/  
  61.     int n1 = rng.operator int();  
  62.     cout << "n1 = " << n1 << endl;  
  63.   
  64.     float f = rng.operator float();  
  65.     cout << "f = " << f << endl;  
  66.   
  67.     /*-------- RNG::operator () returns the next random number ----------------------- 
  68.     *   unsigned int RNG:: operator() ()  == RNG::next() 两个函数相同 
  69.     *   unsigned int RNG:: operator() (unsigned int N) 注意括号 
  70.     *   return the result in the range [0,N) 
  71.     ------------------------------------------------------------------------------------*/  
  72.     int o = rng.operator ()();  
  73.     int o1 = rng.operator() (50);  
  74.     cout << "o = " << o << endl << "o1 = " << o1 << endl;  
  75.   
  76.     /*---------------------- fills arrays with random numbers.------------------------ 
  77.     *    void RNG:: fill( InputOutputArray mat, int distType, InputArray a, 
  78.                             InputArray b, bool saturateRange=false )函数原型 
  79.     *   mat – 2D or N-dimensional matrix; currently matrices with more than 4 channels  
  80.         are not supported by the methods, use Mat::reshape() as a possible workaround 
  81.         说明了输入矩阵的形式,目前尚不支持4通道以上的矩阵,如果超过了,需要调用reshape()函数 
  82.         进行变更 
  83.     *   distribution type, RNG::UNIFORM or RNG::NORMAL 分布的类型(均匀或高斯) 
  84.     *   a – first distribution parameter; in case of the uniform distribution, this is an 
  85.         inclusive lower boundary, in case of the normal distribution, this is a mean value 
  86.         当为均匀分布时,a为下界(闭区间),当为高斯分布时,表示均值 
  87.     *   b – second distribution parameter; in case of the uniform distribution, this is a  
  88.         non-inclusive upper boundary, in case of the normal distribution, this is a standard deviation  
  89.         (diagonal of the standard deviation matrix or the full standard deviation matrix) 
  90.         当为均匀分布时,a为上界(开区间),当为高斯分布时,表示标准差 
  91.     *   saturateRange – pre-saturation flag; for uniform distribution only; if true, the method will 
  92.         first convert a and b to the acceptable value range (according to the mat datatype) and 
  93.         then will generate uniformly distributed random numbers within the range [saturate(a), 
  94.         saturate(b)) , if saturateRange=false, the method will generate uniformly distributed 
  95.         random numbers in the original range [a, b) and then will saturate them, it means, for example,  
  96.         that theRNG().fill(mat_8u, RNG::UNIFORM, -DBL_MAX, DBL_MAX) will likely produce array mostly 
  97.         filled with 0’s and 255’s, since the range (0, 255) is significantly smaller than [-DBL_MAX, DBL_MAX) 
  98.         意思是:此变量只针对均匀分布有效。当为真的时候,会先把产生随机数的范围变换到数据类型的范围, 
  99.         再产生随机数;如果为假,会先产生随机数,再进行截断到数据类型的有效区间。请看以下fillM1和 
  100.         fillM2的例子并观察结果 
  101.     ------------------------------------------------------------------------------------*/  
  102.     Mat_<int>fillM(3,3);  
  103.     rng.fill(fillM,RNG::UNIFORM,1,1000);  
  104.     cout << "filM = " << fillM << endl << endl;  
  105.   
  106.     Mat fillM1(3,3,CV_8U);  
  107.     rng.fill(fillM1,RNG::UNIFORM,1,1000,TRUE);  
  108.     cout << "filM1 = " << fillM1 << endl << endl;  
  109.   
  110.     //fillM1产生的数据都在[0,,255)内,且小于255;  
  111.     //fillM2产生的数据虽然也在同样范围内,但是由于用了截断操作,所以很多数据都是255,  
  112.     //因为CV_8U的有效范围就是0~255  
  113.     //所以我认为最好的方式就是事先想好需要的数据类型和范围,再设置为FALSE(默认值)  
  114.     Mat fillM2(3,3,CV_8U);  
  115.     rng.fill(fillM2,RNG::UNIFORM,1,1000,FALSE);  
  116.     cout << "filM2 = " << fillM2 << endl << endl;  
  117.   
  118.     /*------- uniformly-distributed random number or an array of random numbers---- 
  119.     *   randu(dst, low, high)  
  120.     *   dst – output array of random numbers;  
  121.     *   low – inclusive lower boundary of the generated random numbers; 
  122.     *   high - exclusive upper boundary of the generated random numbers; 
  123.     -----------------------------------------------------------------------------*/  
  124.     Mat_<int>randuM(3,3);  
  125.     randu(randuM,Scalar(0),Scalar(255));  
  126.     cout << "randuM = " << randuM << endl << endl;  
  127.   
  128.     /*---------------normally distributed random numbers------------------- 
  129.     *   randn(dst, mean, stddev)(也叫高斯分布) 
  130.     *   dst – output array of random numbers;  
  131.         the array must be pre-allocated and have 1 to 4 channels; 
  132.     *   mean(均值) – mean value (expectation) of the generated random numbers 
  133.     *   stddev - standard deviation(标准差) of the generated random numbers; it can be either a vector 
  134.         (in which case a diagonal standard deviation matrix is assumed) or a square matrix 
  135.     -----------------------------------------------------------------------------*/  
  136.     Mat_<int>randnM(3,3);  
  137.     randn(randnM,0,1);  
  138.     cout << "randnM = " << randnM << endl << endl;  
  139.   
  140.     /*-----------------Shuffles the array elements randomly(产生随机打乱的矩阵)--------------- 
  141.     *   randShuffle( InputOutputArray dst, double iterFactor=1., RNG* rng=0 ) 
  142.     *   dst -  input/output numerical 1D array; 
  143.     *   iterFactor - scale factor that determines the number of random swap operations; 
  144.     *   rng -  optional random number generator used for shuffling; if it is zero,  
  145.         theRNG()() is used instead; 
  146.     *   The function randShuffle shuffles the specified 1D array by randomly choosing  
  147.         pairs of elements and swapping them. The number of such swap operations will be 
  148.         dst.rows*dst.cols*iterFactor  
  149.     -----------------------------------------------------------------------------*/  
  150.     Mat_<int>randShufM(4,1);  
  151.     randShuffle(randShufM,1,0);  
  152.     cout << "randShufM = " << randShufM << endl << endl;  
  153.     //还不太会用...  
  154.   
  155.     /*------------------------下面介绍一下C版的随机数产生器的相关函数---------------*/  
  156.   
  157.     /*------- initializes a random number generator state(初始化随机数生成器状态)----- 
  158.     *    CvRNG cvRNG( int64 seed=-1) 函数原型 
  159.     *   seed – 64-bit value used to initiate a random sequence 
  160.         64-bit的值用来初始化随机序列; 
  161.         函数 cvRNG 初始化随机数生成器并返回其状态。 
  162.         指向这个状态的指针可以传递给函数 cvRandInt, cvRandReal 和 cvRandArr; 
  163.         在通常的实现中使用一个 multiply-with-carry generator 
  164.         C++版本中的RNG已经代替了CvRNG 
  165.     -----------------------------------------------------------------------------*/  
  166.     //CvRNG rng1 = cvRNG(-1);  
  167.     CvRNG cvRNG;  
  168.   
  169.     /*------- fills an array with random numbers and updates the RNG state------- 
  170.     *    void cvRandArr( CvRNG* rng, CvArr* arr, int dist_type,  
  171.                         CvScalar param1, CvScalar param2)函数原型 
  172.     *   rng – CvRNG state initialized by RNG()被 cvRNG 初始化的 RNG 状态 
  173.     *   arr – The destination array 
  174.     *   dist_type – Distribution type 
  175.         - CV_RAND_UNI uniform distribution 
  176.         - CV_RAND_NORMAL normal or Gaussian distribution 
  177.     *   param1 – The first parameter of the distribution. In the case of a uniform distribution it 
  178.         is the inclusive lower boundary of the random numbers range. In the case of a normal 
  179.         distribution it is the mean value of the random numbers 
  180.         如果是均匀分布它是随机数范围的闭下边界;如果是正态分布它是随机数的平均值 
  181.     *   param2 – The second parameter of the distribution. In the case of a uniform distribution 
  182.         it is the exclusive upper boundary of the random numbers range. In the case of a normal 
  183.         distribution it is the standard deviation of the random numbers 
  184.         如果是均匀分布它是随机数范围的开上边界;如果是正态分布它是随机数的标准差 
  185.     -----------------------------------------------------------------------------*/  
  186.     CvMat* cvM = cvCreateMat(3,3,CV_16U);  
  187.     cvRandArr(&cvRNG,cvM,CV_RAND_UNI,cvScalarAll(0),cvScalarAll(255));  
  188.     cout << "cvM = " << cvM << endl << endl;  
  189.     //这里输出有点奇怪,明明定义的是矩阵,却输出的一串数字,不理解?  
  190.   
  191.     /*------- returns a 32-bit unsigned integer and updates RNG------- 
  192.     *   unsigned int cvRandInt( CvRNG* rng)函数原型  
  193.     *   rng – CvRNG state initialized by RNG() 
  194.         函数 cvRandInt 返回均匀分布的随机 32-bit 无符号整型值并更新 RNG 状态; 
  195.         它和 C 运行库里面的 rand() 函数十分相似,但是它产生的总是一个 32-bit 数而 rand() 
  196.         返回一个 0 到 RAND_MAX(它是 2**16 或者 2**32, 依赖于操作平台)之间的数 
  197.     -----------------------------------------------------------------------------*/  
  198.     int cvInt = cvRandInt(&cvRNG);  
  199.     cout << "cvInt = " << cvInt << endl;  
  200.   
  201.     /*------- returns a floating-point random number and updates RNG.------- 
  202.     *   double cvRandReal( CvRNG* rng)函数原型  
  203.     *   rng – RNG state initialized by RNG() 
  204.         函数 cvRandReal 返回均匀分布的随机浮点数,范围在 0~1 之间 (不包括1) 
  205.     -----------------------------------------------------------------------------*/  
  206.     double cvDouble = cvRandReal(&cvRNG);  
  207.     cout << "cvDouble = " << cvDouble << endl;  
  208.   
  209.     system("pause");  
  210.     return 0;  
  211. }  
以下是结果:各个输出的变量名相互对应

同时也可以看到fillM1和fillM2之间的区别。


以下给出RNG类在OpenCV中源代码:

  1. /*! 
  2.    Random Number Generator 
  3.    The class implements RNG using Multiply-with-Carry algorithm 
  4. */  
  5. class CV_EXPORTS RNG  
  6. {  
  7. public:  
  8.     enum { UNIFORM=0, NORMAL=1 };  
  9.   
  10.       
  11. RNG();//默认构造函数  
  12. // inline RNG::RNG() { state = 0xffffffff; }  
  13.   
  14. RNG(uint64 state);//带参数的构造函数,接受一个64位无符号的值。  
  15. //inline RNG::RNG(uint64 _state) { state = _state ? _state : 0xffffffff; }  
  16.   
  17.   
  18. //! updates the state and returns the next 32-bit unsigned integer random number  
  19.     unsigned next();  
  20. /* 
  21. inline unsigned RNG::next() 
  22.     state = (uint64)(unsigned)state*CV_RNG_COEFF + (unsigned)(state >> 32); 
  23.     return (unsigned)state; 
  24. #define CV_RNG_COEFF 4164903690U 
  25. 用两个很大的无符号数相乘,乘积结果要转换为64位无符号数,转换的时候两个乘数应该向高精度看起,所以应该也先转换为64位再相乘。把state右移32位得到一个数,把这两个数相加。函数返回一个32位的无符号数,其值为截断前面求得的和。 
  26. */  
  27.   
  28. //以下几个函数是从类到uchar.schar,ushort,short,usinged的显示转换函数  
  29. operator uchar();//返回一个8位无符号类型的随机数,把next返回的数截断  
  30. //inline RNG::operator uchar() { return (uchar)next(); }  
  31.   
  32. operator schar();//返回一个8为有符号类型的随机数。???会产生负数吗,返回的也是截断的next返回值。莫非是截断后得到的最高位作为符号位,这样也可能是随机的。???  
  33. //inline RNG::operator schar() { return (schar)next(); }  
  34.   
  35. operator ushort();//返回一个无符号16为整数  
  36. //inline RNG::operator ushort() { return (ushort)next(); }  
  37.   
  38. operator short();//返回一个有符号16为整数  
  39. // inline RNG::operator short() { return (short)next(); }  
  40.   
  41.   
  42. operator unsigned();//返回一个无符号32为整数  
  43. // inline RNG::operator unsigned() { return next(); }  
  44.   
  45.   
  46. //! returns a random integer sampled uniformly from [0, N).  
  47. unsigned operator ()(unsigned N);//重载括号操作符,带参数。在(0,N)之间返回一个整数,调用uniform成员函数  
  48. //inline unsigned RNG::operator ()(unsigned N) {return (unsigned)uniform(0,N);}  
  49.   
  50.   
  51. unsigned operator ()();//重载括号操作符,无参数。直接返回next结果。  
  52. // inline unsigned RNG::operator ()() {return next();}  
  53.   
  54.   
  55. //放在这个位置有点奇怪,为什么不和前边同类放一起呢?放回一个带符//号32为整数  
  56. operator int();  
  57. // inline RNG::operator int() { return (int)next(); }  
  58.   
  59. //返回一个float型(具体多少位看平台)数。  
  60. operator float();  
  61. // inline RNG::operator float() { return next()*2.3283064365386962890625e-10f; }  
  62.   
  63. //两个数按位或一下  
  64. operator double();  
  65. /* 
  66. inline RNG::operator double() 
  67.     unsigned t = next(); 
  68.     return (((uint64)t << 32) | next())*5.4210108624275221700372640043497e-20; 
  69. }*/  
  70.   
  71.   
  72. //! returns uniformly distributed integer random number from [a,b) range  
  73. int uniform(int a, int b);//[a,b)内随机产生一个int型值,均匀分布  
  74. // inline int RNG::uniform(int a, int b) { return a == b ? a : (int)(next()%(b - a) + a); }  
  75.   
  76.   
  77. //! returns uniformly distributed floating-point random number from [a,b) range  
  78. float uniform(float a, float b); //[a,b)内随机产生一个float型值,均匀分布  
  79. // inline float RNG::uniform(float a, float b) { return ((float)*this)*(b - a) + a; }  
  80.   
  81.   
  82. //! returns uniformly distributed double-precision floating-point random number from [a,b) range  
  83. double uniform(double a, double b); //[a,b)内随机产生一个double型值,均匀分布  
  84. // inline double RNG::uniform(double a, double b) { return ((double)*this)*(b - a) + a; }  
  85.   
  86. void fill( InputOutputArray mat, int distType, InputArray a, InputArray b, bool saturateRange=false );//这个函数实现很长,暂时略过。  
  87.   
  88. //! returns Gaussian random variate with mean zero.  
  89. double gaussian(double sigma);//返回均值为0的高斯随机变量,  
  90. /*double RNG::gaussian(double sigma) 
  91.     float temp; 
  92.     randn_0_1_32f( &temp, 1, &state ); 
  93.     return temp*sigma; 
  94. }*/  
  95.       
  96.   
  97. uint64 state;//种子,next中需要这样一个初始值  
  98. };  

以下是一个以RNG的例子,画随机直线和在图像中添加字符:

  1. #include <iostream>  
  2. #include "cv.h"  
  3. #include "highgui.h"  
  4.   
  5. using namespace std;  
  6. using namespace cv;  
  7.   
  8. const char wndName[] = "randDraw";  
  9. const int randNumber = 100;  
  10.   
  11. static Scalar randomColor(RNG& rng)  
  12. {  
  13.     int rColor = (unsigned)rng;  
  14.     //颜色是用RGB三通道表示,因此上面函数中颜色参数的类型都是Scalar类型  
  15.     //将随机数的值取出分别作为RGB三个通道的颜色值  
  16.     return Scalar(rColor & 0xFF,(rColor >> 8) & 0xFF,(rColor >> 16) & 0xFF);  
  17. }  
  18.   
  19. int main(int argc,char** argv)  
  20. {  
  21.      //抗锯齿,平滑线  
  22.     //改为8就不是咯~  
  23.     int lineType = CV_AA;   
  24.     int width = 1000;  
  25.     int height = 700;  
  26.     int x1 = - width/2;  
  27.     int x2 = 3 * width/2;  
  28.     int y1 = - height/2;  
  29.     int y2 = 3 * height/2;  
  30.     const int DELAY = 10;  
  31.   
  32.     //0xFFFFFFFF表示初始的随机值  
  33.     //RNG rng(0xFFFFFFFF);  
  34.     RNG rng;  
  35.     Mat image = Mat::zeros(height,width,CV_8UC3);  
  36.     imshow(wndName,image);  
  37.     waitKey(DELAY);  
  38.   
  39.     for(int i = 0;i < randNumber;i++)  
  40.     {  
  41.         Point pt1;  
  42.         Point pt2;  
  43.         pt1.x = rng.uniform(x1,x2);  
  44.         pt1.y = rng.uniform(y1,y2);  
  45.         pt2.x = rng.uniform(x1,x2);  
  46.         pt2.y = rng.uniform(y1,y2);  
  47.         /*----------------------draws a line segment connecting two points----------- 
  48.         *   void line( Mat& img, Point pt1, Point pt2, const Scalar& color, 
  49.                         int thickness=1, int lineType=8, int shift=0)函数原型 
  50.         *   lineType – Type of the line: 
  51.                         – 8 (or omitted) - 8-connected line. 
  52.                         – 4 - 4-connected line. 
  53.                         – CV_AA - antialiased line. 
  54.         -----------------------------------------------------------------------------*/  
  55.         line(image,pt1,pt2,randomColor(rng),rng.uniform(1,10),lineType);  
  56.     }  
  57.     imshow(wndName,image);  
  58.     waitKey(0);  
  59.   
  60.     for(int i = 0;i < randNumber;i++)  
  61.     {  
  62.         Point org;  
  63.         org.x = rng.uniform(x1,x2);  
  64.         org.y = rng.uniform(y1,y2);  
  65.   
  66.         /*-------------------------draws a text string-------------------------------- 
  67.         *   void putText(Mat& img, const string& text, Point org, int fontFace,  
  68.                         double fontScale, Scalar color,int thickness=1,  
  69.                             int lineType=8, bool bottomLeftOrigin=false )函数原型 
  70.         *   img – image 
  71.         *   text – Text string to be drawn 
  72.         *   org – Bottom-left corner of the text string in the image. 
  73.         *   font – CvFont structure initialized using InitFont() C版本的参数 
  74.         *   fontFace – Font type. One of FONT_HERSHEY_SIMPLEX, FONT_HERSHEY_PLAIN, 
  75.                         FONT_HERSHEY_DUPLEX, FONT_HERSHEY_COMPLEX, FONT_HERSHEY_TRIPLEX, 
  76.                         FONT_HERSHEY_COMPLEX_SMALL, FONT_HERSHEY_SCRIPT_SIMPLEX, or 
  77.                         FONT_HERSHEY_SCRIPT_COMPLEX, where each of the font ID’s can be  
  78.                         combined with FONT_HERSHEY_ITALIC to get the slanted letters 
  79.         *   fontScale – Font scale factor that is multiplied by the font-specific base size 
  80.         *   color – Text color 
  81.         *   thickness – Thickness of the lines used to draw a text 
  82.         *   lineType – Line type. See the line for details 
  83.         *   bottomLeftOrigin – When true, the image data origin is at the bottom-left corner; 
  84.             Otherwise, it is at the top-left corner.如果为真,图像原点在左下角,否则在左上角 
  85.         -----------------------------------------------------------------------------*/  
  86.         putText(image,"OpenCV",org,rng.uniform(0,8),rng.uniform(0,10)*0.5 + 0.1,  
  87.             randomColor(rng),rng.uniform(1,10),lineType,FALSE);  
  88.     }  
  89.   
  90.     imshow(wndName,image);  
  91.     waitKey(0);  
  92.     return 0;  
  93. }  
以下是测试结果:




最后,再列出一个OpenCV自带Demo,我稍微对函数进行了注释。主要是为了练习使用随机数生成器和如何使用OpenCV画图。

  1. #include <iostream>  
  2. #include "cv.h"  
  3. #include "highgui.h"  
  4.   
  5. using namespace std;  
  6. using namespace cv;  
  7.   
  8. static void help()  
  9. {  
  10.     cout << "This program demonstrates OpenCV drawing and text output functions" << endl   
  11.         << "Usage:" << endl  
  12.         <<"./drawing" << endl;  
  13. }  
  14.   
  15. static Scalar randomColor(RNG& rng)  
  16. {  
  17.     int iColor = unsigned(rng);  
  18.     //255 = 0xFF  
  19.     return Scalar(iColor & 255,(iColor >> 8) & 255,(iColor >> 16) & 255);  
  20. }  
  21.   
  22. int main(int argc,char** argv)  
  23. {  
  24.     help();  
  25.     char wndName[] = "Drawing Demo";  
  26.     const int randomNumber = 100;  
  27.     const int DELAY = 10;  
  28.     int lineType = CV_AA;  
  29.     int height = 700;  
  30.     int width = 1000;  
  31.     int x1 = - width/2;  
  32.     int x2 = 3 * width/2;  
  33.     int y1 = - height/2;  
  34.     int y2 = 3 * height/2;  
  35.     RNG rng(0xFFFFFFFF);  
  36.   
  37.     Mat image = Mat::zeros(height,width,CV_8UC3);  
  38.     imshow(wndName,image);  
  39.     waitKey(DELAY);  
  40.   
  41.     //draw line  
  42.     for(int i = 0;i < randomNumber;i++)  
  43.     {  
  44.         Point pt1,pt2;  
  45.         pt1.x = rng.uniform(x1,x2);  
  46.         pt1.y = rng.uniform(y1,y2);  
  47.         pt2.x = rng.uniform(x1,x2);  
  48.         pt2.y = rng.uniform(y1,y2);  
  49.         line(image,pt1,pt2,randomColor(rng),rng.uniform(1,10),lineType);  
  50.         imshow(wndName,image);  
  51.         if(waitKey(DELAY) >= 0)  
  52.             return 0;  
  53.     }  
  54.   
  55.     //draw rectangle  
  56.     for(int i = 0;i < randomNumber;i++)  
  57.     {  
  58.         Point pt1,pt2;  
  59.         pt1.x = rng.uniform(x1,x2);  
  60.         pt1.y = rng.uniform(y1,y2);  
  61.         pt2.x = rng.uniform(x1,x2);  
  62.         pt2.y = rng.uniform(y1,y2);  
  63.         int thickness = rng.uniform(-3,10);  
  64.   
  65.         /*----------------------draws a simple, thick, or filled up-right rectangle----------- 
  66.         *   C++: void rectangle(Mat& img, Point pt1, Point pt2, const Scalar& color,  
  67.                                 int thickness=1, int lineType=8,int shift=0) 
  68.         *   C++: void rectangle(Mat& img, Rect rec, const Scalar& color, int thickness=1,  
  69.                                 int lineType=8, int shift=0) 
  70.         *   img – image 
  71.         *   pt1 – Vertex of the rectangle 
  72.         *   pt2 – Vertex of the rectangle opposite to pt1  
  73.         *   rec – Alternative specification of the drawn rectangle 
  74.         *   color – Rectangle color or brightness (grayscale image) 
  75.         *   thickness – Thickness of lines that make up the rectangle. Negative values, 
  76.             like CV_FILLED, mean that the function has to draw a filled rectangle 
  77.         *   lineType – Type of the line. See the line() description 
  78.         *   shift – Number of fractional bits in the point coordinates 
  79.         -----------------------------------------------------------------------------*/  
  80.         rectangle(image,pt1,pt2,randomColor(rng),MAX(thickness,-1),lineType);  
  81.         imshow(wndName,image);  
  82.         if(waitKey(DELAY) >= 0)  
  83.             return 0;  
  84.     }  
  85.   
  86.   
  87.   
  88.   
  89.     //draw ellipse  
  90.     for(int i = 0; i < randomNumber;i++)  
  91.     {  
  92.         Point center;  
  93.         center.x = rng.uniform(x1,x2);  
  94.         center.y = rng.uniform(y1,y2);  
  95.         Size axes;  
  96.         axes.width = rng.uniform(0,200);  
  97.         axes.height = rng.uniform(0,200);  
  98.         double angle = rng.uniform(0,180);  
  99.   
  100.         /*---------draws a simple or thick elliptic arc or fills an ellipse sector--------- 
  101.         *   C++: void ellipse(Mat& img, Point center, Size axes, double angle,  
  102.                                 double startAngle,double endAngle,const Scalar& color,  
  103.                                 int thickness=1, int lineType=8, int shift=0) 
  104.         *   C++: void ellipse(Mat& img, const RotatedRect& box, const Scalar& color,  
  105.                                 int thickness=1, int lineType=8) 
  106.         *   img – image  
  107.         *   center – Center of the ellipse 椭圆中心 
  108.         *   axes – Half of the size of the ellipse main axes 椭圆长轴的一半 
  109.         *   angle – Ellipse rotation angle in degrees 椭圆旋转的角度 
  110.         *   startAngle – Starting angle of the elliptic arc in degrees 弧度开始的角度 
  111.         *   endAngle – Ending angle of the elliptic arc in degrees 弧度结束的角度 
  112.         *   box – Alternative ellipse representation via RotatedRect or CvBox2D 
  113.             This means that the function draws an ellipse inscribed in the rotated rectangle 
  114.         *   color – Ellipse color 
  115.         *   thickness – Thickness of the ellipse arc outline, if positive. Otherwise, this indicates that a 
  116.             filled ellipse sector is to be drawn 
  117.         *   lineType – Type of the ellipse boundary. See the line() description 
  118.         *   shift – Number of fractional bits in the coordinates of the center and values of axes 
  119.         -----------------------------------------------------------------------------*/  
  120.         ellipse(image,center,axes,angle,angle - 100,angle + 200,randomColor(rng),rng.uniform(1,8),lineType);  
  121.         imshow(wndName,image);  
  122.         if(waitKey(DELAY) >= 0)  
  123.             return 0;  
  124.     }  
  125.   
  126.     //draw polylines  
  127.     for(int i = 0;i < randomNumber;i++)  
  128.     {  
  129.         Point pt[2][3];  
  130.         pt[0][0].x = rng.uniform(x1,x2);  
  131.         pt[0][0].y = rng.uniform(y1,y2);  
  132.         pt[0][1].x = rng.uniform(x1,x2);  
  133.         pt[0][1].y = rng.uniform(y1,y2);  
  134.         pt[0][2].x = rng.uniform(x1,x2);  
  135.         pt[0][2].y = rng.uniform(y1,y2);  
  136.         pt[1][0].x = rng.uniform(x1,x2);  
  137.         pt[1][0].y = rng.uniform(y1,y2);  
  138.         pt[1][1].x = rng.uniform(x1,x2);  
  139.         pt[1][1].y = rng.uniform(y1,y2);  
  140.         pt[1][2].x = rng.uniform(x1,x2);  
  141.         pt[1][2].y = rng.uniform(y1,y2);  
  142.         const Point* ppt[2] = {pt[0],pt[1]};  
  143.         int npt[] = {3,3};  
  144.   
  145.         /*-------------------draws several polygonal curves---------------------------- 
  146.         *   C++: void polylines(Mat& img, const Point** pts, const int* npts, int ncontours,  
  147.                                     bool isClosed, const Scalar& color, int thickness=1, 
  148.                                         int lineType=8, int shift=0 ) 
  149.         *   C++: void polylines(InputOutputArray img, InputArrayOfArrays pts, bool isClosed,  
  150.                             const Scalar& color,int thickness=1, int lineType=8, int shift=0 ) 
  151.         *   img – image 
  152.         *   pts – Array of polygonal curves 多边形曲线数组 
  153.         *   npts – Array of polygon vertex counters 顶点数组 
  154.         *   ncontours – Number of curves 曲线数量 
  155.         *   isClosed – Flag indicating whether the drawn polylines are closed or not 
  156.                         If they are closed,the function draws a line from the last vertex  
  157.                         of each curve to its first vertex 标志曲线是否闭合 
  158.         *   color – Polyline color 
  159.         *   thickness – Thickness of the polyline edges 
  160.         *   lineType – Type of the line segments. See the line() description 
  161.         *   shift – Number of fractional bits in the vertex coordinates  
  162.         -----------------------------------------------------------------------------*/  
  163.         polylines(image,ppt,npt,2,TRUE,randomColor(rng),rng.uniform(1,10),lineType);  
  164.         imshow(wndName,image);  
  165.         if(waitKey(DELAY) >= 0)  
  166.             return 0;  
  167.     }  
  168.   
  169.     //draw polygons with filled area  
  170.     for(int i = 0;i < randomNumber;i++)  
  171.     {  
  172.         Point pt[2][3];  
  173.         pt[0][0].x = rng.uniform(x1, x2);  
  174.         pt[0][0].y = rng.uniform(y1, y2);  
  175.         pt[0][1].x = rng.uniform(x1, x2);  
  176.         pt[0][1].y = rng.uniform(y1, y2);  
  177.         pt[0][2].x = rng.uniform(x1, x2);  
  178.         pt[0][2].y = rng.uniform(y1, y2);  
  179.         pt[1][0].x = rng.uniform(x1, x2);  
  180.         pt[1][0].y = rng.uniform(y1, y2);  
  181.         pt[1][1].x = rng.uniform(x1, x2);  
  182.         pt[1][1].y = rng.uniform(y1, y2);  
  183.         pt[1][2].x = rng.uniform(x1, x2);  
  184.         pt[1][2].y = rng.uniform(y1, y2);  
  185.         const Point* ppt[2] = {pt[0], pt[1]};  
  186.         int npt[] = {3, 3};  
  187.   
  188.         /*--------------fills the area bounded by one or more polygons--------------- 
  189.         *   C++: void fillPoly( Mat& img, const Point** pts, const int* npts, int ncontours, 
  190.                         const Scalar& color, int lineType=8, int shift=0, Point offset=Point() ) 
  191.         *   img – image 
  192.         *   pts – Array of polygons where each polygon is represented as an array of points 
  193.         *   npts – Array of polygon vertex counters 
  194.         *   ncontours – Number of contours that bind the filled region 
  195.         *   color – Polygon color 
  196.         *   lineType – Type of the polygon boundaries. See the line() description 
  197.         *   shift – Number of fractional bits in the vertex coordinates 
  198.         *   offset – Optional offset of all points of the contours 
  199.         -----------------------------------------------------------------------------*/  
  200.         fillPoly(image, ppt, npt, 2, randomColor(rng), lineType);  
  201.         imshow(wndName, image);  
  202.         if(waitKey(DELAY) >= 0)  
  203.             return 0;  
  204.     }  
  205.   
  206.     //draw circle  
  207.     for(int i = 0;i < randomNumber;i++)  
  208.     {  
  209.         Point center;  
  210.         center.x = rng.uniform(x1,x2);  
  211.         center.y = rng.uniform(y1,y2);  
  212.   
  213.         /*-----------------------------draw a circle---------------------------------- 
  214.         *   C++: void circle(Mat& img, Point center, int radius, const Scalar& color, 
  215.                                 int thickness=1, int lineType=8,int shift=0) 
  216.         *   img – Image where the circle is drawn 
  217.         *   center – Center of the circle 
  218.         *   radius – Radius of the circle 
  219.         *   color – Circle color 
  220.         *   thickness – Thickness of the circle outline, if positive. 
  221.                         Negative thickness means that a 
  222.         *   filled circle is to be drawn 
  223.         *   lineType – Type of the circle boundary. See the line() description 
  224.         *   shift – Number of fractional bits in the coordinates of the center and  
  225.             in the radius value 
  226.         -----------------------------------------------------------------------------*/  
  227.         circle(image,center,rng.uniform(0,300),randomColor(rng),rng.uniform(-1,9),lineType);  
  228.         imshow(wndName,image);  
  229.         if(waitKey(DELAY) >= 0)  
  230.             return 0;  
  231.     }  
  232.   
  233.     //put text on the image  
  234.     for(int i = 0;i < randomNumber;i++)  
  235.     {  
  236.         Point org;  
  237.         org.x = rng.uniform(x1,x2);  
  238.         org.y = rng.uniform(y1,y2);  
  239.         putText(image,"Testing text rendering",org,rng.uniform(0,8)/*font type*/,  
  240.                 rng.uniform(0,100)*0.05 + 0.1/*font scale*/,  
  241.                     randomColor(rng),rng.uniform(1,10)/*thickness*/,lineType);  
  242.         imshow(wndName,image);  
  243.         if(waitKey(DELAY) >= 0)  
  244.             return 0;  
  245.     }  
  246.       
  247.     /*------------------calculates the width and height of a text string-------------- 
  248.     *   C++: Size getTextSize( const string& text, int fontFace, double fontScale, 
  249.                                 int thickness, int* baseLine) 
  250.     *   text – Input text string 
  251.     *   fontFace – Font to use. See the putText() for details 
  252.     *   fontScale – Font scale. See the putText() for details 
  253.     *   thickness – Thickness of lines used to render the text 
  254.     *   baseLine – Output parameter - y-coordinate of the baseline relative  
  255.                     to the bottom-most text point. 
  256.     --------------------------------------------------------------------------------------*/  
  257.     //string text = " OpenCV Forever!" ;  
  258.     //int fontFace = FONT_HERSHEY_COMPLEX;  
  259.     //double fontScale = 2;  
  260.     //int thickness = 3;  
  261.     //int baseline=0;  
  262.     //baseline += thickness;  
  263.     //Size textSize = getTextSize(text, fontFace,  
  264.     //                      fontScale, thickness, &baseline);  
  265.   
  266.     Size textSize = getTextSize("OpenCV Forever!",FONT_HERSHEY_COMPLEX,3,5,0);  
  267.     Point org((width - textSize.width)/2,(height - textSize.height)/2);  
  268.   
  269.     Mat image2;  
  270.     for(int i = 0;i < 255;i += 2)  
  271.     {  
  272.         image2 = image - Scalar::all(i);  
  273.         putText(image2,"OpenCV Forever!",org,FONT_HERSHEY_COMPLEX,  
  274.             3,Scalar(i,i,255),5,lineType);  
  275.   
  276.         imshow(wndName,image2);  
  277.         if(waitKey(DELAY) >= 0)  
  278.             return 0;  
  279.     }  
  280.   
  281.     waitKey();  
  282.     return 0;  
  283. }  

测试结果很有意思。顿时让我对OpenCV又爱上了几分。。。





//-----------------------------------------------------------

转自:http://blog.csdn.net/zyttae/article/details/41719349

感谢博主的分享

//------------------------------------------------------------------




    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多