在上一篇中,我們了解了如何使用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 );
}
}
運作結果
