安装Qt 中 OpenCV的设置
win32-msvc*{
INCLUDEPATH += $${OPENCVPATH_MSVC}/include
CONFIG(debug, debug|release) {
LIBS+=-L$${OPENCVPATH_MSVC}/lib/debug \
-lcxcore210d \
-lhighgui210d
} else {
LIBS += -L$${OPENCVPATH_MSVC}/lib/release \
-lcxcore210 \
-lhighgui210
}
}
OPENCVPATH_MINGW = D:/Qt/OpenCV-2.1.0-mingw
win32-g++{
INCLUDEPATH += $${OPENCVPATH_MINGW}/include
LIBS += -L$${OPENCVPATH_MINGW}/lib \
-lcxcore210 \
-lhighgui210
}
unix:LIBS += -lcv \
-lhighgui读取类
#ifndef CAMERADEVICE_H
#define CAMERADEVICE_H
#include <QtCore/QObject>
QT_BEGIN_NAMESPACE
class QTimer;
class QImage;
QT_END_NAMESPACE
namespace cv{
class VideoCapture;
class Mat;
}
class CameraDevice : public QObject
{
Q_OBJECT
public:
explicit CameraDevice(QObject *parent = 0);
~CameraDevice();
signals:
void imageReady(const QImage& image);
public slots:
bool start();
bool stop();
private slots:
void onTimeout();
private:
QImage imageFromMat(const cv::Mat& frame);
cv::VideoCapture * m_capture;
QTimer * m_timer;
};
#endif // CAMERADEVICE_H//cameradevice.cpp
#include <QtCore/QTimer>
#include <QtGui/QImage>
#include "opencv/cv.h"
#include "opencv/highgui.h"
#include "cameradevice.h"
CameraDevice::CameraDevice(QObject *parent) :
QObject(parent)
{
m_capture = new cv::VideoCapture;
m_timer = new QTimer(this);
connect(m_timer, SIGNAL(timeout()), this, SLOT(onTimeout()));
}
CameraDevice::~CameraDevice()
{
delete m_capture;
m_capture = NULL;
}
bool CameraDevice::start()
{
if (m_capture->isOpened()) {
return true;
}
m_capture->open(CV_CAP_ANY);
if (m_capture->isOpened()) {
m_timer->start(40);
}
return m_capture->isOpened();
}
bool CameraDevice::stop()
{
if (m_capture->isOpened()) {
m_capture->release();
}
return true;
}
void CameraDevice::onTimeout()
{
if (!m_capture->isOpened()) {
return;
}
static cv::Mat frame;
*m_capture >> frame;
if (frame.cols) {
emit imageReady(imageFromMat(frame));
}
}
QImage CameraDevice::imageFromMat(const cv::Mat &frame)
{
const unsigned char* src = frame.ptr();
QImage image(frame.cols, frame.rows, QImage::Format_RGB32);
unsigned char * des = image.bits();
unsigned long count = frame.cols * frame.rows;
for (unsigned long i = 0; i < count; ++i)
{
*des++ = *src++;
*des++ = *src++;
*des++ = *src++;
*des++ = 0xff;
}
return image;
}界面类
#ifndef DIALOG_H
#define DIALOG_H
#include <QtGui/QDialog>
namespace Ui {
class Dialog;
}
class CameraDevice;
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
private slots:
void onImageArrival(const QImage & image);
private:
Ui::Dialog *ui;
CameraDevice * m_camera;
};
#endif // DIALOG_H
//dialog.cpp
#include "dialog.h"
#include "ui_dialog.h"
#include "cameradevice.h"
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog),
m_camera(new CameraDevice(this))
{
ui->setupUi(this);
connect(m_camera, SIGNAL(imageReady(QImage)), this, SLOT(onImageArrival(QImage)));
connect(ui->startButton, SIGNAL(clicked()), m_camera, SLOT(start()));
connect(ui->stopButton, SIGNAL(clicked()), m_camera, SLOT(stop()));
}
Dialog::~Dialog()
{
delete ui;
}
void Dialog::onImageArrival(const QImage &image)
{
ui->view->setPixmap(QPixmap::fromImage(image));
}主程序//main.cpp
#include <QtGui/QApplication>
#include "dialog.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Dialog w;
w.show();
return a.exec();
}问题
#include "dialog.h"
#include "ui_dialog.h"
#include "cameradevice.h"
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog),
m_camera(new CameraDevice)
{
ui->setupUi(this);
QThread * thread = new QThread(this);
m_camera->moveToThread(thread);
thread->start();
connect(m_camera, SIGNAL(imageReady(QImage)), this, SLOT(onImageArrival(QImage)));
connect(ui->startButton, SIGNAL(clicked()), m_camera, SLOT(start()));
connect(ui->stopButton, SIGNAL(clicked()), m_camera, SLOT(stop()));
}
Dialog::~Dialog()
{
m_camera->deleteLater();
delete ui;
}
void Dialog::onImageArrival(const QImage &image)
{
ui->view->setPixmap(QPixmap::fromImage(image));
}
为了pro工程文件看起来简单点,创建一个 pri 文件,包含 opencv相关信息。
分别为 VS2008、Mingw和Linux设置OpenCV头文件和库的路径。
OPENCVPATH_MSVC = D:/Qt/OpenCV-2.1.0-vs2008win32-msvc*{
INCLUDEPATH += $${OPENCVPATH_MSVC}/include
CONFIG(debug, debug|release) {
LIBS+=-L$${OPENCVPATH_MSVC}/lib/debug \
-lcxcore210d \
-lhighgui210d
} else {
LIBS += -L$${OPENCVPATH_MSVC}/lib/release \
-lcxcore210 \
-lhighgui210
}
}
OPENCVPATH_MINGW = D:/Qt/OpenCV-2.1.0-mingw
win32-g++{
INCLUDEPATH += $${OPENCVPATH_MINGW}/include
LIBS += -L$${OPENCVPATH_MINGW}/lib \
-lcxcore210 \
-lhighgui210
}
unix:LIBS += -lcv \
-lhighgui读取类
创建一个视频捕捉类,提供start和stop槽来控制摄像头打开和关闭,通过定时器定时捕捉图像,并通过信号将图片传出。
//cameradevice.h#ifndef CAMERADEVICE_H
#define CAMERADEVICE_H
#include <QtCore/QObject>
QT_BEGIN_NAMESPACE
class QTimer;
class QImage;
QT_END_NAMESPACE
namespace cv{
class VideoCapture;
class Mat;
}
class CameraDevice : public QObject
{
Q_OBJECT
public:
explicit CameraDevice(QObject *parent = 0);
~CameraDevice();
signals:
void imageReady(const QImage& image);
public slots:
bool start();
bool stop();
private slots:
void onTimeout();
private:
QImage imageFromMat(const cv::Mat& frame);
cv::VideoCapture * m_capture;
QTimer * m_timer;
};
#endif // CAMERADEVICE_H//cameradevice.cpp
#include <QtCore/QTimer>
#include <QtGui/QImage>
#include "opencv/cv.h"
#include "opencv/highgui.h"
#include "cameradevice.h"
CameraDevice::CameraDevice(QObject *parent) :
QObject(parent)
{
m_capture = new cv::VideoCapture;
m_timer = new QTimer(this);
connect(m_timer, SIGNAL(timeout()), this, SLOT(onTimeout()));
}
CameraDevice::~CameraDevice()
{
delete m_capture;
m_capture = NULL;
}
bool CameraDevice::start()
{
if (m_capture->isOpened()) {
return true;
}
m_capture->open(CV_CAP_ANY);
if (m_capture->isOpened()) {
m_timer->start(40);
}
return m_capture->isOpened();
}
bool CameraDevice::stop()
{
if (m_capture->isOpened()) {
m_capture->release();
}
return true;
}
void CameraDevice::onTimeout()
{
if (!m_capture->isOpened()) {
return;
}
static cv::Mat frame;
*m_capture >> frame;
if (frame.cols) {
emit imageReady(imageFromMat(frame));
}
}
QImage CameraDevice::imageFromMat(const cv::Mat &frame)
{
const unsigned char* src = frame.ptr();
QImage image(frame.cols, frame.rows, QImage::Format_RGB32);
unsigned char * des = image.bits();
unsigned long count = frame.cols * frame.rows;
for (unsigned long i = 0; i < count; ++i)
{
*des++ = *src++;
*des++ = *src++;
*des++ = *src++;
*des++ = 0xff;
}
return image;
}界面类
对话框类就简单了,只需要一个 label 来显示图像,两个按钮来控制开启与关闭即可
//dialog.h#ifndef DIALOG_H
#define DIALOG_H
#include <QtGui/QDialog>
namespace Ui {
class Dialog;
}
class CameraDevice;
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
private slots:
void onImageArrival(const QImage & image);
private:
Ui::Dialog *ui;
CameraDevice * m_camera;
};
#endif // DIALOG_H
//dialog.cpp
#include "dialog.h"
#include "ui_dialog.h"
#include "cameradevice.h"
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog),
m_camera(new CameraDevice(this))
{
ui->setupUi(this);
connect(m_camera, SIGNAL(imageReady(QImage)), this, SLOT(onImageArrival(QImage)));
connect(ui->startButton, SIGNAL(clicked()), m_camera, SLOT(start()));
connect(ui->stopButton, SIGNAL(clicked()), m_camera, SLOT(stop()));
}
Dialog::~Dialog()
{
delete ui;
}
void Dialog::onImageArrival(const QImage &image)
{
ui->view->setPixmap(QPixmap::fromImage(image));
}主程序//main.cpp
#include <QtGui/QApplication>
#include "dialog.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Dialog w;
w.show();
return a.exec();
}问题
用一个定时器来做似乎存在些问题,反复打开关闭,在windows下可发现资源泄漏。不清楚是什么原因。
简单调整几行代码,改为多线程程序后,该问题似乎消失了。
- 改动主要在对话框类中:
#include "dialog.h"
#include "ui_dialog.h"
#include "cameradevice.h"
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog),
m_camera(new CameraDevice)
{
ui->setupUi(this);
QThread * thread = new QThread(this);
m_camera->moveToThread(thread);
thread->start();
connect(m_camera, SIGNAL(imageReady(QImage)), this, SLOT(onImageArrival(QImage)));
connect(ui->startButton, SIGNAL(clicked()), m_camera, SLOT(start()));
connect(ui->stopButton, SIGNAL(clicked()), m_camera, SLOT(stop()));
}
Dialog::~Dialog()
{
m_camera->deleteLater();
delete ui;
}
void Dialog::onImageArrival(const QImage &image)
{
ui->view->setPixmap(QPixmap::fromImage(image));
}
改为多线程后,可将捕捉类中的定时器的时间设为 0