虚拟机下Ubuntu16.04+Qt5+OpenCV3 简单的笔记本前置摄像头UI界面上打开与关闭的实现
第一次写CSDN博客,还不太熟悉这个编辑器,哪里写得不妥的地方,希望得到大家的指正。
刚刚接触Qt和openCV,希望可以和大家一起学习。
测试摄像头
由于我在完成代码后运行了多次结果都没有画面,对代码的各种修改都没解决问题,然后才才想起来会不会是摄像头没有加载的问题。于是,我打开了cheese(这个ubuntu16.04应该是自带的),如果没有的话也不要紧,可以自行安装。
sudo apt-get install cheese
我打开之后,发现果然是黑屏,虽然摄像头的灯是亮的,就是像这个样子,功能按键都是灰的。
然后我查了一下,发现大家的解决方案大致都是先检查摄像头是否加载成功,再切换USB兼容性
lsusb //查看一下是否有找到摄像头
ls /dev | grep video //查看是否有video0,即默认的前置摄像头
但我发现我的摄像头是加载了的
再切换了usb接口的兼容性(虚拟机->设置->USB控制器->USB兼容性,大概就是3.0和2.0切换吧),也还是没有解决问题。
那就很迷了,为什么就是显示不出来呢。
然后参考这篇博文:https://blog.csdn.net/haoruojing/article/details/60963780
大概是这样解决的:
回到windows,此电脑右键–>管理->服务和应用程序–>服务,启动
启动VMware这几项,我是对VMware USB Arbitration service 重新启动了,然后设备管理器里的camera消失了,不过电脑重启即可。然后再打开虚拟机,打开ubuntu,连接摄像头,我还把USB兼容性改为了3.0,然后再打开cheese,就发现可以看到图像了。
实现代码
参考:https://www.cnblogs.com/annt/p/ant003.html
首先创建一个工程,我创建的是Qt Widgets Application,className是DUQU。
.pro文件
.pro文件里需要加入以下一些OpenCV的库
INCLUDEPATH += /usr/local/include \ #(这部分可能路径不太一样,可以打开文档查找一下)
/usr/local/include/opencv4
LIBS += /usr/local/lib/libopencv_highgui.so \
/usr/local/lib/libopencv_core.so \
/usr/local/lib/libopencv_imgproc.so \
/usr/local/lib/libopencv_imgcodecs.so \
/usr/local/lib/libopencv_videoio.so \
/usr/local/lib/libopencv_shape.so \
/usr/local/lib/libopencv_core.so.4.0
UI界面的实现
进入duqu.ui
放置两个Push Button:Open和Close
(可以把objectName分别改为openButton,closeButton,再把text也该一下)
一个Label:objectName为label
一个Scroll Area(作为放置Label的一个区域)
大致就是如下图所示
然后就是设置槽了,选中Push Button,右键选择 Go to slot,signal选择clicked(),两个Push Button都是这样操作。然后就会看到我们的ducu.cpp文件里相应地生成了两个暂时为空的槽函数:
void DUQU::on_openButton_clicked();
void DUQU::on_closeButton_clicked();
“duqu.h"
#ifndef DUQU_H
#define DUQU_H
#include <QMainWindow>
#include <QTimer>
#include <QPixmap>
#include <QDebug>
#include <QImage>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
namespace Ui {
class DUQU;
}
class DUQU : public QMainWindow
{
Q_OBJECT
public:
explicit DUQU(QWidget *parent = 0); //构造函数
~DUQU(); //析构函数
private slots:
void nextFrame(); //实现定时从摄像头取图并显示在label上的功能
void on_openButton_clicked(); //打开摄像头
void on_closeButton_clicked(); //关闭摄像头
private:
Ui::DUQU *ui;
cv::VideoCapture capture; //一个获取视频的抽象接口结构
cv::Mat frame; //一帧图像
QImage image; //一张图像
QTimer *timer; //定时器用于定时取帧,隔一段时间获取图像。
QImage Mat2QImage(cv::Mat cvImg); //Mat->QImage的转化
};
#endif // DUQU_H
“duqu.cpp”
#include "duqu.h"
#include "ui_duqu.h"
DUQU::DUQU(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::DUQU)
{
ui->setupUi(this);
ui->label->setScaledContents(true);// 图片自适应窗口控件大小
}
DUQU::~DUQU()
{
delete ui;
delete timer;
}
//Mat->QImage
QImage DUQU::Mat2QImage(cv::Mat cvImg)
{
QImage qImg;
cv::cvtColor(cvImg,cvImg,cv::COLOR_BGR2RGB);
qImg=QImage((const unsigned char*)(cvImg.data),
cvImg.cols,cvImg.rows, //宽,高
cvImg.step, //步长
QImage::Format_RGB888); //24位图,RGB=[0,1,2]
//return qImg.rgbSwapped();
return qImg;
}
//打开摄像头
void DUQU::on_openButton_clicked()
{
capture.open(0); //打开默认的摄像头
if (capture.isOpened())
{
capture >> frame; //获取一帧图像
if(frame.empty())
{
qDebug()<<"error!";
}
if(!frame.empty())
{
image = Mat2QImage(frame); //Mat->QImage
ui->label->setPixmap(QPixmap::fromImage(image)); //QImage->QPixmap,并将图像显示在label上
timer = new QTimer(this); //计时器
timer->setInterval(30); //设置间隔:30毫秒
connect(timer,SIGNAL(timeout()),this,SLOT(nextFrame()));
//一旦超时则触发nextFrame(),即显示下一帧图像
//SIGNAL(timeout()):每当计时结束,计时器归零并重新计时,并发送一个信号激活slot函数
timer->start(); //重新开始计时
}
}
}
//显示下一帧图像
void DUQU::nextFrame()
{
capture >> frame; //获取的图像frame是Mat数据矩阵
image = Mat2QImage(frame);//Mat->QImage
ui->label->setPixmap(QPixmap::fromImage(image)); //fromImage(image): QImage->QPixmap
//最后将 QPixmap 将图像显示在label上
}
//关闭摄像头
void DUQU::on_closeButton_clicked()
{
timer->stop(); //停止计时
capture.release(); //关闭摄像头
ui->label->setPixmap(QPixmap()); //释放内存,关闭画面
}
“main.cpp”
#include "duqu.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
DUQU *w=new DUQU;
w->show();
return app.exec();
}
实现效果
这样就完成一个简单的ui界面上的摄像头的打开与关闭了。