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的合理范围内)。
// 程序说明:《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的合理范围内)。
相关文章推荐
- shell脚本学习 一
- linux kernel 的配置及编译
- Linux C编程学习笔记-------讲19图形界面编程
- linux c语言实现 执行shell命令
- 第 十 四 天 : 服 务 器 日 常 的 监 控 工 具
- Shell编程(1)
- Linux 应用程序编程基础
- linux命令后台运行
- Android数据存储之文件 openFileOutput & openFileInput
- linux驱动结构
- Linux C编程学习笔记----Fedora系统下开发环境配置
- Linux下SVN服务器自动更新文件到Web目录的方法
- Praat在CentOS 6.5中安装出现./praat /usr/lib/libstdc++.so.6: version `GLIBCXX_3.4.18' not found错误的解决办法
- 解决因特网和xshell考虑到问题
- Linux下MySql的登陆和管理操作
- Linux服务器--CentOS6上源码安装LAMP(实现WordPress,PhpMyAdmin)
- SuSE Linux Enterprise Server 11 SP2 安装mysql
- linux kernel learning notes
- Linux静态库和共享库
- Ubuntu 12.04和centos 7 ip的设置方法