从头开始opencv(九)——core:random generator and text


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算法。

其构造函数的初始化可以传入一个64位的整型参数作为随机数产生器的初值。next可以取出下一个随机数,uniform函数可以返回指定范围的随机数,Gaussian函数返回一个高斯随机数,fill则用随机数填充矩阵。

  
  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);
}
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页