您的位置:首页 > 运维架构

opencv2-1随机图形与文字生成

2015-09-24 22:16 302 查看
//--------------------------------------【程序说明】-------------------------------------------

// 程序说明:《OpenCV3编程入门》OpenCV2版书本附赠示例程序01

// 程序描述:随机图形和文字生成示例

// 测试所用操作系统: Windows 7 64bit

// 测试所用IDE版本:Visual Studio 2010

// 测试所用OpenCV版本:2.4.9

// 2014年11月 Revised by @浅墨_毛星云

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

//---------------------------------【头文件、命名空间包含部分】----------------------------

// 描述:包含程序所使用的头文件和命名空间

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

#include <opencv2/core/core.hpp>

#include <opencv2/highgui/highgui.hpp>

#include <iostream>

#include <stdio.h>

using namespace cv;

//-----------------------------------【全局变量声明部分】---------------------------------------

// 描述:声明全局变量

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

const int NUMBER = 100;

const int DELAY = 5;

const int window_width = 900;

const int window_height = 600;

int x_1 = -window_width/2;

int x_2 = window_width*3/2;

int y_1 = -window_width/2;

int y_2 = window_width*3/2;

//-----------------------------------【函数声明部分】-------------------------------------------

// 描述:函数原型声明

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

static Scalar randomColor( RNG& rng );

int Drawing_Random_Lines( Mat image, char* window_name, RNG rng );

int Drawing_Random_Rectangles( Mat image, char* window_name, RNG rng );

int Drawing_Random_Ellipses( Mat image, char* window_name, RNG rng );

int Drawing_Random_Polylines( Mat image, char* window_name, RNG rng );

int Drawing_Random_Filled_Polygons( Mat image, char* window_name, RNG rng );

int Drawing_Random_Circles( 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 );

//-----------------------------------【main( )函数】-------------------------------------------

// 描述:控制台应用程序的入口函数,我们的程序从这里开始

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

int main( void )

{

int c;

//创建窗口

char window_name[] = "Drawing_2程序窗口";

// 创建随机的RNG

RNG rng( 0xFFFFFFFF );

//初始化矩阵

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

// 在 DELAY ms内显示窗口

imshow( window_name, image );

waitKey( DELAY );

//线条的绘制

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 = Drawing_Random_Ellipses( image, window_name, rng );

if( c != 0 ) return 0;

// 折线的绘制

c = Drawing_Random_Polylines( image, window_name, rng );

if( c != 0 ) return 0;

// 多边形的绘制

c = Drawing_Random_Filled_Polygons( image, window_name, rng );

if( c != 0 ) return 0;

// 绘制圆形

c = Drawing_Random_Circles( 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 );

if( c != 0 ) return 0;

waitKey(0);

return 0;

}

//-----------------------------------【randomColor( )函数】-----------------------------------

// 描述:生成随机颜色

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

static Scalar randomColor( RNG& rng )

{

int icolor = (unsigned) rng;

return Scalar( icolor&255, (icolor>>8)&255, (icolor>>16)&255 );

}

//---------------------------【Drawing_Random_Lines( )函数】-------------------------------

// 描述:绘制随机的线条

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

int Drawing_Random_Lines( Mat image, char* window_name, RNG rng )

{

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;

}

//---------------------------【Drawing_Random_Ellipses( )函数】----------------------------

// 描述:绘制随机的矩形

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

int Drawing_Random_Rectangles( Mat image, char* window_name, RNG rng )

{

Point pt1, pt2;

int lineType = 8;

int thickness = rng.uniform( -3, 10 );

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), MAX( thickness, -1 ), lineType );

imshow( window_name, image );

if( waitKey( DELAY ) >= 0 )

{ return -1; }

}

return 0;

}

//---------------------------【Drawing_Random_Ellipses( )函数】----------------------------

// 描述:绘制随机的椭圆

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

int Drawing_Random_Ellipses( Mat image, char* window_name, RNG rng )

{

int lineType = 8;

for ( int i = 0; i < NUMBER; i++ )

{

Point center;

center.x = rng.uniform(x_1, x_2);

center.y = rng.uniform(y_1, y_2);

Size axes;

axes.width = rng.uniform(0, 200);

axes.height = rng.uniform(0, 200);

double angle = rng.uniform(0, 180);

ellipse( image, center, axes, angle, angle - 100, angle + 200,

randomColor(rng), rng.uniform(-1,9), lineType );

imshow( window_name, image );

if( waitKey(DELAY) >= 0 )

{ return -1; }

}

return 0;

}

