# Goals

• Use the Random Number generator class and how to get a random number from a uniform distribution(使用Random Number generator class以及如何从均匀分布中获取随机数)
• Display text on an OpenCV window by using the function cv::putText

# Code

In this tutorial, we intend to use *random* values for the drawing parameters. Also, we intend to populate our image with a big number of geometric figures. Since we will be initializing them in a random fashion, this process will be automatic and made by using *loops* .

和上一章节相比，我们使用随机数来进行图形的生成，同时，我们打算用大量几何图形来填充图像。

# Explanation

RNG rng( 0xFFFFFFFF );


RNG implements a random number generator. In this example, rng is a RNG element initialized with the value 0xFFFFFFFF

RNG是一个随机数生成器。在上面这个代码中，rng是初始值为0xFFFFFFFF的RNG类型的数据。

RNG类可以压缩一个64位的i整数并得到scalar和array的随机数。随机数的产生采用的是Multiply-With-Carry算法和Ziggurat算法。

Then we create a matrix initialized to zeros (which means that it will appear as black), specifying its height, width and its type

然后我们创建一个初始化为0的矩阵，并指定其高度、宽度和类型。

Mat image = Mat::zeros( window_height, window_width, CV_8UC3 );
imshow( window_name, image );


然后我们开始疯狂画东西：

c = Drawing_Random_Lines(image, window_name, rng);
if( c != 0 ) return 0;
c = Drawing_Random_Rectangles(image, window_name, rng);
if( c != 0 ) return 0;
c = Displaying_Random_Text( image, window_name, rng );
if( c != 0 ) return 0;
c = Displaying_Big_End( image, window_name, rng );


上述代码中的每个Drawing_Random_Lines()之类的代码都是自定义的，函数原型如下：

## Drawing_Random_Lines()

int Drawing_Random_Lines( Mat image, char* window_name, RNG rng )
{
int lineType = 8;
Point pt1, pt2;
for( int i = 0; i < NUMBER; i++ )
{
pt1.x = rng.uniform( x_1, x_2 );
pt1.y = rng.uniform( y_1, y_2 );
pt2.x = rng.uniform( x_1, x_2 );
pt2.y = rng.uniform( y_1, y_2 );
line( image, pt1, pt2, randomColor(rng), rng.uniform(1, 10), 8 );
imshow( window_name, image );
if( waitKey( DELAY ) >= 0 )
{ return -1; }
}
return 0;
}


我们可以发现，for循环共执行了NUMBER次，也就是说，总工会生成NUMBER条直线。

可以知道，直线的两个端点为pt1pt2

代码rng.uniform(x_1,x_2)的意思是生成一个[x_1,x_2)范围内的随机数。

static Scalar randomColor( RNG& rng )
{
int icolor = (unsigned) rng;
return Scalar( icolor&255, (icolor>>8)&255, (icolor>>16)&255 );
}


这段代码用于生成随机的颜色。

生成如下所示的图片：

## Drawing_Random_Rectangles()

Drawing_Random_Lines()生成方法类似：

int Drawing_Random_Rectangles(Mat image, char* window_name, RNG rng)
{
int lineType = 8;
Point pt1, pt2;
for (int i = 0; i < NUMBER; i++)
{
pt1.x = rng.uniform(x_1, x_2);
pt1.y = rng.uniform(y_1, y_2);
pt2.x = rng.uniform(x_1, x_2);
pt2.y = rng.uniform(y_1, y_2);
rectangle(image,pt1,pt2,randomColor(rng),rng.uniform(1, 10),lineType);
/*if (waitKey(DELAY) >= 0)
{
return -1;
}*/
}
imshow(window_name, image);
waitKey(0);
return 0;
}


## Display_Random_Text()

int Displaying_Big_End( Mat image, char* window_name, RNG rng )
{
Size textsize = getTextSize("OpenCV forever!", FONT_HERSHEY_COMPLEX, 3, 5, 0);
Point org((window_width - textsize.width)/2, (window_height - textsize.height)/2);
int lineType = 8;
Mat image2;
for( int i = 0; i < 255; i += 2 )
{
image2 = image - Scalar::all(i);
putText( image2, "OpenCV forever!", org, FONT_HERSHEY_COMPLEX, 3,
Scalar(i, i, 255), 5, lineType );
imshow( window_name, image2 );
if( waitKey(DELAY) >= 0 )
{ return -1; }
}
return 0;
}


## 完整代码

#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>

