本帖最后由 正点原子运营 于 2022-8-26 16:29 编辑
第十九章 Camera
此章节例程适用于Ubuntu和正点原子I.MX6U开发板,不适用于Windows(需要自行修改才能适用Windows,Windows上的应用不在我们讨论范围)! 19.1 资源简介正点原子I.MX6U开发板底板上有一路“CSI”摄像头接口。支持正点原子的OV5640、OV2640和OV7725(不带FIFO)。同时有USB接口,可以接USB免驱摄像头。例程兼容USB摄像头与正点原子的OV5640、OV2640和OV7725摄像头。 出厂系统请更新到正点原子I.MX6U最新的出厂系统,在驱动层正点原子对OV5640、OV2640和OV7725摄像头维护、优化或者添加支持。 19.2 环境搭建Qt里也有一个QCamera类。没错,确实可以使用这个QCamera类来开发摄像头。但是这个类在正点原子的I.MX6U开发板4.1.15内核版本上不能使用OV5640、OV2640和OV7725,可以使用USB免驱摄像头。因为OV5640、OV2640和OV7725的驱动默认是读取YUYV格式数据,而QCamera里读取的数据是RGB格式数据,它们可能数据对不上就无法使用了!但是也不建议修改驱动的方法来使用QCamera,防止QCamera在某些方法上与驱动层不对应,导致使用报错。 实际上我们使用V4l2编程就可以对摄像头进行编程,效果会比在Qt显示流畅,因为V4l2的数据直接可以显示在fb0(也就是屏上)。而经过Qt还需要在控件上处理,所以效率会慢一些!在正点原子I.MX6U开发板上或者说是嵌入式上,比较低性能的CPU对于处理图像等大数据还是比较吃力的。所以我们需要去优化,不同的编程方式,对数据的处理不同,写出来的效果也会不同! 下面主要介绍Qt + OpenCV调用摄像头,效果肯定不能与使用V4l2直接显示在fb0上相比。在这个开发板的CPU上显示效果还是比较好的,还能接受,流畅度一般。 要想在Ubuntu上使用OpenCV,那么我们的Ubuntu上必须有OpenCV的库,如果您不想在Ubuntu安装OpenCV,就可以跳过这小节,直接用出厂系统提供的交叉编译工具链,里面已经提供有OpenCV。在Ubuntu上安装OpenCV只是方便我们测试界面,编写的程序也可以在Ubuntu上运行。安装的步骤也比较简单。 正点原子I.MX6U出厂系统的OpenCV版本为3.1.0。也不一定非要与正点原子I.MX6U出厂系统里的OpenCV相同版本,我们只是在Ubuntu上运行OpenCV。其中用到的API在3.1.0版本与3.4.1版本基本没有什么区别。3.1.0版本的OpenCV与3.4.1版本的OpenCV绝大多数核心API都相同,不必要担心找不到相同的API。 这里编者选择安装到OpenCV版本为3.4.1版本,因为3.1.0版本在配置cmake时下载的第三方库因为网络的原因难下载,导致cmake配置不过去。(PS:如果不是因为编译不过去,编者会选择与开发板相同的版本的OpenCV的)。 右键选择复制下载链接,用迅雷下载会比较快。下载完成后我们拷贝下载的文件到Ubuntu上进行解压。或者直接在正点原子的I.MX6U的光盘资料路径下找到开发板光盘A-基础资料/1、例程源码/7、第三方库源码/opencv-3.4.1.tar.gz。然后拷贝到Ubuntu下。 如下图我们已经下载好文件,并拷贝下载好的文件到Ubuntu的家目录下。 执行下面的指令进行解压。解压将会得到一个opencv-3.4.1文件夹,我们使用cd指令进入此文件夹。 - tar xf opencv-3.4.1.tar.gz
- cd opencv-3.4.1
复制代码
安装cmake,用于生成编译OpenCV所需要的文件。 - sudo apt-get install cmake
复制代码新建一个build目录,并进入,用于编译生成的文件。
执行cmake配置编译。注意下面的指令“..”不要漏了!这里表示上一层目录。cmake会从上一层目录下找配置项,并配置到当前目录。 在配置的过程中cmake会下载一些库,如 ippicv_2017u3_lnx_intel64_general_20170822.tgz,需要一段时间,请等待,如果不能下载成功请重复尝试。 cmake配置成功如下图。 执行make开始编译。输入下面的指令。 - make -j 16 // 以实际分配给虚拟机的核心数为准,最佳为分配给虚拟机核心数据的2倍。编者的虚拟机最大分配了16个核心,编者个人的电脑并不快,就是核心多,所以编译就快。编译完成耗时约5分钟。不要只输入make,否则将编译很久!需要加参数 -j n,n请根据个人虚拟机的实际情况。
复制代码
执行下面的指令安装,安装到系统目录,需要加sudo权限。
安装完成如下。可以看到库被安装到/usr/local/lib下,头文件被安装在/usr/local/include下。 我们只需要知道安装的库路径和头文件路径即可在Qt里调用Ubuntu安装的OpenCV。头文件作用来编写程序,库路径用来运行程序时调用。我们只要在Qt的pro项目文件里指定这两个路径即可。
19.3 应用实例请根据【正点原子】I.MX6U 出厂系统Qt交叉编译环境搭建V1.x.pdf(x >= 6)的文档搭建好I.MX6U的交叉编译环境。交叉编译工具链里已经有OpenCV,所以我们只要在我们搭建的交叉环境下就可以调用OpenCV的相关API进行编写Qt项目了。 项目简介:Qt加OpenCV打开摄像头采集图像并拍照。 例05_opencv_camera,Qt Camera编程(难度:较难)。项目路径为Qt/3/05_opencv_camera。 用脚本打开Qt Creator,必须按出厂系统Qt交叉编译环境搭建V1.x.pdf(x >= 6)的文档搭建好交叉编译环境,用脚本启动时,脚本有相应的环境变量,编译时会用到。 - /opt/Qt5.12.9/Tools/QtCreator/bin/qtcreator.sh &
复制代码 编写程序应使用我们搭建的ATK-I.MX6U套件编写,否则若选择了Desktop Qt 5.12.9 GCC 64bit,如果我们的Ubuntu没有安装OpenCV就会使用不了OpenCV。如果您在19.2小节已经安装过OpenCV,那么下面两个套件都可一起选。本次编者两个一起选,因为编者有USB摄像头可以在Ubutnu上使用OpenCV测试,编写的程序交叉编译后在I.MX6U开发板使用USB免驱摄像头或者正点原子OV5640/OV7725(不带FIFO款)/OV2640测试成功!
下面开始编写程序。首先我们需要在项目pro文件添加OpenCV库的支持及头文件路径。 05_opencv_camera.pro文件如下,添加以下内容,这里主要是判断交叉编译器的类型,然后链接到不同的头文件路径与库。 - 1 QT += core gui
- 2
- 3 greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
- 4
- 5 CONFIG += c++11
- 6
- 7 # The following define makes your compiler emit warnings if you use
- 8 # any Qt feature that has been marked deprecated (the exact warnings
- 9 # depend on your compiler). Please consult the documentation of the
- 10 # deprecated API in order to know how to port your code away from it.
- 11 DEFINES += QT_DEPRECATED_WARNINGS
- 12
- 13 # You can also make your code fail to compile if it uses deprecated APIs.
- 14 # In order to do so, uncomment the following line.
- 15 # You can also select to disable deprecated APIs only up to a certain version of Qt.
- 16 #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
- 17
- 18 TARGET_ARCH = ${QT_ARCH}
- 19 contains(TARGET_ARCH, arm){
- 20 CONFIG += link_pkgconfig
- 21 PKGCONFIG += opencv
- 22 INCLUDEPATH += /opt/fsl-imx-x11/4.1.15-2.1.0/sysroots/cortexa7hf-neon-poky-linux-gnueabi/usr/include
- 23 } else {
- 24 LIBS += -L/usr/local/lib \
- 25 -lopencv_core \
- 26 -lopencv_highgui \
- 27 -lopencv_imgproc \
- 28 -lopencv_videoio \
- 29 -lopencv_imgcodecs
- 30
- 31 #INCLUDEPATH可写可不写,系统会到找到此路径
- 32 INCLUDEPATH += /usr/local/include
- 33 }
- 34
- 35 SOURCES += \
- 36 camera.cpp \
- 37 main.cpp \
- 38 mainwindow.cpp
- 39
- 40 HEADERS += \
- 41 camera.h \
- 42 mainwindow.h
- 43
- 44 # Default rules for deployment.
- 45 qnx: target.path = /tmp/${TARGET}/bin
- 46 else: unix:!android: target.path = /opt/${TARGET}/bin
- 47 !isEmpty(target.path): INSTALLS += target
复制代码第18行,获取编译器的类型。 第19行,判断交叉编译器的类型是否为arm。 第22行,arm对应opencv的头文件路径,可以不写,编译不会报错,但是我们想查看对应的头文件,就不得不包括这个路径了,否则跳转不过去! 第24~32行,添加库的支持。-L后面指的是库文件路径,-l后面的是相关库参数(l是大字母“L”的小写字母“l”,不是一),如果不会写库的名称,可以参考Ubuntu的OpenCV安装路径下的/usr/local/lib/pkgconfig/opencv.pc文件。 camera.h文件,此文件声明了一个Camera类,其内容如下,比较简单。 - 9 #ifndef CAMERA_H
- 10 #define CAMERA_H
- 11
- 12 #include <QImage>
- 13 #include <QTimer>
- 14 /* 使用命名空间cv下的VideoCapture与Mat类 */
- 15 namespace cv {
- 16 class VideoCapture;
- 17 class Mat;
- 18 }
- 19
- 20 class Camera : public QObject
- 21 {
- 22 Q_OBJECT
- 23 public:
- 24 explicit Camera(QObject *parent = nullptr);
- 25 ~Camera();
- 26
- 27 signals:
- 28 /* 声明信号,用于传递有图片信号时显示图像 */
- 29 void readyImage(const QImage&);
- 30
- 31 public slots:
- 32 /* 用于开启定时器 */
- 33 bool cameraProcess(bool);
- 34
- 35 /* 选择摄像头 */
- 36 void selectCameraDevice(int);
- 37
- 38 private slots:
- 39 /* 定时器时间到处理函数,发送图像数据信号 */
- 40 void timerTimeOut();
- 41
- 42 private:
- 43 /* 声明OpenCV的cv命名空间下的VideoCapture对象 */
- 44 cv::VideoCapture * capture;
- 45
- 46 /* 定时器 */
- 47 QTimer * timer;
- 48
- 49 /* 图像转换处理函数 */
- 50 QImage matToQImage(const cv::Mat&);
- 51 };
- 52
- 53 #endif // CAMERA_H
- 54
复制代码camera.cpp类的定义如下。 - 9 #include "camera.h"
- 10 #include "opencv2/core/core.hpp"
- 11 #include "opencv2/highgui/highgui.hpp"
- 12 #include <QImage>
- 13 #include <QDebug>
- 14
- 15 Camera::Camera(QObject *parent) :
- 16 QObject(parent)
- 17 {
- 18 /* 实例化 */
- 19 capture = new cv::VideoCapture();
- 20 timer = new QTimer(this);
- 21
- 22 /* 信号槽连接 */
- 23 connect(timer, SIGNAL(timeout()), this, SLOT(timerTimeOut()));
- 24 }
- 25
- 26 Camera::~Camera()
- 27 {
- 28 delete capture;
- 29 capture = NULL;
- 30 }
- 31
- 32 void Camera::selectCameraDevice(int index)
- 33 {
- 34 /* 如果有其他摄像头打开了,先释放 */
- 35 if (capture->isOpened()) {
- 36 capture->release();
- 37 }
- 38
- 39 /* 打开摄像头设备 */
- 40 capture->open(index);
- 41 }
- 42
- 43 bool Camera::cameraProcess(bool bl)
- 44 {
- 45 if (bl) {
- 46 /* 为什么是33?1000/33约等于30帧,也就是一秒最多显示30帧 */
- 47 timer->start(33);
- 48 } else {
- 49 timer->stop();
- 50 }
- 51 /* 返回摄像头的状态 */
- 52 return capture->isOpened();
- 53 }
- 54
- 55 void Camera::timerTimeOut()
- 56 {
- 57 /* 如果摄像头没有打开,停止定时器,返回 */
- 58 if (!capture->isOpened()) {
- 59 timer->stop();
- 60 return;
- 61 }
- 62
- 63 static cv::Mat frame;
- 64 *capture >> frame;
- 65 if (frame.cols)
- 66 /* 发送图片信号 */
- 67 emit readyImage(matToQImage(frame));
- 68 }
- 69
- 70 QImage Camera::matToQImage(const cv::Mat &img)
- 71 {
- 72 /* USB摄像头和OV5640等都是RGB三通道,不考虑单/四通道摄像头 */
- 73 if(img.type() == CV_8UC3) {
- 74 /* 得到图像的的首地址 */
- 75 const uchar *pimg = (const uchar*)img.data;
- 76
- 77 /* 以img构造图片 */
- 78 QImage qImage(pimg, img.cols, img.rows, img.step,
- 79 QImage::Format_RGB888);
- 80
- 81 /* 在不改变实际图像数据的条件下,交换红蓝通道 */
- 82 return qImage.rgbSwapped();
- 83 }
- 84
- 85 /* 返回QImage */
- 86 return QImage();
- 87 }
复制代码 mainwindow.h头文件代码如下。 - /******************************************************************
- Copyright © Deng Zhimao Co., Ltd. 1990-2021. All rights reserved.
- * @projectName 05_opencv_camera
- * @brief mainwindow.h
- * [url=home.php?mod=space&uid=90321]@Author[/url] Deng Zhimao
- * [url=home.php?mod=space&uid=55957]@EMAIL[/url] 1252699831@qq.com
- * [url=home.php?mod=space&uid=28414]@net[/url] www.openedv.com
- * @date 2021-03-17
- *******************************************************************/
- 1 #ifndef MAINWINDOW_H
- 2 #define MAINWINDOW_H
- 3
- 4 #include <QMainWindow>
- 5 #include <QVBoxLayout>
- 6 #include <QHBoxLayout>
- 7 #include <QComboBox>
- 8 #include <QPushButton>
- 9 #include <QVBoxLayout>
- 10 #include <QLabel>
- 11 #include <QScrollArea>
- 12 #include <QDebug>
- 13
- 14 class Camera;
- 15
- 16 class MainWindow : public QMainWindow
- 17 {
- 18 Q_OBJECT
- 19
- 20 public:
- 21 MainWindow(QWidget *parent = nullptr);
- 22 ~MainWindow();
- 23
- 24 private:
- 25 /* 主容器,Widget也可以当作一种容器 */
- 26 QWidget *mainWidget;
- 27
- 28 /* 滚动区域,方便开发高分辨率 */
- 29 QScrollArea *scrollArea;
- 30
- 31 /* 将采集到的图像使用Widget显示 */
- 32 QLabel *displayLabel;
- 33
- 34 /* 界面右侧区域布局 */
- 35 QHBoxLayout *hboxLayout;
- 36
- 37 /* 界面右侧区域布局 */
- 38 QVBoxLayout *vboxLayout;
- 39
- 40 /* 界面右侧区域容器 */
- 41 QWidget *rightWidget;
- 42
- 43 /* 界面右侧区域显示拍照的图片 */
- 44 QLabel *photoLabel;
- 45
- 46 /* 界面右侧区域摄像头设备下拉选择框 */
- 47 QComboBox *comboBox;
- 48
- 49 /* 两个按钮,一个为拍照按钮,另一个是开启摄像头按钮 */
- 50 QPushButton *pushButton[2];
- 51
- 52 /* 拍照保存的照片 */
- 53 QImage saveImage;
- 54
- 55 /* 摄像头设备 */
- 56 Camera *camera;
- 57
- 58 /* 布局初始化 */
- 59 void layoutInit();
- 60
- 61 /* 扫描是否存在摄像头 */
- 62 void scanCameraDevice();
- 63
- 64 private slots:
- 65 /* 显示图像 */
- 66 void showImage(const QImage&);
- 67
- 68 /* 设置按钮文本 */
- 69 void setButtonText(bool);
- 70
- 71 /* 保存照片到本地 */
- 72 void saveImageToLocal();
- 73 };
- 74 #endif // MAINWINDOW_H
复制代码 mainwindow.cpp源文件代码如下。
- /******************************************************************
- Copyright © Deng Zhimao Co., Ltd. 1990-2021. All rights reserved.
- * @projectName 05_opencv_camera
- * @brief mainwindow.cpp
- * @author Deng Zhimao
- * @email 1252699831@qq.com
- * @net www.openedv.com
- * @date 2021-03-17
- *******************************************************************/
- 1 #include "mainwindow.h"
- 2 #include <QGuiApplication>
- 3 #include <QScreen>
- 4 #include <QFile>
- 5 #include <QPixmap>
- 6 #include <QBuffer>
- 7 #include "camera.h"
- 8
- 9 MainWindow::MainWindow(QWidget *parent)
- 10 : QMainWindow(parent)
- 11 {
- 12 /* 布局初始化 */
- 13 layoutInit();
- 14
- 15 /* 扫描摄像头 */
- 16 scanCameraDevice();
- 17 }
- 18
- 19 MainWindow::~MainWindow()
- 20 {
- 21 }
- 22
- 23 void MainWindow::layoutInit()
- 24 {
- 25 /* 获取屏幕的分辨率,Qt官方建议使用这
- 26 * 种方法获取屏幕分辨率,防上多屏设备导致对应不上
- 27 * 注意,这是获取整个桌面系统的分辨率
- 28 */
- 29 QList <QScreen *> list_screen = QGuiApplication::screens();
- 30
- 31 /* 如果是ARM平台,直接设置大小为屏幕的大小 */
- 32 #if __arm__
- 33 /* 重设大小 */
- 34 this->resize(list_screen.at(0)->geometry().width(),
- 35 list_screen.at(0)->geometry().height());
- 36 #else
- 37 /* 否则则设置主窗体大小为800x480 */
- 38 this->resize(800, 480);
- 39 #endif
- 40
- 41 /* 实例化与布局,常规操作 */
- 42 mainWidget = new QWidget();
- 43 photoLabel = new QLabel();
- 44 rightWidget = new QWidget();
- 45 comboBox = new QComboBox();
- 46 pushButton[0] = new QPushButton();
- 47 pushButton[1] = new QPushButton();
- 48 scrollArea = new QScrollArea();
- 49 displayLabel = new QLabel(scrollArea);
- 50 vboxLayout = new QVBoxLayout();
- 51 hboxLayout = new QHBoxLayout();
- 52
- 53 vboxLayout->addWidget(photoLabel);
- 54 vboxLayout->addWidget(comboBox);
- 55 vboxLayout->addWidget(pushButton[0]);
- 56 vboxLayout->addWidget(pushButton[1]);
- 57
- 58 rightWidget->setLayout(vboxLayout);
- 59
- 60 hboxLayout->addWidget(scrollArea);
- 61 hboxLayout->addWidget(rightWidget);
- 62 mainWidget->setLayout(hboxLayout);
- 63
- 64 this->setCentralWidget(mainWidget);
- 65
- 66 pushButton[0]->setMaximumHeight(40);
- 67 pushButton[0]->setMaximumWidth(200);
- 68
- 69 pushButton[1]->setMaximumHeight(40);
- 70 pushButton[1]->setMaximumWidth(200);
- 71
- 72 comboBox->setMaximumHeight(40);
- 73 comboBox->setMaximumWidth(200);
- 74 photoLabel->setMaximumSize(100, 75);
- 75 scrollArea->setMinimumWidth(this->width()
- 76 - comboBox->width());
- 77
- 78 /* 显示图像最大画面为xx */
- 79 displayLabel->setMinimumWidth(scrollArea->width() * 0.75);
- 80 displayLabel->setMinimumHeight(scrollArea->height() * 0.75);
- 81 scrollArea->setWidget(displayLabel);
- 82
- 83 /* 居中显示 */
- 84 scrollArea->setAlignment(Qt::AlignCenter);
- 85
- 86 /* 自动拉伸 */
- 87 photoLabel->setScaledContents(true);
- 88 displayLabel->setScaledContents(true);
- 89
- 90 /* 设置一些属性 */
- 91 pushButton[0]->setText("拍照");
- 92 pushButton[0]->setEnabled(false);
- 93 pushButton[1]->setText("开始");
- 94 pushButton[1]->setCheckable(true);
- 95
- 96 /* 摄像头 */
- 97 camera = new Camera(this);
- 98
- 99 /* 信号连接槽 */
- 100 connect(camera, SIGNAL(readyImage(QImage)),
- 101 this, SLOT(showImage(QImage)));
- 102 connect(pushButton[1], SIGNAL(clicked(bool)),
- 103 camera, SLOT(cameraProcess(bool)));
- 104 connect(pushButton[1], SIGNAL(clicked(bool)),
- 105 this, SLOT(setButtonText(bool)));
- 106 connect(pushButton[0], SIGNAL(clicked()),
- 107 this, SLOT(saveImageToLocal()));
- 108
- 109 }
- 110
- 111 void MainWindow::scanCameraDevice()
- 112 {
- 113 /* 如果是Windows系统,一般是摄像头0 */
- 114 #if win32
- 115 comboBox->addItem("windows摄像头0");
- 116 connect(comboBox,
- 117 SIGNAL(currentIndexChanged(int)),
- 118 camera, SLOT(selectCameraDevice(int)));
- 119 #else
- 120 /* QFile文件指向/dev/video0 */
- 121 QFile file("/dev/video0");
- 122
- 123 /* 如果文件存在 */
- 124 if (file.exists())
- 125 comboBox->addItem("video0");
- 126 else {
- 127 displayLabel->setText("无摄像头设备");
- 128 return;
- 129 }
- 130
- 131 file.setFileName("/dev/video1");
- 132
- 133 if (file.exists()) {
- 134 comboBox->addItem("video1");
- 135 /* 开发板ov5640等设备是1 */
- 136 comboBox->setCurrentIndex(1);
- 137 }
- 138
- 139 file.setFileName("/dev/video2");
- 140
- 141 if (file.exists())
- 142 /* 开发板USB摄像头设备是2 */
- 143 comboBox->addItem("video2");
- 144
- 145 #if !__arm__
- 146 /* ubuntu的USB摄像头一般是0 */
- 147 comboBox->setCurrentIndex(0);
- 148 #endif
- 149
- 150 connect(comboBox,
- 151 SIGNAL(currentIndexChanged(int)),
- 152 camera, SLOT(selectCameraDevice(int)));
- 153 #endif
- 154 }
- 155
- 156 void MainWindow::showImage(const QImage &image)
- 157 {
- 158 /* 显示图像 */
- 159 displayLabel->setPixmap(QPixmap::fromImage(image));
- 160 saveImage = image;
- 161
- 162 /* 判断图像是否为空,空则设置拍照按钮不可用 */
- 163 if (!saveImage.isNull())
- 164 pushButton[0]->setEnabled(true);
- 165 else
- 166 pushButton[0]->setEnabled(false);
- 167 }
- 168
- 169 void MainWindow::setButtonText(bool bl)
- 170 {
- 171 if (bl) {
- 172 /* 设置摄像头设备 */
- 173 camera->selectCameraDevice(comboBox->currentIndex());
- 174 pushButton[1]->setText("关闭");
- 175 } else {
- 176 /* 若关闭了摄像头则禁用拍照按钮 */
- 177 pushButton[0]->setEnabled(false);
- 178 pushButton[1]->setText("开始");
- 179 }
- 180 }
- 181
- 182 void MainWindow::saveImageToLocal()
- 183 {
- 184 /* 判断图像是否为空 */
- 185 if (!saveImage.isNull()) {
- 186 QString fileName =
- 187 QCoreApplication::applicationDirPath() + "/test.png";
- 188 qDebug()<<"正在保存"<<fileName<<"图片,请稍候..."<<endl;
- 189
- 190 /* save(arg1,arg2,arg3)重载函数,arg1代表路径文件名,
- 191 * arg2保存的类型,arg3代表保存的质量等级 */
- 192 saveImage.save(fileName, "PNG", 1);
- 193
- 194 /* 设置拍照的图像为显示在photoLabel上 */
- 195 photoLabel->setPixmap(QPixmap::fromImage(QImage(fileName)));
- 196
- 197 qDebug()<<"保存完成!"<<endl;
- 198 }
- 199 }
- 200
复制代码 第111~154行,判断linux下的设备/dev/video*。细心的同学发现,这个程序是Linux下用的。当然Windows也是可以使用OpenCV的,需要自己修改pro文件链接到Windows的OpenCV库-L需要修改为-LD,Windows下的库文件是dll类型,此外不考虑macOS系统,具体情况编者没得实验。
19.4 程序运行效果
选择合适的摄像头设备,(注意如果在Ubuntu使用USB摄像头,需要设置USB的兼容性为3.0反之2.0,具体需要看不同摄像头设备,点击连接摄像头到虚拟机。可以先使用Ubuntu18.04自带的茄子拍照软件,检测摄像头是否可用)。点击拍照,可以看程序输出的Debug信息,保存照片的路径为当前可执行程序的路径,保存照片名称为test.png,右上角显示保存照片的缩略图,再次点击拍照则会替换已经保存过的照片。若想要保存多个照片可自行设计。 若在正点原子I.MX6U开发板上运行此程序,先插上摄像头,确保摄像头能用,注意不要选择video0,video0是NXP的pxp驱动产生的节点,不是摄像头,否则会报错。I.MX6U开发板是单核A7的CPU,性能有限,所以流畅度一般,还可以。但是在保存照片时会比PC电脑慢好多,不过也不能太勉强这个6ULL芯片了啦,能拍照已经不错了,或者大家可以对保存照片步骤进行优化,开启一个线程进行优化,剩下的交给大家了,大家可以的。 OpenCV在不设置摄像头分辨率时会采用默认分辨率640*480 30fps(绝大多数摄像头都是支持这个分辨率)。USB免驱摄像头可以使用下面的方法来设置分辨率。
- capture->open(1);
- capture ->set(CV_CAP_PROP_FRAME_WIDTH, 320);
- capture ->set(CV_CAP_PROP_FRAME_HEIGHT, 240);
复制代码 但是正点原子6ULL开发板上的OV5640/OV2640/OV7725(不带FIFO款)摄像头就不可以直接使用些方法设置采集分辨率了,因为驱动里设置分辨率的方法与标准的V4L2设置分辨有些差异。也可以直接使用正点原子I.MX6U里的摄像头采集分辨率设置软件camera_settings直接设置,注意在处理图像中的matToQImage函数需要以确认的分辨率进行转换使用了。 总结,想要在Qt中使用OpenCV,那么我们的开发板文件系统里或者Ubuntu系统必须要有OpenCV的库。对于某些非通用的USB摄像头来说,因为驱动层限制不能直接使用Qt自带的QCamera类。
|