Qt+OpenCV2.3.1调用摄像头(OpenCV2.x版本使用介绍)

转载请注明原文地址: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库都装入你的程序中。使用时,你仅需要包含用到的头文件,比如:

#include 
#include 
#include 

所有OpenCV用到的东西都被放入名字空间 cv 中以避免与其他库的数据结构和函数名称的命名冲突。因此,在使用OpenCV库中的任何定义和函数时,你必须在名称之前冠以 cv:: ,或者在包含头文件后,加上以下指令:

using namespace cv;  // 新的C++接口API都在此名字空间中,需要导入。

因为所有库中函数都已在此名字空间中,所以无需加 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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#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()));
}
OpenCV的图像格式是BGR,QImage的则是RGB,所以要进行图像格式转换,否则图像会的颜色会走样,2.x版本里面用cvtColor进行转换,详情见代码:

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文档也行

有什么不足的地方,还请提出来,大家一起进步!


你可能感兴趣的:(OpenCV,Qt)