基础学习笔记之opencv(14):随机数发生器&绘制文字
本文主要介绍下opencv中自带的一个随机数发生器的类RNG,这里我用这个类来画一些图形,和基础学习笔记之opencv(13):基本绘图 一文中类似,只是 这里画出来图像的坐标,大小,颜色,角度等所有信息都是随机的,且是用RNG这个类产生的。参考文献为opencv自带tutiol及其代码。
开发环境:opencv2.4.2+Qt4.8.2+ubuntu12.04+QtCreator2.5
实验功能:
1. 该实验可以画6中几何图形和1个文本显示,每种都是画80个,每画完一个延时100ms。
2. 打开软件后,默认画的图为直线。可以在软件的左下角Drawing Type下拉列表中选择不同的几何绘画图形及文字,这6种几何图形分别为画直线,画矩形,画椭圆弧线,画多边形,画圆,画填充多边形。文本显示为显示“OpenCv Forever!”,选择完后在窗口中会自动显示其随机绘图过程,
3. 单击Close按钮,退出软件。
实验说明:
1. Qt Gui界面的显示是在程序的构造函数执行完后完成的,所以如果在构造函数中对界面有动态的输出效果我们是看不到的,只能都构造函数执行完了后才能看到最后的结果。那么怎么办才能做到在构造函数结束时自动调用某一程序来完成我们想要看到的动态初始化效果呢?这里可以使用QTimer下的singleShot()函数。例如:
Qtimer::singleShot(0, this, SLOT(event()));
其中第一个参数为时隔多长(单位为ms)执行后面的event信号函数,当然该函数的函数名可以自己定义。这句代码的意思是立即执行执行event()函数。
2. 和sleep()函数一样,在Qt中也不能用opencv中的waitKey()函数来进行延时,否则也会出现其它错误。
3. polylines()函数和上篇文章的fillPoly()函数有点不同,polylines()函数为画多边形的外框,而fillPoly()函数为填充多边形。其中polylines的第5个参数为是否需要画闭合的多边形标志位。当然了,还有一点不同的是在fillPoly()函数中不需要参数thickness,因为它的功能是填充多边形,就不需要线型的宽度了。
4. 这几种几何图形耗时最多的是画随机椭圆弧形,因为它的8个属性都是随机的,需要稍微多的一些计算时间(当然了,这些时间相对人眼来说可以忽略),8个属性分别为椭圆中心点,长半轴,短半轴,倾斜角度,其实角度,结束角度,弧形颜色,线型大小。
实验结果:
画随机直线和随机矩形效果图如下:
画随机椭圆弧形和随机多边形框效果图如下:
画随机圆和随机填充多边形效果图如下:
最后显示文本OpenCV Forever!效果图如下:
实验主要部分代码及其注释(附录有其工程code下载链接):
#include "mainwindow.h" #include "ui_mainwindow.h" #include <iostream> #include <QElapsedTimer> #include <QTimer> using namespace std; MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); rng( 0xFFFFFFFF ); window_width = 700; window_height = 500; number = 80; delay = 100; x1 = -window_width/2; x2 = window_width*2/3; y1 = -window_width/2; y2 = window_width*2/3; cout<<"Begin"<<endl; /*怎么才能做到在构造函数结束时自动调用某一程序来完成我们想要看到的动态初始化效果呢?这里可以使用QTimer下的singleShot()函数。 Qtimer::singleShot(0, this, SLOT(***())); 其中第一个参数为时隔多长(单位为ms)执行后面的信号函数,这里是立即执行。*/ QTimer::singleShot(0, this, SLOT(project_begin())); } MainWindow::~MainWindow() { delete ui; } void MainWindow::draw_rand_lines(Mat& img, RNG& rng) { img = Mat::zeros( window_height, window_width, CV_8UC3 ); int thickness; QElapsedTimer t; for( int i = 0; i <= number; i++ ) { Point pt1( rng.uniform( 0, window_width), rng.uniform( 0, window_width) ); Point pt2( rng.uniform( 0, window_width), rng.uniform( 0, window_width) ); thickness = (int)rng.uniform( 1, 8 ); line( img, pt1, pt2, MainWindow::rand_color(rng), thickness, 8 ); imwrite( "../drawing/lines.jpg", img ); ui->textBrowser->clear(); ui->textBrowser->append( "<img src=../drawing/lines.jpg>" ); // waitKey( delay );//该函数 t.start(); if( t.elapsed() <= delay ) QCoreApplication::processEvents(); } } void MainWindow::draw_rand_rectangles(Mat &img, RNG &rng) { img = Mat::zeros( window_height, window_width, CV_8UC3 ); int thickness; QElapsedTimer t; for( int i = 0; i <= number; i++ ) { Point pt1( rng.uniform( 0, window_width), rng.uniform( 0, window_width) ); Point pt2( rng.uniform( 0, window_width), rng.uniform( 0, window_width) ); thickness = (int)rng.uniform( 1, 8 ); rectangle( img, pt1, pt2, rand_color(rng), thickness, 8 ); imwrite( "../drawing/rectangles.jpg", img ); ui->textBrowser->clear(); ui->textBrowser->append( "<img src=../drawing/rectangles.jpg>" ); t.start(); if( t.elapsed() <= delay ) QCoreApplication::processEvents(); } } void MainWindow::draw_rand_ellipses(Mat &img, RNG &rng) { img = Mat::zeros( window_height, window_width, CV_8UC3 ); int thickness; int w1, h1; double angle, start_angle, end_angle; QElapsedTimer t; for( int i = 0; i <= number; i++ ) { Point pt1( rng.uniform(x1, x2), rng.uniform(y1, y2) ); thickness = (int)rng.uniform( 1, 8 ); w1 = rng.uniform( 0, 200 ); h1 = rng.uniform( 0, 200 ); angle = rng.uniform( 0, 360 ); start_angle = rng.uniform( 0, (int)(angle-150) );//与opencv给的不同,我这里的start角度也是随机的 end_angle = rng.uniform( 0, (int)(angle+150) );//end角度当然也是随机的 ellipse( img, pt1, Size(w1, h1), angle, start_angle, end_angle, rand_color(rng), thickness, 8 ); imwrite( "../drawing/ellipses.jpg", img ); ui->textBrowser->clear(); ui->textBrowser->append( "<img src=../drawing/ellipses.jpg>" ); t.start(); while( t.elapsed() <= delay ) QCoreApplication::processEvents(); } } void MainWindow::draw_rand_polylines(Mat &img, RNG &rng) { img = Mat::zeros( window_height, window_width, CV_8UC3 ); int thickness; QElapsedTimer t; for( int i = 0; i <= number; i++ ) { thickness = (int)rng.uniform( 1, 8 ); 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 *pts[2] = {pt[0], pt[1]}; const int npts[] = {3, 3}; //每次2组 polylines( img, pts, npts, 2, 1, rand_color(rng), thickness, 8 ); imwrite( "../drawing/polylines.jpg", img ); ui->textBrowser->clear(); ui->textBrowser->append( "<img src=../drawing/polylines.jpg>" ); t.start(); while( t.elapsed() <= delay ) QCoreApplication::processEvents(); } } void MainWindow::draw_rand_circles(Mat &img, RNG &rng) { img = Mat::zeros( window_height, window_width, CV_8UC3 ); int thickness, radius; Point pt; QElapsedTimer t; for( int i = 0; i <= number; i++ ) { thickness = (int)rng.uniform( 1, 8 ); pt.x = rng.uniform( 0, window_width ); pt.y = rng.uniform( 0, window_height ); radius = (int)rng.uniform( 0, window_height/2 ); circle( img, pt, radius, rand_color(rng), thickness, 8 ); imwrite( "../drawing/circles.jpg", img ); ui->textBrowser->clear(); ui->textBrowser->append( "<img src=../drawing/circles.jpg>" ); t.start(); while( t.elapsed() <= delay ) QCoreApplication::processEvents(); } } void MainWindow::draw_rand_filledpolys(Mat &img, RNG &rng) { img = Mat::zeros( window_height, window_width, CV_8UC3 ); QElapsedTimer t; 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 *pts[2] = {pt[0], pt[1]}; const int npts[] = {3, 3}; //注意这个函数是没有thickness这个参数的,因为这是个填充函数,所以不需要 fillPoly( img, pts, npts, 2, rand_color(rng), 8 ); imwrite( "../drawing/filledpolys.jpg", img ); ui->textBrowser->clear(); ui->textBrowser->append( "<img src=../drawing/filledpolys.jpg>" ); t.start(); while( t.elapsed() <= delay ) QCoreApplication::processEvents(); } } void MainWindow::draw_rand_texts(Mat &img, RNG &rng) { img = Mat::zeros( window_height, window_width, CV_8UC3 ); QElapsedTimer t; Point pt;//字体左下角坐标 int font_face; int thickness; double font_scale; for( int i = 0; i <= number; i++ ) { font_face = rng.uniform( 0 ,8 );//字体模式选择 font_scale = rng.uniform(0, 100)*0.05+0.1;//字体尺寸缩放选择 thickness = rng.uniform( 1, 8 ); pt.x = rng.uniform( 0, window_width ); pt.y = rng.uniform( 0, window_height ); putText( img, "OpenCV Forever!", pt, font_face, font_scale, rand_color(rng), thickness, 8 ); imwrite( "../drawing/texts.jpg", img ); ui->textBrowser->clear(); ui->textBrowser->append( "<img src=../drawing/texts.jpg>" ); t.start(); while( t.elapsed() <= delay ) QCoreApplication::processEvents(); } } Scalar MainWindow::rand_color(RNG& rng) { int color = (unsigned)rng; return Scalar( color&255, (color>>8)&255, (color>>16)&255 ); } void MainWindow::on_closeButton_clicked() { close(); } /*选择不同的模式*/ void MainWindow::on_comboBox_currentIndexChanged(int index) { if( 0 == index ) { draw_rand_lines( img, rng ); } else if( 1 == index ) { draw_rand_rectangles( img, rng ); } else if( 2 == index ) { draw_rand_ellipses( img, rng ); } else if( 3 == index ) { draw_rand_polylines( img, rng ); } else if( 4 == index ) { draw_rand_circles( img, rng ); } else if(5 == index ) { draw_rand_filledpolys( img, rng ); } else if( 6 == index ) { draw_rand_texts( img, rng ); } } void MainWindow::project_begin() { draw_rand_lines( img, rng ); }
实验总结:
通过本次实验,对c++中类的构造函数有了进一步的认识,当然了,对opencv的RNG随机数相关的类有了一定的了解,虽然在这里都是用它来产生均匀分布,其实它还可用产生高斯等分布。