opencv 2.x学习笔记(十)随机数发生器、绘制文字

本文介绍了OpenCV中的随机数生成器RNG的使用,包括构造函数、生成均匀分布和高斯分布随机数的方法。同时,详细讲解了如何使用putText函数在图像上绘制文字,包括参数设置和实例演示。

在上一篇中,我们了解了如何使用opencv为我们提供的基本绘图函数来为我们来绘制一个简单的图像。在这一篇中,我们将继续使用上一篇中所讲到的函数来演示opencv的随机数产生功能以及如何绘制文字。

随机数产生器

在我们的程序中,经常需要使用随机数生成功能。为此,opencv为我们提供了一个随机数生成器类,RNG。它封装了一个64位的int类型整数,为此我们课可以得到一个随机的Scalar和随机的数组。目前,它支持产生均匀分布随机数和高斯分布随机数。

它的构造函数的初始化可以传入一个64位的整型参数作为随机数产生器的初值。RNG类的定义大致如下:

/*!
   Random Number Generator

   The class implements RNG using Multiply-with-Carry algorithm
*/
class CV_EXPORTS RNG
{
public:
    enum { UNIFORM=0, NORMAL=1 };

    RNG();
    RNG(uint64 state);
    //! updates the state and returns the next 32-bit unsigned integer random number
    unsigned next();

    operator uchar();
    operator schar();
    operator ushort();
    operator short();
    operator unsigned();
    //! returns a random integer sampled uniformly from [0, N).
    unsigned operator ()(unsigned N);
    unsigned operator ()();
    operator int();
    operator float();
    operator double();
    //! returns uniformly distributed integer random number from [a,b) range
    int uniform(int a, int b);
    //! returns uniformly distributed floating-point random number from [a,b) range
    float uniform(float a, float b);
    //! returns uniformly distributed double-precision floating-point random number from [a,b) range
    double uniform(double a, double b);
    void fill( InputOutputArray mat, int distType, InputArray a, InputArray b, bool saturateRange=false );
    //! returns Gaussian random variate with mean zero.
    double gaussian(double sigma);

    uint64 state;
};
其中主要函数的含义:

  • next():取出下一个随机数。
  • uniform():返回指定范围的均匀分布的随机数。
  • gaussian():返回一个高斯随机数。
  • fill():利用随机数填充矩阵。

因此我们可以这样来构造一个rng对象:

RNG rng( 0xFFFFFFFFFFFFFFFF );
可以这样来产生一个随机数。

pt1.x = rng.uniform( 0.0, (double)window_width );
同时可以这样来得到它的下一个随机数。

int icolor = (unsigned) rng;
(调用unsigned(), 在该函数内部,调用next())。

绘制文字

了解了如何产生一个随机数之后,我们的任务已经进行了一半,那么我们该如何在一个图像中绘制文字呢?

opencv为我们提供了putText函数来完成这一功能,具体声明如下:

//! renders text string in the image
CV_EXPORTS_W void putText( Mat& img, const string& text, Point org,
                         int fontFace, double fontScale, Scalar color,
                         int thickness=1, int lineType=8,
                         bool bottomLeftOrigin=false );

  • img: 要绘制文字的图像。
  • text: 要绘制的文字。
  • org: 图像中文字字符串的左下角坐标。
  • fontFace:字体类型,可以在下面类型中取值。

FONT_HERSHEY_SIMPLEX, FONT_HERSHEY_PLAIN, FONT_HERSHEY_DUPLEX, FONT_HERSHEY_COMPLEX, FONT_HERSHEY_TRIPLEX, 

FONT_HERSHEY_COMPLEX_SMALL, FONT_HERSHEY_SCRIPT_SIMPLEX, FONT_HERSHEY_SCRIPT_COMPLEX。

  • fontScale: 字体的比例因子,用以乘以字体特定的基本尺寸。
  • color: 文本颜色。
  • bottomLeftOrigin: 如果为true,图像数据的起点在左下角,否则在左上角。

我们可以这样来使用:

putText( image2, "Hello OpenCV!", org, FONT_HERSHEY_COMPLEX, 3, Scalar( i, i, 255 ), 5 );
了解这些之后,我们就可以来做一个随机产生的线条和三角形的一个演示实例。为了获得一个图像渐变的效果,我们在代码中每隔一段时间,就对原来的图像减去一个指定值。如下所示:

	Mat image2;
	for( int i = 0; i < 255; i += 2 )
	{
		image2 = image - Scalar::all( i );
		putText( image2, "Hello OpenCV!", org, FONT_HERSHEY_COMPLEX, 3, Scalar( i, i, 255 ), 5 );
		waitKey(5);
		imshow( window_name, image2 );
	}

完整实例:

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>

using namespace std;
using namespace cv;

const int window_height = 600;
const int window_width  = 900;
const int NUMBER = 100;

Scalar randomColor( RNG& rng );
void Drawing_Random_Lines(  Mat image, char * window_name, RNG rng );
void Drawing_Random_Filled_Polygons( Mat image, char * window_name, RNG rng );
void Drawing_Text( Mat image, char * window_name, RNG rng );

int main()
{
	RNG rng( 0xFFFFFFFFFFFFFFFF );
	Mat image = Mat::zeros( window_height, window_width, CV_8UC3 );

	char window_name[] = "Random image";

	Drawing_Random_Lines( image, window_name, rng );
	Drawing_Random_Filled_Polygons( image, window_name, rng );
	Drawing_Text( image, window_name, rng );
	waitKey(0);
	return 0;
}

Scalar randomColor( RNG& rng )
{
	int icolor = (unsigned) rng;
	return Scalar( icolor&255, (icolor>>8)&255, (icolor>>16)&255 );
}

void Drawing_Random_Lines( Mat image, char * window_name, RNG rng )
{
	Point pt1, pt2;
	for( int i = 0; i < NUMBER; i ++ )
	{
		pt1.x = rng.uniform( 0.0, (double)window_width );
		pt1.y = rng.uniform( 0.0, (double)window_height );
		pt2.x = rng.uniform( 0.0, (double)window_width );
		pt2.y = rng.uniform( 0.0, (double)window_height );

		line( image, pt1, pt2, randomColor( rng ), 2 );
		waitKey(5);
		imshow( window_name, image );
	}
}

void Drawing_Random_Filled_Polygons( Mat image, char * window_name, RNG rng )
{
	for( int i = 0; i < NUMBER; i ++ )
	{
		Point pt[2][3];
		pt[0][0].x = rng.uniform(0, window_width);
		pt[0][0].y = rng.uniform(0, window_height);
		pt[0][1].x = rng.uniform(0, window_width);
		pt[0][1].y = rng.uniform(0, window_height);
		pt[0][2].x = rng.uniform(0, window_width);
		pt[0][2].y = rng.uniform(0, window_height);
		pt[1][0].x = rng.uniform(0, window_width);
		pt[1][0].y = rng.uniform(0, window_height);
		pt[1][1].x = rng.uniform(0, window_width);
		pt[1][1].y = rng.uniform(0, window_height);
		pt[1][2].x = rng.uniform(0, window_width);
		pt[1][2].y = rng.uniform(0, window_height);

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

		fillPoly( image, ppt, npt, 2, randomColor( rng ) );
		imshow( window_name, image );
		waitKey(5);
	}
}

void Drawing_Text( Mat image, char * window_name, RNG rng )
{
	Size textsize = getTextSize( "Hello OpenCV!", FONT_HERSHEY_COMPLEX, 3, 5, 0 );
	Point org((window_width - textsize.width)/2, (window_height - textsize.height)/2 );

	Mat image2;
	for( int i = 0; i < 255; i += 2 )
	{
		image2 = image - Scalar::all( i );
		putText( image2, "Hello OpenCV!", org, FONT_HERSHEY_COMPLEX, 3, Scalar( i, i, 255 ), 5 );
		waitKey(5);
		imshow( window_name, image2 );
	}
}

运行结果




评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值