转载请注明原文地址:http://blog.csdn.net/huang8579/article/details/8026158
OpenCV2.3.1已经编译完了,上一篇文章中只是简单地介绍一下完全用OpenCV自己图形库实现摄像头调用和图像显示,这篇文章则主要介绍Qt与OpenCV的使用
请注意:
OpenCV 2.x版本和1.x版本有着很大的差别,网上有很多文章讲的都是1.x版本,2.x版本中图像存储容器改为Mat,但是向下兼容以前的容器,库的使用上也有巨大差别
所以以后在使用开源库的时候,首先要去官方网站上查看文档,知道有哪些差别,如果只按照老的文档操作的话, 很容易造成时间上不必要的浪费!!
OpenCV 2.x 文档翻译网站:http://www.opencv.org.cn/opencvdoc/2.3.2/html/index.html
2.X版本的改变
1、新容器
在用新版本之前,你首先需要学习一些新的图像数据结构: Mat - 基本图像容器 ,它取代了旧的 CvMat 和 IplImage.
Mat的基本原理就是矩阵存储,所以在向QImage传递图像数据的大小时,Mat提供了矩阵的行数(Cols)和列数(Rows),用以取代IplImage的宽和高。
2、新的库调用方法
OpenCV 2 接受按需定制。所有函数不再装入一个单一的库中。我们会提供许多模块,每个模块都包含了与其功能相关的数据结构和函数。这样一来,如果你仅仅需要使用OpenCV的一部分功能,你就不需要把整个巨大的OpenCV库都装入你的程序中。使用时,你仅需要包含用到的头文件,比如:
所有OpenCV用到的东西都被放入名字空间 cv 中以避免与其他库的数据结构和函数名称的命名冲突。因此,在使用OpenCV库中的任何定义和函数时,你必须在名称之前冠以 cv:: ,或者在包含头文件后,加上以下指令:
因为所有库中函数都已在此名字空间中,所以无需加 cv 作为前缀。据此所有新的C++兼容函数都无此前缀,并且遵循驼峰命名准则。也就是第一个字母为小写(除非是单个单词作为函数名,如 Canny)并且后续单词首字母大写(如 copyMakeBorder ).
接下来,请记住你需要将所有用到的模块链接到你的程序中。如果你在Windows下开发且用到了 动态链接库(DLL) ,你还需要将OpenCV对应动态链接库的路径加入程序执行路径中。关于Windows下开发的更多信息请阅读 How to build applications with OpenCV inside the Microsoft Visual Studio;对于Linux用户,可参考 Using OpenCV with Eclipse (plugin CDT) 中的实例及说明。
Qt中使用OpenCV库新建QWidget工程,ui,main.cpp全都默认
头文件的实现,上面已经介绍,直接代码:
- #ifndef WIDGET_H
- #define WIDGET_H
- #include <QWidget>
- #include <QPainter>
- #include <QImage>
- #include <QTimer>
- #include <opencv2/highgui/highgui.hpp>
- #include <opencv2/core/core.hpp>
- #include <opencv2/video/video.hpp>
- #include <opencv2/imgproc/imgproc.hpp>
- #define FPS 33
- using namespace cv;
- namespace Ui {
- class Widget;
- }
- class Widget : public QWidget
- {
- Q_OBJECT
- public:
- explicit Widget(QWidget *parent = 0);
- void paintEvent(QPaintEvent *);
- ~Widget();
- private:
- Ui::Widget *ui;
- VideoCapture V;
- QTimer timer;
- Mat im;
- private slots:
- void showImage();
- };
- #endif // WIDGET_H
定时器的使用,不介绍了,相信看代码能看懂, 讲一下VideoCapture,这个比以前的cvCreateCamera方便许多,不需要在把每一帧图像存到队列里以后再传给容器了,可以直接用 V >> im来实现,打开摄像头方式和以前相同
- //数字代表设备号,就是调用哪个摄像头
- VideoCapture V(0);
- //指针方式
- V = new VideoCapture(0);
- //判断是否成功打开摄像头
- V.isOpened()
- Widget::Widget(QWidget *parent) :
- QWidget(parent),
- ui(new Ui::Widget)
- {
- ui->setupUi(this);
- V.open(0);
- //设定摄像头采集图像的宽、高,可以不设置,采用原始图像
- V.set(CV_CAP_PROP_FRAME_WIDTH,);
- V.set(CV_CAP_PROP_FRAME_HEIGHT,450);
- //开启定时器
- timer.start(FPS);
- //img = new QImage((unsigned char*)im.data,im.cols,im.rows,QImage::Format_RGB888);
- connect(&timer,SIGNAL(timeout()),this,SLOT(showImage()));
- }
- void Widget::showImage()
- {
- V >> im;
- //图像格式转换
- cvtColor(im,im,CV_BGR2RGB);
- update();
- }
最后在QWidget上用QPainter进行绘图,Qt有很多可绘图控件,比如Qlabel、QWidget等,这些控件自身带有绘图事件的触发,通过调用控件的update(),可以触发绘图事件,对控件进行重新绘图,用这种控件自身的绘图功能效率上远远高于其他额外的绘图方式
注意QImage接收Mat图像数据时传递的参数类型
绘图部分代码:
- void Widget::paintEvent(QPaintEvent *)
- {
- QImage img((unsigned char*)im.data,im.cols,im.rows,QImage::Format_RGB888);
- QPainter painter(this);
- painter.drawImage(-1,-1,img);
- }
关于QPainter的内容,大家自己在网上找吧,很多了,我就不介绍了,直接看Qt文档也行
有什么不足的地方,还请提出来,大家一起进步!