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

OpenCV_Tutorials——CORE MODULE.THE CORE FUNCTIONALITY——Random genenrator and text with OpenCV

2015-05-26 16:16 393 查看

2.7 随机产生器和OpenCV当中的文字

目标

在教程中,你会学习到:

1、使用随机数字产生类(RNG)并且如何从均匀分布中获得随机数字。

2、使用OpenCV的putText函数在窗口中显示文字

代码

1、在前一个的教程(Basic Drawing)中,我们画了不同的几何图形,给出了例如坐标(使用Points形式的)的输入参数,颜色,线条粗细,等等。你可能已经注意到我们对于那些参数都是给出了特殊的值。

2、在本教程中,我们打算使用为绘图参数使用随机值。同样,我们打算使用大量的几何图形来填满我们的图形。因为我们打算使用随机的形式来进行初始化,这个过程将通过循环的形式自动进行。

3、这里的代码在OpenCV的事例文件夹(OpenCV\sample)。

/**

* @file Drawing_2.cpp

* @brief Simple sample code

*/

#include <opencv2/core/core.hpp>

#include <opencv2/highgui/highgui.hpp>

#include <iostream>

#include <stdio.h>

using namespace cv;

/// Global Variables

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;

/// Function headers

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

/**

* @function main

*/

int main( void )

{

int c;

/// Start creating a window

char window_name[] = "Drawing_2 Tutorial";

/// Also create a random object (RNG)

RNG rng( 0xFFFFFFFF );

/// Initialize a matrix filled with zeros

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

/// Show it in a window during DELAY ms

imshow( window_name, image );

waitKey( DELAY );

/// Now, let's draw some lines

c = Drawing_Random_Lines(image, window_name, rng);

if( c != 0 ) return 0;

/// Go on drawing, this time nice rectangles

c = Drawing_Random_Rectangles(image, window_name, rng);

if( c != 0 ) return 0;

/// Draw some ellipses

c = Drawing_Random_Ellipses( image, window_name, rng );

if( c != 0 ) return 0;

/// Now some polylines

c = Drawing_Random_Polylines( image, window_name, rng );

if( c != 0 ) return 0;

/// Draw filled polygons

c = Drawing_Random_Filled_Polygons( image, window_name, rng );

if( c != 0 ) return 0;

/// Draw circles

c = Drawing_Random_Circles( image, window_name, rng );

if( c != 0 ) return 0;

/// Display text in random positions

c = Displaying_Random_Text( image, window_name, rng );

if( c != 0 ) return 0;

/// Displaying the big end!

c = Displaying_Big_End( image, window_name, rng );

if( c != 0 ) return 0;

waitKey(0);

return 0;

}

/// Function definitions

/**

* @function randomColor

* @brief Produces a random color given a random object

*/

static Scalar randomColor( RNG& rng )

{

int icolor = (unsigned) rng;

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

}

/**

* @function 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;

}

/**

* @function Drawing_Rectangles

*/

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;

}

/**

* @function 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;

}

/**

* @function 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;

}

/**

* @function 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;

}

/**

* @function 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;

}

/**

* @function 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;

}

/**

* @function 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_COMPLEX, 3,

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

imshow( window_name, image2 );

if( waitKey(DELAY) >= 0 )

{ return -1; }

}

return 0;

}

解释

1、让我们查看一下main函数。我们看到第一个东西就是创建了一个随机数字产生器类的对象。

RNG rng(0xFFFFFFFF);

RNG表明这是一个随机数字产生器。在这个例子中,rng作为RNG元素被初始化为0xFFFFFFFF

2、然后我们使用zeros函数初始化矩阵(也就是意味着显示出来是黑色的),指明它的高、宽以及它的类型。

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

imshow(window_name,image);

3、然后我们要画一些杂乱的东西。在对代码进行浏览之后,你可以看到这里主要分成8部分,已定义函数如下:

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

if(c!=0) return 0;

c=Drawing_Random_Big_End(image,window_name,rng);

if(c!=0) return 0;

所有的这些函数都遵循相同的事例,因此我们将要分析其中几个具有代表性的事例。

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

line(image,pt1,pt2,randomColor(rng),rng.uniform(1,10),8);

Imshow(window_name.image);

If(waitKey(DELAY)>=0)

{

rerturn -1;
}

return 0;
}
}

我们可以看出:

1、for循环将重复NUMBER次。因为line函数在循环里面,也就意味着NUMBER条线会将要被绘制出。

2、每条线的两端的点是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之间的随机数(随机数的范围包括啊,不包括b)。

-从上面的解释中,我们推断出端点pt1和pt2是随机产生的,因此线条的位置是完全不可能预测的,产生了好的视觉效果(可以从Result部分中看到)。

-此外我们还注意line函数的参数,对于color参数的输入,我们使用:

randomColor(rng)

让我们看一下这个函数是什么意思:

static Scalar randomColor(RNG& rng)

{

int icolor=(unsigned) rng;

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

}

正如我们所看到的,返回值是一个使用了三个随即初始化R,G,B值的Scalar类型。这个Scalar对象被用于line函数中。因此线条的颜色也将是个随机值!

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,”Texting 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,”Texting text rendering”,org,rng.uniform(0,8),rng.uniform(0,100)*0.05+0.1,randomColor(rng),rng.uniform(1,10),lineType);

putText这个函数的作用是什么呢?在我们的示例中:

(1)在图像中显示“Testing text rendering”

(2)左下端角落的文字会被定位在点org处。

(3)字体类型是是随机的在[0,8>之间的整数值。[ >这个应该是包括前不包括后的意思。

(4)字体被显示的范围在这个rng.uniform(0,100)*0.05+0.1这个表达式(也就是在[0.1,5.1>范围)

(5)文字的颜色是随机的(由randomColor(rng)函数进行)

(6)文字的粗细范围在1-10之间,被指定于函数rng.uniform(1,10)

就像结果中显示的,我们会(映射到其他绘图程序)在图像的随即位置中得到NUMBER条文字。

8、Display_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 forerve!”,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三个值,因此其中任何一个都会被影响到)得差的结果。

同样要记得的是减操作总是包含了saturate操作,也就是说结果总是在允许的范围内存在(在我们的示例中,不会是负数,只会在0-255之间)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