本文主要讲讲怎样用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"<
其原因在主线程GUI中不宜采用sleep()等函数,否则会出现意想不到的结果。
如果需要延时,#include
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//#include #include #include 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( "" ); /*下面几句为在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( "" ); t.start(); while(t.elapsed()<1000) QCoreApplication::processEvents(); /*画椭圆2*/ ui->textBrowser->clear(); my_ellipse( img ,90 ); imwrite ( "../drawing/drawing2.jpg", img ); ui->textBrowser->append( "" ); t.start(); while(t.elapsed()<1000) QCoreApplication::processEvents(); /*画椭圆3*/ ui->textBrowser->clear(); my_ellipse( img, 45 ); imwrite ( "../drawing/drawing3.jpg", img ); ui->textBrowser->append( "" ); t.start(); while(t.elapsed()<1000) QCoreApplication::processEvents(); /*画椭圆4*/ ui->textBrowser->clear(); my_ellipse( img, 135 ); imwrite ( "../drawing/drawing3.jpg", img ); ui->textBrowser->append( "" ); 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( "" ); 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( "" ); QElapsedTimer t; t.start(); while(t.elapsed()<1000) QCoreApplication::processEvents(); ui->textBrowser->clear(); my_polygon( img ); imwrite ( "../drawing/drawing2.jpg", img ); ui->textBrowser->append( "" ); 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( "" ); 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( "" ); 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()系列的函数。
附:工程code下载。