從頭開始opencv(九)——core:random generator and text

weixin_41926958發表於2020-10-25


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);
}

相關文章