Random generator and text with OpenCV
此为OpenCV官方教程的个人翻译
目标
在本篇文章中,您将学习如何:
代码
- 在上一教程(基本绘图)中,我们绘制了各种几何图形,并给出了坐标(以Point的形式),颜色,厚度等输入参数。您可能已经注意到,我们为这些参数提供了特定的值。
- 在本教程中,我们打算对绘图参数使用随机值。此外,我们打算用大量的几何图形填充我们的图像。由于我们将以随机方式初始化它们,因此此过程将自动进行,并使用 循环 。
- 此代码位于 OpenCV 示例文件夹中。或者,您可以从这里获取它。
解释
-
让我们从查看 main 函数开始。我们观察到,我们做的第一件事是创建一个随机数生成器对象(RNG):
RNG rng( 0xFFFFFFFF );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 ); -
然后我们继续画疯狂的东西。看一下代码,可以看到它主要分为8个部分,定义为函数:
/// 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 );所有这些函数都遵循相同的模式,因此我们将只分析其中的几个函数,因为相同的解释适用于所有函数。
-
我们来看看函数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 循环将重复多次。由于函数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参数中,对于颜色输入,我们输入:
randomColor(rng)让我们看一下函数实现:
static Scalar randomColor( RNG& rng ) { int icolor = (unsigned) rng; return Scalar( icolor&255, (icolor>>8)&255, (icolor>>16)&255 ); }正如我们所看到的,返回值是一个具有3个随机初始化值的Scalar,这些值用作线条颜色的R,G和B参数。因此,线条的颜色也将是随机的!
-
-
-
上述说明适用于生成圆、椭圆、多边形等的其他函数。中心和顶点等参数也是随机生成的。
-
在完成之前,我们还应该看一下Display_Random_Text函数和Displaying_Big_End,因为它们都有一些有趣的功能:
-
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: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”**
- 文本的左下角将位于Point中
- 字体类型是以下区域中的随机整数值:\((0,8]\)
- 字体的比例由表达式 rng.uniform(0, 100)x0.05 + 0.1 表示,其范围为:\([0.1,5.1)\)
- 文本颜色是随机的(用 randomColor(rng) 表示))
- 文本粗细范围介于 1 和 10 之间,由 rng.uniform(1,10) 指定
因此,我们将在随机位置的图像上获得(与其他绘图函数相似)NUMBER文本。
-
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(获取参数文本的大小)之外,我们可以观察到的新操作位于 foor 循环中:
image2 = image - Scalar::all(i)因此,image2 是 image 和 Scalar::all(i)的减法。事实上,这里发生的事情是,image2 的每个像素都将是image的每个像素减去 i 的值的结果(请记住,对于每个像素,我们考虑三个值,如 R、G 和 B,因此每个值都会受到影响)
还要记住,减法运算总是在内部执行饱和运算,这意味着获得的结果将始终在允许的范围内(没有负数,在我们的示例中介于0和255之间)。
结果
正如您刚刚在代码部分中看到的那样,该程序将按顺序执行各种绘制函数,这将产生:
-
首先,屏幕上将出现一组随机的线,如以下屏幕截图所示:

-
接下来是一些矩形

-
椭圆

-
PolyLines

-
圆

-
文字

-
最终


浙公网安备 33010602011771号