//---------------------------【Drawing_Random_Polylines( )函数】--------------------------

// 描述:绘制随机的折线

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

int Drawing_Random_Polylines( Mat image, char* window_name, RNG rng )

{

int lineType = 8;

for( int i = 0; i< NUMBER; i++ )

{

Point pt[2][3];

pt[0][0].x = rng.uniform(x_1, x_2);

pt[0][0].y = rng.uniform(y_1, y_2);

pt[0][1].x = rng.uniform(x_1, x_2);

pt[0][1].y = rng.uniform(y_1, y_2);

pt[0][2].x = rng.uniform(x_1, x_2);

pt[0][2].y = rng.uniform(y_1, y_2);

pt[1][0].x = rng.uniform(x_1, x_2);

pt[1][0].y = rng.uniform(y_1, y_2);

pt[1][1].x = rng.uniform(x_1, x_2);

pt[1][1].y = rng.uniform(y_1, y_2);

pt[1][2].x = rng.uniform(x_1, x_2);

pt[1][2].y = rng.uniform(y_1, y_2);

const Point* ppt[2] = {pt[0], pt[1]};

int npt[] = {3, 3};

polylines(image, ppt, npt, 2, true, randomColor(rng), rng.uniform(1,10), lineType);

imshow( window_name, image );

if( waitKey(DELAY) >= 0 )

{ return -1; }

}

return 0;

}

//---------------------------【Drawing_Random_Filled_Polygons( )函数】------------------

// 描述:绘制随机的多边形

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

int Drawing_Random_Filled_Polygons( Mat image, char* window_name, RNG rng )

{

int lineType = 8;

for ( int i = 0; i < NUMBER; i++ )

{

Point pt[2][3];

pt[0][0].x = rng.uniform(x_1, x_2);

pt[0][0].y = rng.uniform(y_1, y_2);

pt[0][1].x = rng.uniform(x_1, x_2);

pt[0][1].y = rng.uniform(y_1, y_2);

pt[0][2].x = rng.uniform(x_1, x_2);

pt[0][2].y = rng.uniform(y_1, y_2);

pt[1][0].x = rng.uniform(x_1, x_2);

pt[1][0].y = rng.uniform(y_1, y_2);

pt[1][1].x = rng.uniform(x_1, x_2);

pt[1][1].y = rng.uniform(y_1, y_2);

pt[1][2].x = rng.uniform(x_1, x_2);

pt[1][2].y = rng.uniform(y_1, y_2);

const Point* ppt[2] = {pt[0], pt[1]};

int npt[] = {3, 3};

fillPoly( image, ppt, npt, 2, randomColor(rng), lineType );

imshow( window_name, image );

if( waitKey(DELAY) >= 0 )

{ return -1; }

}

return 0;

}

//---------------------------【Drawing_Random_Circles( )函数】-----------------------------

// 描述:绘制随机的圆

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

int Drawing_Random_Circles( Mat image, char* window_name, RNG rng )

{

int lineType = 8;

for (int i = 0; i < NUMBER; i++)

{

Point center;

center.x = rng.uniform(x_1, x_2);

center.y = rng.uniform(y_1, y_2);

circle( image, center, rng.uniform(0, 300), randomColor(rng),

rng.uniform(-1, 9), lineType );

imshow( window_name, image );

if( waitKey(DELAY) >= 0 )

{ return -1; }

}

return 0;

}

//---------------------------【Displaying_Random_Text( )函数】-----------------------------

// 描述:绘制随机的文字

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

int Displaying_Random_Text( Mat image, char* window_name, RNG rng )

{

int lineType = 8;

for ( int i = 1; i < NUMBER; i++ )

{

Point org;

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

imshow( window_name, image );

if( waitKey(DELAY) >= 0 )

{ return -1; }

}

return 0;

}

//---------------------------【Displaying_Big_End( )函数】------------------------------------

// 描述:绘制最终的结束效果

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

int Displaying_Big_End( Mat image, char* window_name, 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_PLAIN, 3,

Scalar(50, i, i), 5, lineType );

imshow( window_name, image2 );

if( waitKey(DELAY) >= 0 )

{ return -1; }

}

