OpenCV  4.10.0
开源计算机视觉
正在加载...
正在搜索...
无匹配项
使用 OpenCV 随机生成器和文本

上一教程: 基本绘图
下一教程: 平滑图像

原始作者Ana Huamán
兼容性OpenCV >= 3.0

目标

在本教程中,你将学习如何

  • 使用随机数生成器类 (cv::RNG ) 和如何从均匀分布中获取一个随机数。
  • 使用 cv::putText 函数在 OpenCV 窗口中显示文本

代码

  • 在上一个教程(基本绘图)中,我们绘制了各种几何图形,给出了诸如坐标(采用 cv::Point 形式)、颜色、粗细等的输入参数。你可能已经注意到,我们为这些参数给出了具体的值。
  • 在本教程中,我们打算为绘图参数使用随机值。我们还打算用大量的几何图形填充我们的图像。由于我们将以随机的方式对它们进行初始化,这个过程将是自动的,是通过使用循环实现的。
  • 此代码位于你的 OpenCV 样本文件夹中。否则,你可以从 此处 获取它

说明

  1. 让我们从检查main 函数开始。我们观察到,我们做的第一件事是创建一个随机数生成器对象 (RNG)
    RNG rng( 0xFFFFFFFF );
    RNG 实现了随机数生成器。在本例中,rng 是使用值0xFFFFFFFF 初始化的 RNG 元素
  2. 然后,我们创建一个初始化为的矩阵(这意味着它将显示为黑色),指定它的高度、宽度和类型
    Mat image = Mat::zeros( window_height, window_width, CV_8UC3 );
    imshow( window_name, image );
    #define CV_8UC3
    定义 interface.h:90
  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 = Displaying_Random_Text( image, window_name, rng );
    if( c != 0 ) return 0;
    c = Displaying_Big_End( image, window_name, rng );
    上述所有函数都遵循相同的模式,因此我们只分析其中几个函数,因为所有函数的解释都相同。
  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;
    }
    _Tp x
    点的 x 坐标
    定义 types.hpp:201
    我们可以观察到以下内容
    • for 循环将重复 NUMBER 次。由于函数 cv::line 在此循环中,这意味着将生成 NUMBER 行。
    • 线的端点由 pt1pt2 给出。对于 pt1,我们可以看到
      pt1.x = rng.uniform( x_1, x_2 );
      pt1.y = rng.uniform( y_1, y_2 );
      • 我们知道 rng 是一个随机数生成器对象。在上面的代码中,我们调用 rng.uniform(a,b)。这会在值 ab 之间生成一个均匀分布的随机分布(在 a 中包含,在 b 中不包含)。
      • 从上面的解释中,我们推断出端点 pt1pt2 将是随机值,因此线的位置将非常不可预测,从而产生良好的视觉效果(查看下面的“结果”部分)。
      • 另一个观察结果是,我们注意到在 cv::line 参数中,对于颜色输入,我们输入
        randomColor(rng)
        让我们查看函数实现
        static Scalar randomColor( RNG& rng )
        {
        int icolor = (unsigned) rng;
        return Scalar( icolor&255, (icolor>>8)&255, (icolor>>16)&255 );
        }
        如我们所见,返回值是一个带有 3 个随机初始化值的标量,它们用作线条颜色的RGB 参数。因此,线条的颜色也应该是随机的!
  5. 以上说明适用于生成圆形、椭圆和多边形等其他函数。如centervertices等参数也是随机生成的。
  6. 结束之前,我们还应看一看函数Display_Random_TextDisplaying_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);

    因此,cv::putText函数的作用是什么?在我们的示例中

    • 绘制文本**"Testing text rendering"**在image
    • 文本的左下角位于点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!", 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;
    }

    除了函数getTextSize(它获得参数文本的大小)以外,我们可以在foor循环中观察到新操作

    image2 = image - Scalar::all(i)

    因此,image2imageScalar::all(i)的减法。事实上,这里发生的情况是,image2的每个像素将是image的每个像素与i值相减的结果(记住对于每个像素,我们考虑三个值,例如 R、G 和 B,因此它们每个都会受到影响)。

    同样,还要记住,减法运算总是在内部执行饱和运算,这意味着获得的结果将始终在允许范围内(对于我们的示例来说,范围为无负值且处于 0 到 255 之间)。

结果

正如您刚才在代码部分中看到的那样,该程序将按顺序执行各种绘图函数,这些函数将生成

  1. 首先,屏幕上将出现一组随机的NUMBER线,如同在本屏幕截图中看到的那样
  1. 然后,会出现一组新的图形,此时为矩形
  2. 现在会显示一些椭圆,每个椭圆都有随机的位置、大小、粗细和弧长
  1. 现在,屏幕上会出现具有 03 个段的折线,同样是随机配置。
  1. 接下来是填充的多边形(在本示例中为三角形)。
  2. 要出现的最后一种几何图形:圆形!
  1. 接近结束时,文本“*测试文本渲染*”将以各种字体、大小、颜色和位置显示。
  2. 最后的高潮(顺便说一句,这同样代表着一个伟大的真理)