#define NUMBER 5
#define x_1 100
#define x_2 400
#define y_1 100
#define y_2 400
#define DELAY 0
#define window_width 500
#define window_height 500
using namespace cv;
int Drawing_Random_Lines(Mat image, char* window_name, RNG rng);
int Drawing_Random_Rectangles(Mat image, char* window_name, RNG rng);
int Displaying_Random_Text(Mat image, char* window_name, RNG rng);
int Displaying_Big_End(Mat image, char* window_name, RNG rng);
static Scalar randomColor(RNG& rng);
int main()
{
RNG rng(0xFFFFFFFF);

Mat image = Mat::zeros(500, 500, CV_8UC3);
imshow("first window", image);
waitKey(0);
char window_name[] = "lines window";
int c = Drawing_Random_Lines(image, window_name, rng);
image = Mat::zeros(500, 500, CV_8UC3);
if (c != 0) return 0;
char window_name2[] = "rectangle window";
c = Drawing_Random_Rectangles(image, window_name2, rng);
image = Mat::zeros(500, 500, CV_8UC3);
if (c != 0) return 0;
char window_name3[] = "text window";
c = Displaying_Random_Text(image, window_name3, rng);
if (c != 0) return 0;
image = Mat::zeros(500, 500, CV_8UC3);
c = Drawing_Random_Lines(image, window_name, rng);
c = Drawing_Random_Rectangles(image, window_name, rng);
c = Displaying_Random_Text(image, window_name, rng);
c = Displaying_Big_End(image, window_name, rng);
return 0;
}

int Drawing_Random_Lines(Mat image, char* window_name, RNG rng)
{
int lineType = 8;
Point pt1, pt2;
for (int i = 0; i < NUMBER; i++)
{
pt1.x = rng.uniform(x_1, x_2);
pt1.y = rng.uniform(y_1, y_2);
pt2.x = rng.uniform(x_1, x_2);
pt2.y = rng.uniform(y_1, y_2);
line(image, pt1, pt2, randomColor(rng), rng.uniform(1, 10), 8);
/*if (waitKey(DELAY) >= 0)
{
return -1;
}*/
}
imshow(window_name, image);
waitKey(0);
return 0;
}

int Drawing_Random_Rectangles(Mat image, char* window_name, RNG rng)
{
int lineType = 8;
Point pt1, pt2;
for (int i = 0; i < NUMBER; i++)
{
pt1.x = rng.uniform(x_1, x_2);
pt1.y = rng.uniform(y_1, y_2);
pt2.x = rng.uniform(x_1, x_2);
pt2.y = rng.uniform(y_1, y_2);
rectangle(image,pt1,pt2,randomColor(rng),rng.uniform(1, 10),lineType);
/*if (waitKey(DELAY) >= 0)
{
return -1;
}*/
}
imshow(window_name, image);
waitKey(0);
return 0;
}

int Displaying_Random_Text(Mat image, char* window_name, RNG rng)
{
int lineType = 8;
Point org;
for (int i = 1; i < NUMBER; i++)
{
org.x = rng.uniform(x_1, x_2);
org.y = rng.uniform(y_1, y_2);
putText(image, "Testing text rendering", org, rng.uniform(0, 8),
rng.uniform(0, 100) * 0.05 + 0.1, randomColor(rng), rng.uniform(1, 10), lineType);

/*if (waitKey(DELAY) >= 0)
{
return -1;
}*/
}
imshow(window_name, image);
waitKey(0);
return 0;
}

int Displaying_Big_End(Mat image, char* window_name, RNG rng)
{
Size textsize = getTextSize("OpenCV forever!", FONT_HERSHEY_COMPLEX, 3, 5, 0);
Point org((window_width - textsize.width) / 2, (window_height - textsize.height) / 2);
int lineType = 8;
Mat image2;
for (int i = 0; i < 10; i += 2)
{
image2 = image - Scalar::all(i);
putText(image2, "OpenCV forever!", org, FONT_HERSHEY_COMPLEX, 3,
Scalar(i, i, 255), 5, lineType);
imshow(window_name, image2);
if (waitKey(DELAY) >= 0)
{
return -1;
}
}
return 0;
}
static Scalar randomColor(RNG& rng)
{
int icolor = (unsigned)rng;
return Scalar(icolor & 255, (icolor >> 8) & 255, (icolor >> 16) & 255);
}


总结：在具体实现过程中，可以发现其实是伪随机，因为不管怎样，我们生成的随机数始终是一个值。

# 对官方教程的改进

因为RNG生成的随机数是伪随机的，细究原因，很容易发现和经典C语言生成随机数的局限是一致的，当种子固定不变时，生成的随机数自然始终是一个了。
如此，只要改变每次的种子即可。将原来的RNG生成代码RNG rng( 0xFFFFFFFF );改为：

RNG rng((unsigned)time(NULL));


当然得加上相应头文件：
完整代码如下：

#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>

#include <ctime>