return 0;

}

解析:

1)第一步是实例化一个 Random Number Generator(随机数发生器对象) (RNG);RNG rng( 0xFFFFFFFF );RNG的实现了一个随机数发生器,随机数发生器类 (RNG) 并得到均匀分布的随机数。在上面的例子中, rng 是用数值 0xFFFFFFFF 来实例化的一个RNG对象.

2)然后我们初始化一个 0 矩阵(代表一个全黑的图像), 并且指定它的宽度,高度,和像素格式:

/// 初始化一个0矩阵

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

/// 把它会知道一个窗口中

imshow( window_name, image );

3)然后我们开始疯狂的绘制。看过代码时候你会发现它主要分八个部分,正如函数定义的一样,所有这些范数都遵循相同的模式,所以我们只分析其中的一组,因为这适用于所有。

4)查看函数 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 次。 并且函数 line 在循环中, 这意味着要生成 NUMBER 条线段。线段的两个端点分别是 pt1 和 pt2. 对于 pt1 我们看到:

pt1.x = rng.uniform( x_1, x_2 );

pt1.y = rng.uniform( y_1, y_2 );

我们知道 rng 是一个 随机数生成器 对象。在上面的代码中我们调用了 rng.uniform(a,b)
。这指定了一个在 a 和 b 之间的均匀分布(包含 a, 但不含 b)。

由上面的说明,我们可以推断出 pt1 和 pt2 将会是随机的数值,因此产生的线段是变幻不定的,这会产生一个很好的视觉效果(从下面绘制的图片可以看出)。我们还可以发现, 在 line 的参数设置中,对于 color 的设置我们用了:

randomColor(rng)

让我们来看看函数的实现:

static Scalar randomColor( RNG& rng )

{

int icolor = (unsigned) rng;

return Scalar( icolor&255, (icolor>>8)&255, (icolor>>16)&255 );

}

正如我们看到的,函数的返回值是一个用三个随机数初始化的 Scalar 对象,这三个随机数代表了颜色的 R, G, B 分量。所以,线段的颜色也是随机的!

5)上面的解释同样适用于其它的几何图形,比如说参数 center(圆心) 和 vertices(顶点) 也是随机的。

6)在结束之前,我们还应该看看函数 Display_Random_Text 和 Displaying_Big_End, 因为它们有一些有趣的特征:

7)Display_Random_Text:

int Displaying_Random_Text( Mat image, char* window_name, RNG rng )

{

int lineType = 8;

for ( int i = 1; i < NUMBER; i++ )

{

Point org;

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

imshow( window_name, image );

if( waitKey(DELAY) >= 0 )

{ return -1; }

}

return 0;

}

这些看起来都很熟悉,但是这一句:

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

函数 putText 都做了些什么?在我们的例子中:

在 image 上绘制文字 “Testing text rendering” 。

文字的左下角将用点 org 指定。

字体参数是用一个在 [0, 8> 之间的整数来定义。

字体的缩放比例是用表达式 rng.uniform(0, 100)x0.05 + 0.1 指定(表示它的范围是 [0.1, 5.1>)。

字体的颜色是随机的 (记为 randomColor(rng))。

字体的粗细范围是从 1 到 10, 表示为 rng.uniform(1,10) 。

因此, 我们将绘制 (与其余函数类似) NUMBER 个文字到我们的图片上,以位置随机的方式。

8)Displaying_Big_End

int Displaying_Big_End( Mat image, char* window_name, RNG rng )

{

Size textsize = getTextSize("OpenCV forever!", CV_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, CV_FONT_HERSHEY_COMPLEX, 3,

Scalar(i, i, 255), 5, lineType );

imshow( window_name, image2 );

if( waitKey(DELAY) >= 0 )

{ return -1; }

}

return 0;

}

除了 getTextSize (用于获取文字的大小参数), 我们可以发现在 for 循环里的新操作:

image2 = image - Scalar::all(i)

**image2** 是 **image** 和 **Scalar::all(i)** 的差。事实上,**image2** 的每个像素都是 **image** 的每个像素减去 **i** (对于每个像素,都是由R,G,B三个分量组成,每个分量都会独立做差)的差。

我们还要知道,减法操作 总是 保证是 合理 的操作, 这表明结果总是在合理的范围内 (这个例子里结果不会为负数,并且保证在 0~255的合理范围内)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: