乞丐哥的私房菜(Windows OpenCV 篇 —— Image Processing 节 之 Random generator and text with OpenCV 随机生成器)二

  • 操作系统:Windows 7 SP1
  • 编译器:mingw64 g++ 8.1.0
  • 编辑器:Emacs 30.1
  • OpenCV :4.12.0

目录

  • 使用随机数生成器类(cv::RNG)以及如何获取随机数
  • 使用函数 cv::putText 在 OpenCV 窗口中显示文件

源代码

  • 基本绘图中绘制了几种几何图形,输入参数包括坐标(以 cv::Point 的形式)、颜色、粗细等。为参数提供了具体的值
  • 在这里,使用随机数作为绘图参数。此外,打算在图像中填充大量的几何图形。将以随机方式初始化,这个过程将是自动的,并且会使用循环来完成
  • 源码在这里下载

解释说明

  1. 查看主函数,注意到首先做的事情是创建一个随机数生成器对象(RNG):
      RNG rng(0xFFFFFFFF);
    
    RNG 实现了一个随机数生成器。在这里,rng 是一个用值 0xFFFFFFFF 初始化的 RNG 元素
  2. 然后我们创建一个初始化为零(这意味着它会显示黑色)的矩阵,并指定其高度、宽度和类型:
      Mat image = Mat::zeros(window_hight, window_width, CV_8UC3);
      imshow(window_name, image);
    
  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;
      }
    
    我们可以观察到以下内容:
    • 这个 for 循环将重复 NUMBER 次。由于函数 cv::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 将是随机值,因此线的位置是相当难以预测的,从而产生良好的视觉效果(看下面的结果部分)
      • 作为另一个观察,注意到在 cv::line 参数中,对于颜色输入我们输入:
          randomColor(rng);
        
        看看函数的实现:
          static Scalar randomColor( RNG& rng )
          {
            int icolor = (unsigned) rng;
            return Scalar( icolor&255, (icolor>>8)&255, (icolor>>16)&255 );
          }
        
        从上面可以看出,返回值是一个 Scalar,它包含 3 个随机初始化值,用作R、G 和 B颜色,即线条颜色的参数,因此,线条的颜色也会是随机的
  5. 上面的解释适用于生成圆、椭圆、多边形等其他函数。诸如中心和顶点等参数也是随机生成的
  6. 在完成之前,我们还应该看看函数 Display_Random_Text 和 Displaying_Big_End,因为它们都有几个有趣的功能:
  7. 显示随机文本:
      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”
    • 文本的左下角将位于点 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. Display_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(获取文本的大小),新的操作我们可以在 for 循环中观察到:
      image2 = image - Scalar::all(i)
    
    所以,image2 是 image 减去 Scalar::all(i)。事实上,这里发生的事情是 image2 的每个像素将是 image 的每个像素减去 i 的值的结果(请记住,对于每个像素,我们考虑的是三个值,如 R、G 和 B,所以它们都会受到影响)

结果

正如你在代码部分所看到的,程序将依次执行各种绘图函数,这将产生:

  1. 首先,一组随机的 NUMBER 线将出现在展蓝上,如下截图所示:
    在这里插入图片描述

  2. 然后,一组新的图形会出现:矩形,椭圆
    在这里插入图片描述

  3. 折线再次以随机配置出现在屏幕上
    在这里插入图片描述

  4. 填充多边形(根据随机不同,图形也可能不同)

  5. 最后一个几何图形:圆
    在这里插入图片描述

  6. 在最后时,文本 “Testing Text Rendering” 将以各种字体、大小、颜色和位置出现
    在这里插入图片描述

    因为是随机的,运行的结果是相似的,但不相同

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值