本文主要介紹下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隨機數相關的類有了一定的了解,雖然在這里都是用它來產生均勻分布,其實它還可用產生高斯等分布。