#define NUMBER 5
#define x_1 100
#define x_2 400
#define y_1 100
#define y_2 400
#define DELAY 0
#define window_width 500
#define window_height 500
using namespace cv;
int Drawing_Random_Lines(Mat image, char* window_name, RNG rng);
int Drawing_Random_Rectangles(Mat image, char* window_name, RNG rng);
int Displaying_Random_Text(Mat image, char* window_name, RNG rng);
int Displaying_Big_End(Mat image, char* window_name, RNG rng);
static Scalar randomColor(RNG& rng);
int main()
{
/*RNG rng(0xFFFFFFFF);*/
RNG rng((unsigned)time(NULL));

Mat image = Mat::zeros(500, 500, CV_8UC3);
imshow("first window", image);
waitKey(0);
char window_name[] = "lines window";
int c = Drawing_Random_Lines(image, window_name, rng);
image = Mat::zeros(500, 500, CV_8UC3);
if (c != 0) return 0;
char window_name2[] = "rectangle window";
c = Drawing_Random_Rectangles(image, window_name2, rng);
image = Mat::zeros(500, 500, CV_8UC3);
if (c != 0) return 0;
char window_name3[] = "text window";
c = Displaying_Random_Text(image, window_name3, rng);
if (c != 0) return 0;
image = Mat::zeros(500, 500, CV_8UC3);
c = Drawing_Random_Lines(image, window_name, rng);
c = Drawing_Random_Rectangles(image, window_name, rng);
c = Displaying_Random_Text(image, window_name, rng);
c = Displaying_Big_End(image, window_name, rng);
return 0;
}

int Drawing_Random_Lines(Mat image, char* window_name, RNG rng)
{
rng((unsigned)time(NULL));
int lineType = 8;
Point pt1, pt2;
for (int i = 0; i < NUMBER; i++)
{
pt1.x = rng.uniform(x_1, x_2);
pt1.y = rng.uniform(y_1, y_2);
pt2.x = rng.uniform(x_1, x_2);
pt2.y = rng.uniform(y_1, y_2);
line(image, pt1, pt2, randomColor(rng), rng.uniform(1, 10), 8);
/*if (waitKey(DELAY) >= 0)
{
return -1;
}*/
}
imshow(window_name, image);
waitKey(0);
return 0;
}

int Drawing_Random_Rectangles(Mat image, char* window_name, RNG rng)
{
rng((unsigned)time(NULL));
int lineType = 8;
Point pt1, pt2;
for (int i = 0; i < NUMBER; i++)
{
pt1.x = rng.uniform(x_1, x_2);
pt1.y = rng.uniform(y_1, y_2);
pt2.x = rng.uniform(x_1, x_2);
pt2.y = rng.uniform(y_1, y_2);
rectangle(image,pt1,pt2,randomColor(rng),rng.uniform(1, 10),lineType);
/*if (waitKey(DELAY) >= 0)
{
return -1;
}*/
}
imshow(window_name, image);
waitKey(0);
return 0;
}

int Displaying_Random_Text(Mat image, char* window_name, RNG rng)
{
rng((unsigned)time(NULL));
int lineType = 8;
Point org;
for (int i = 1; i < NUMBER; i++)
{
org.x = rng.uniform(x_1, x_2);
org.y = rng.uniform(y_1, y_2);
putText(image, "Testing text rendering", org, rng.uniform(0, 8),
rng.uniform(0, 100) * 0.05 + 0.1, randomColor(rng), rng.uniform(1, 10), lineType);

/*if (waitKey(DELAY) >= 0)
{
return -1;
}*/
}
imshow(window_name, image);
waitKey(0);
return 0;
}

int Displaying_Big_End(Mat image, char* window_name, RNG rng)
{
Size textsize = getTextSize("OpenCV forever!", FONT_HERSHEY_COMPLEX, 3, 5, 0);
Point org((window_width - textsize.width) / 2, (window_height - textsize.height) / 2);
int lineType = 8;
Mat image2;
for (int i = 0; i < 10; i += 2)
{
image2 = image - Scalar::all(i);
putText(image2, "OpenCV forever!", org, FONT_HERSHEY_COMPLEX, 3,
Scalar(i, i, 255), 5, lineType);
imshow(window_name, image2);
if (waitKey(DELAY) >= 0)
{
return -1;
}
}
return 0;
}
static Scalar randomColor(RNG& rng)
{
rng((unsigned)time(NULL));
int icolor = (unsigned)rng;
return Scalar(icolor & 255, (icolor >> 8) & 255, (icolor >> 16) & 255);
}

10-22 2741
10-19 798

08-30 404
06-22 9272
08-14 2万+
03-14 274
04-08 76
05-15 6732
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客