本文主要講講怎樣用opencv畫一些基本圖形,這些圖形包括,直線,圓,橢圓,多邊形等。參考資料為opencv自帶tutiol及其code。
開發環境:ubuntu12.04+Qt4.8.2+QtCreator2.5+opencv2.4.2
實驗功能:
1.單擊Drawing1按鈕,將會畫出atom圖形,並且可以看出該圖形成的過程,共分5個步驟畫,每畫完1個部分會自動停留1s,以便觀察,然后畫下一個部分,直至完成atom圖形。
2.單擊Drawing2按鈕,將會畫出rook圖形,並且可以看出該圖形成的過程,共分3個步驟畫 ,每畫完1個部分會自動停留1s,以便觀察,然后畫下一個部分,直至完成atom圖形。
3.單擊close按鈕,退出程序。
實驗說明:
1. QtextEdit除了用append()函數顯示圖片外,還可以用insertHtml()函數和setPlainText()來顯示,用法類似,其中insertHtml()可以用來顯示圖片和有格式的文字,而setPlainText()只能用來顯示無格式的文字。
2.為什么TextBrowser下的append()函數2個連在一起使用時,只有當最后一個append函數運行完后才顯示出append的內容呢?
比如說,
ui->textBrowser->append( “first” ); usleep( 1000000 );//延時1s ui->textBrowser->append( “second” ); usleep( 1000000 ); ui->textBrowser->append( “third” );
實際運行到這幾句代碼時,並不是顯示完first,延時1s后顯示second,再延時1s后顯示third. 而是直接延時2秒,first,second,third同時顯示呢?
而把程序改成在終端輸出字符串,用的usleep函數,其結果卻正常,能滿足我們預先設定的了。即改為下面代碼時:
cout<<"first"<<endl; usleep( 1000000 );//延時1s cout<<"second"<<endl; usleep( 1000000 ); count<<"third"<<endl;
其原因在主線程GUI中不宜采用sleep()等函數,否則會出現意想不到的結果。
如果需要延時,#include <QElapsedTimer>后,可以用下面的代碼(比如說延時1s):
QElapsedTimer t; t.start(); while(t.elapsed()<1000) QcoreApplication::processEvents();
3.fillPoly函數的第2個參數是指1個指向Point的雙指針,因為該函數可以同時填充多個多邊形。第3個參數為指向整型的指針,表示每個多邊形中頂點的個數。
實驗結果:
畫atom圖過程之一及其結果:
畫rook圖過程之一及其結果:
實驗主要部分代碼及注釋(附錄有工程code下載鏈接):
#include "mainwindow.h" #include "ui_mainwindow.h" //#include <windows.h> //#include <time.h> #include <iostream> #include <QElapsedTimer> using namespace std; MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); ui->textBrowser->setFixedWidth( W ); ui->textBrowser->setFixedHeight( W ); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_closeButton_clicked() { close(); } void MainWindow::on_drawing1Button_clicked() { /*畫圖1,資料中稱該圖為atom*/ img = Mat::zeros( W, W, CV_8UC3 ); imwrite( "../drawing/drawing.jpg", img ); ui->textBrowser->insertHtml( "<img src =../drawing/drawing.jpg>" ); /*下面幾句為在Qt中常用的延時函數,這里為延時1s,注意主線程中不要采用sleep()等函數 否則會出現意想不到的結果*/ QElapsedTimer t; t.start(); while(t.elapsed()<1000) QCoreApplication::processEvents(); /*畫橢圓1*/ ui->textBrowser->clear(); my_ellipse( img, 0 ); imwrite ( "../drawing/drawing1.jpg", img ); ui->textBrowser->append( "<img src=../drawing/drawing1.jpg>" ); t.start(); while(t.elapsed()<1000) QCoreApplication::processEvents(); /*畫橢圓2*/ ui->textBrowser->clear(); my_ellipse( img ,90 ); imwrite ( "../drawing/drawing2.jpg", img ); ui->textBrowser->append( "<img src=../drawing/drawing2.jpg>" ); t.start(); while(t.elapsed()<1000) QCoreApplication::processEvents(); /*畫橢圓3*/ ui->textBrowser->clear(); my_ellipse( img, 45 ); imwrite ( "../drawing/drawing3.jpg", img ); ui->textBrowser->append( "<img src=../drawing/drawing3.jpg>" ); t.start(); while(t.elapsed()<1000) QCoreApplication::processEvents(); /*畫橢圓4*/ ui->textBrowser->clear(); my_ellipse( img, 135 ); imwrite ( "../drawing/drawing3.jpg", img ); ui->textBrowser->append( "<img src=../drawing/drawing3.jpg>" ); t.start(); while(t.elapsed()<1000) QCoreApplication::processEvents(); /*畫atom的中心實心圓*/ ui->textBrowser->clear(); my_filled_circle( img, Point(W/2, W/2) ); imwrite ( "../drawing/drawing3.jpg", img ); ui->textBrowser->append( "<img src=../drawing/drawing3.jpg>" ); t.start(); while(t.elapsed()<1000) QCoreApplication::processEvents(); } void MainWindow::on_drawing2Button_clicked() { /*畫圖2,資料中稱該圖為rook,其實就是一枚國際像棋子*/ img = Mat::zeros( W, W, CV_8UC3 ); imwrite( "../drawing/drawing.jpg", img ); ui->textBrowser->insertHtml( "<img src =../drawing/drawing.jpg>" ); QElapsedTimer t; t.start(); while(t.elapsed()<1000) QCoreApplication::processEvents(); ui->textBrowser->clear(); my_polygon( img ); imwrite ( "../drawing/drawing2.jpg", img ); ui->textBrowser->append( "<img src=../drawing/drawing2.jpg>" ); t.start(); while(t.elapsed()<1000) QCoreApplication::processEvents(); ui->textBrowser->clear(); rectangle( img, Rect( Point(0, 7*W/8), Point(W, W) ), Scalar(0, 0, 255), -1, 8); imwrite ( "../drawing/drawing2.jpg", img ); ui->textBrowser->append( "<img src=../drawing/drawing2.jpg>" ); t.start(); while(t.elapsed()<1000) QCoreApplication::processEvents();
ui->textBrowser->clear(); my_line( img, Point(0, 15*W/16), Point( W, 15*W/16) ); my_line( img, Point(W/4, W/8), Point(W/4, W) ); my_line( img, Point(W/2, 7*W/8), Point(W/2, W) ); my_line( img, Point(3*W/4, W/8), Point(3*W/4, W) ); imwrite ( "../drawing/drawing2.jpg", img ); ui->textBrowser->append( "<img src=../drawing/drawing2.jpg>" ); t.start(); while(t.elapsed()<1000) QCoreApplication::processEvents(); } void MainWindow::my_ellipse( Mat& img, float angle ) { cv::ellipse( img, Point(W/2, W/2), Size(3*W/8, W/8), angle, 0, 360, Scalar(0, 255, 0), 2, 8 ); } void MainWindow::my_filled_circle( Mat& img, Point center ) { cv::circle( img, center, W/8, Scalar(0, 0, 255), -1, 8 ); } void MainWindow::my_polygon( Mat& img ) { int ncontours = 1; Point rook_points[1][20]; rook_points[0][0] = Point( W/4.0, 7*W/8.0 ); rook_points[0][1] = Point( 3*W/4.0, 7*W/8.0 ); rook_points[0][2] = Point( 3*W/4.0, 13*W/16.0 ); rook_points[0][3] = Point( 11*W/16.0, 13*W/16.0 ); rook_points[0][4] = Point( 19*W/32.0, 3*W/8.0 ); rook_points[0][5] = Point( 3*W/4.0, 3*W/8.0 ); rook_points[0][6] = Point( 3*W/4.0, W/8.0 ); rook_points[0][7] = Point( 26*W/40.0, W/8.0 ); rook_points[0][8] = Point( 26*W/40.0, W/4.0 ); rook_points[0][9] = Point( 22*W/40.0, W/4.0 ); rook_points[0][10] = Point( 22*W/40.0, W/8.0 ); rook_points[0][11] = Point( 18*W/40.0, W/8.0 ); rook_points[0][12] = Point( 18*W/40.0, W/4.0 ); rook_points[0][13] = Point( 14*W/40.0, W/4.0 ); rook_points[0][14] = Point( 14*W/40.0, W/8.0 ); rook_points[0][15] = Point( W/4.0, W/8.0 ); rook_points[0][16] = Point( W/4.0, 3*W/8.0 ); rook_points[0][17] = Point( 13*W/32.0, 3*W/8.0 ); rook_points[0][18] = Point( 5*W/16.0, 13*W/16.0 ); rook_points[0][19] = Point( W/4.0, 13*W/16.0) ; const Point *pts[1] = { rook_points[0] }; // const Point **pts = rook_points;//這樣定義是不行的,因為rook_points是個常量的二階指針 int npts[1] = { 20 }; //用指定顏色填充指定閉合的多邊形。 fillPoly( img, pts, npts, ncontours, Scalar(0, 255, 0), 8 ); } void MainWindow::my_line( Mat& img, Point start, Point end ) { line( img, start, end, Scalar(0, 0, 0), 2, 8 ); }
實驗總結:
本次實驗的主要時間花在了延時函數的使用上,因為不同操作系統的內核不同,所以使用延時函數時需要小心,一開始使用的延時函數usleep(),總出現莫名其妙的現象,后面在論壇上得到了網友的指點說GUI線程中最好不要使用sleep()系列的函數。