- 操作系统:Windows 7 SP1
- 编译器:mingw64 g++ 8.1.0
- 编辑器:Emacs 30.1
- OpenCV :4.12.0
目录
- 使用随机数生成器类(cv::RNG)以及如何获取随机数
- 使用函数 cv::putText 在 OpenCV 窗口中显示文件
源代码
- 在基本绘图中绘制了几种几何图形,输入参数包括坐标(以 cv::Point 的形式)、颜色、粗细等。为参数提供了具体的值
- 在这里,使用随机数作为绘图参数。此外,打算在图像中填充大量的几何图形。将以随机方式初始化,这个过程将是自动的,并且会使用循环来完成
- 源码在这里下载
解释说明
- 查看主函数,注意到首先做的事情是创建一个随机数生成器对象(RNG):
RNG 实现了一个随机数生成器。在这里,rng 是一个用值 0xFFFFFFFF 初始化的 RNG 元素RNG rng(0xFFFFFFFF);
- 然后我们创建一个初始化为零(这意味着它会显示黑色)的矩阵,并指定其高度、宽度和类型:
Mat image = Mat::zeros(window_hight, window_width, CV_8UC3); imshow(window_name, image);
- 然后我们疯狂的画东西,主要分 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 );
- 查看函数 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);
从上面可以看出,返回值是一个 Scalar,它包含 3 个随机初始化值,用作R、G 和 B颜色,即线条颜色的参数,因此,线条的颜色也会是随机的static Scalar randomColor( RNG& rng ) { int icolor = (unsigned) rng; return Scalar( icolor&255, (icolor>>8)&255, (icolor>>16)&255 ); }
- 上面的解释适用于生成圆、椭圆、多边形等其他函数。诸如中心和顶点等参数也是随机生成的
- 在完成之前,我们还应该看看函数 Display_Random_Text 和 Displaying_Big_End,因为它们都有几个有趣的功能:
- 显示随机文本:
一切看起来都那么的熟悉,但这个表达: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; }
那么,函数 cv::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);
- 在图像中绘制文本 “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 个文本随机覆盖在我们的图像上
- Display_Big_End
除了函数 getTextSize(获取文本的大小),新的操作我们可以在 for 循环中观察到: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; }
所以,image2 是 image 减去 Scalar::all(i)。事实上,这里发生的事情是 image2 的每个像素将是 image 的每个像素减去 i 的值的结果(请记住,对于每个像素,我们考虑的是三个值,如 R、G 和 B,所以它们都会受到影响)image2 = image - Scalar::all(i)
结果
正如你在代码部分所看到的,程序将依次执行各种绘图函数,这将产生: