Camera
此章節(jié)例程適用于 Ubuntu 和正點(diǎn)原子 I.MX6U 開發(fā)板,不適用于 Windows(需要自行修改
才能適用 Windows,Windows 上的應(yīng)用不在我們討論范圍)!
資源簡介
正點(diǎn)原子 I.MX6U 開發(fā)板底板上有一路“CSI”攝像頭接口。支持正點(diǎn)原子的 OV5640、
OV2640 和 OV7725(不帶 FIFO)。同時(shí)有 USB 接口,可以接 USB 免驅(qū)攝像頭。例程兼容 USB
攝像頭與正點(diǎn)原子的 OV5640、OV2640 和 OV7725 攝像頭。
出廠系統(tǒng)請(qǐng)更新到正點(diǎn)原子 I.MX6U 最新的出廠系統(tǒng),在驅(qū)動(dòng)層正點(diǎn)原子對(duì) OV5640、
OV2640 和 OV7725 攝像頭維護(hù)、優(yōu)化或者添加支持。
環(huán)境搭建
Qt 里也有一個(gè) QCamera 類。沒錯(cuò),確實(shí)可以使用這個(gè) QCamera 類來開發(fā)攝像頭。但是這
個(gè)類在正點(diǎn)原子的 I.MX6U 開發(fā)板 4.1.15 內(nèi)核版本上不能使用 OV5640、OV2640 和 OV7725,
可以使用 USB 免驅(qū)攝像頭。因?yàn)?OV5640、OV2640 和 OV7725 的驅(qū)動(dòng)默認(rèn)是讀取 YUYV 格式
數(shù)據(jù),而 QCamera 里讀取的數(shù)據(jù)是 RGB 格式數(shù)據(jù),它們可能數(shù)據(jù)對(duì)不上就無法使用了!但是
也不建議修改驅(qū)動(dòng)的方法來使用 QCamera,防止 QCamera 在某些方法上與驅(qū)動(dòng)層不對(duì)應(yīng),導(dǎo)致
使用報(bào)錯(cuò)。
實(shí)際上我們使用 V4l2 編程就可以對(duì)攝像頭進(jìn)行編程,效果會(huì)比在 Qt 顯示流暢,因?yàn)?V4l2
的數(shù)據(jù)直接可以顯示在 fb0(也就是屏上)。而經(jīng)過 Qt 還需要在控件上處理,所以效率會(huì)慢一些!
在正點(diǎn)原子 I.MX6U 開發(fā)板上或者說是嵌入式上,比較低性能的 CPU 對(duì)于處理圖像等大數(shù)據(jù)還
是比較吃力的。所以我們需要去優(yōu)化,不同的編程方式,對(duì)數(shù)據(jù)的處理不同,寫出來的效果也
會(huì)不同!
下面主要介紹 Qt + OpenCV 調(diào)用攝像頭,效果肯定不能與使用 V4l2 直接顯示在 fb0 上相比。
在這個(gè)開發(fā)板的 CPU 上顯示效果還是比較好的,還能接受,流暢度一般。這個(gè)可能是 OpenCV
在對(duì)攝像頭數(shù)據(jù)做了一定的處理才會(huì)變的慢了。
要想在 Ubuntu 上使用 OpenCV,那么我們的 Ubuntu 上必須有 OpenCV 的庫,如果您不想
在 Ubuntu 安裝 OpenCV,就可以跳過這小節(jié),直接用出廠系統(tǒng)提供的交叉編譯工具鏈,里面已
經(jīng)提供有 OpenCV。在 Ubuntu 上安裝 OpenCV 只是方便我們測(cè)試界面,編寫的程序也可以在
Ubuntu 上運(yùn)行。安裝的步驟也比較簡單。
正點(diǎn)原子 I.MX6U 出廠系統(tǒng)的 OpenCV 版本為 3.1.0。也不一定非要與正點(diǎn)原子 I.MX6U 出
廠系統(tǒng)里的 OpenCV 相同版本,我們只是在 Ubuntu 上運(yùn)行 OpenCV。其中用到的 API 在 3.1.0
版本與 3.4.1 版本基本沒有什么區(qū)別。3.1.0 版本的 OpenCV 與 3.4.1 版本的 OpenCV 絕大多數(shù)核
心 API 都相同,不必要擔(dān)心找不到相同的 API。
這里筆者選擇安裝到 OpenCV 版本為 3.4.1 版本,因?yàn)?3.1.0 版本在配置 cmake 時(shí)下載的第
三方庫因?yàn)榫W(wǎng)絡(luò)的原因難下載,導(dǎo)致 cmake 配置不過去。(PS:如果不是因?yàn)榫幾g不過去,筆者
會(huì)選擇與開發(fā)板相同的版本的 OpenCV 的)。
進(jìn)入 OpenCV 的官網(wǎng) https://opencv.org/releases。下載 3.4.1 版本的 OpenCV,如下圖。我們
選擇 Sources(源碼)進(jìn)行下載。
右鍵選擇復(fù)制下載鏈接,用迅雷下載會(huì)比較快。下載完成后我們拷貝下載的文件到 Ubuntu
上進(jìn)行解壓?;蛘咧苯釉谡c(diǎn)原子的 I.MX6U 的光盤資料路徑下找到開發(fā)板光盤 A-基礎(chǔ)資料/1、
例程源碼/7、第三方庫源碼/opencv-3.4.1.tar.gz。然后拷貝到 Ubuntu 下。
如下圖我們已經(jīng)下載好文件,并拷貝下載好的文件到 Ubuntu 的家目錄下。
執(zhí)行下面的指令進(jìn)行解壓。解壓將會(huì)得到一個(gè) opencv-3.4.1 文件夾,我們使用 cd 指令進(jìn)入
此文件夾。
tar xf opencv-3.4.1.tar.gz
cd opencv-3.4.1
安裝 cmake,用于生成編譯 OpenCV 所需要的文件。
sudo apt-get install cmake
新建一個(gè) build 目錄,并進(jìn)入,用于編譯生成的文件。
mkdir build
cd build
執(zhí)行 cmake 配置編譯。注意下面的指令“…”不要漏了!這里表示上一層目錄。cmake 會(huì)從
上一層目錄下找配置項(xiàng),并配置到當(dāng)前目錄。
cmake …
在配置的過程中 cmake 會(huì)下載一些庫,如 ippicv_2017u3_lnx_intel64_general_20170822.tgz,
需要一段時(shí)間,請(qǐng)等待,如果不能下載成功請(qǐng)重復(fù)嘗試。
cmake 配置成功如下圖。
執(zhí)行 make 開始編譯。輸入下面的指令。
make -j 16 // 以實(shí)際分配給虛擬機(jī)的核心數(shù)為準(zhǔn),最佳為分配給虛擬
機(jī)核心數(shù)據(jù)的 2 倍。筆者的虛擬機(jī)最大分配了 16 個(gè)核心,筆者個(gè)人的電腦并不快,就是核心多,
所以編譯就快。編譯完成耗時(shí)約 5 分鐘。不要只輸入 make,否則將編譯很久!需要加參數(shù) -j n,
n 請(qǐng)根據(jù)個(gè)人虛擬機(jī)的實(shí)際情況。
執(zhí)行下面的指令安裝,安裝到系統(tǒng)目錄,需要加 sudo 權(quán)限。
sudo make install
安裝完成如下??梢钥吹綆毂话惭b到/usr/local/lib 下,頭文件被安裝在/usr/local/include 下。
我們只需要知道安裝的庫路徑和頭文件路徑即可在 Qt 里調(diào)用 Ubuntu 安裝的 OpenCV。頭
文件作用來編寫程序,庫路徑用來運(yùn)行程序時(shí)調(diào)用。我們只要在 Qt 的 pro 項(xiàng)目文件里指定這兩
個(gè)路徑即可。
應(yīng)用實(shí)例
請(qǐng)根據(jù)【正點(diǎn)原子】I.MX6U 出廠系統(tǒng) Qt 交叉編譯環(huán)境搭建 V1.x.pdf(x >= 6)的文檔搭建好
I.MX6U 的交叉編譯環(huán)境。交叉編譯工具鏈里已經(jīng)有 OpenCV,所以我們只要在我們搭建的交叉
環(huán)境下就可以調(diào)用 OpenCV 的相關(guān) API 進(jìn)行編寫 Qt 項(xiàng)目了。
項(xiàng)目簡介:Qt 加 OpenCV 打開攝像頭采集圖像并拍照。
例 05_opencv_camera,Qt Camera 編程(難度:較難)。項(xiàng)目路徑為 Qt/3/05_opencv_camera。
用腳本打開 Qt Creator,必須按出廠系統(tǒng) Qt 交叉編譯環(huán)境搭建 V1.x.pdf(x >= 6)的文檔搭建
好交叉編譯環(huán)境,用腳本啟動(dòng)時(shí),腳本有相應(yīng)的環(huán)境變量,編譯時(shí)會(huì)用到。
/opt/Qt5.12.9/Tools/QtCreator/bin/qtcreator.sh &
編寫程序應(yīng)使用我們搭建的 ATK-I.MX6U 套件編寫,否則若選擇了 Desktop Qt 5.12.9 GCC
64bit,如果我們的 Ubuntu 沒有安裝 OpenCV 就會(huì)使用不了 OpenCV。如果您在 19.2 小節(jié)已經(jīng)
安裝過 OpenCV,那么下面兩個(gè)套件都可一起選。本次筆者兩個(gè)一起選,因?yàn)楣P者有 USB 攝像
頭可以在 Ubutnu 上使用 OpenCV 測(cè)試,編寫的程序交叉編譯后在 I.MX6U 開發(fā)板使用 USB 免
驅(qū)攝像頭或者正點(diǎn)原子 OV5640/OV7725(不帶 FIFO 款)/OV2640 測(cè)試成功!
下面開始編寫程序。首先我們需要在項(xiàng)目 pro 文件添加 OpenCV 庫的支持及頭文件路徑。
05_opencv_camera.pro 文件如下,添加以下內(nèi)容,這里主要是判斷交叉編譯器的類型,然
后鏈接到不同的頭文件路徑與庫。
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-gnuea
bi/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 可寫可不寫,系統(tǒng)會(huì)到找到此路徑
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 對(duì)應(yīng) opencv 的頭文件路徑,可以不寫,編譯不會(huì)報(bào)錯(cuò),但是我們想查看對(duì)
應(yīng)的頭文件,就不得不包括這個(gè)路徑了,否則跳轉(zhuǎn)不過去!
第 24~32 行,添加庫的支持。-L 后面指的是庫文件路徑,-l 后面的是相關(guān)庫參數(shù)(l 是大
字母“L”的小寫字母“l(fā)”,不是一),如果不會(huì)寫庫的名稱,可以參考 Ubuntu 的 OpenCV 安裝
路徑下的/usr/local/lib/pkgconfig/opencv.pc 文件。
camera.h 文件,此文件聲明了一個(gè) Camera 類,其內(nèi)容如下,比較簡單。
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 /* 聲明信號(hào),用于傳遞有圖片信號(hào)時(shí)顯示圖像 */
29 void readyImage(const QImage&);
30
31 public slots:
32 /* 用于開啟定時(shí)器 */
33 bool cameraProcess(bool);
34
35 /* 選擇攝像頭 */
36 void selectCameraDevice(int);
37
38 private slots:
39 /* 定時(shí)器時(shí)間到處理函數(shù),發(fā)送圖像數(shù)據(jù)信號(hào) */
40 void timerTimeOut();
41
42 private:
43 /* 聲明 OpenCV 的 cv 命名空間下的 VideoCapture 對(duì)象 */
44 cv::VideoCapture * capture;
45
46 /* 定時(shí)器 */
47 QTimer * timer;
48
49 /* 圖像轉(zhuǎn)換處理函數(shù) */
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 /* 實(shí)例化 */
19 capture = new cv::VideoCapture();
20 timer = new QTimer(this);
21
22 /* 信號(hào)槽連接 */
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 /* 打開攝像頭設(shè)備 */
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 /* 返回?cái)z像頭的狀態(tài) */
52 return capture->isOpened();
53 }
54
55 void Camera::timerTimeOut()
56 {
57 /* 如果攝像頭沒有打開,停止定時(shí)器,返回 */
58 if (!capture->isOpened()) {
59 timer->stop();
60 return;
61 }
62
63 static cv::Mat frame;
64 *capture >> frame;
65 if (frame.cols)
66 /* 發(fā)送圖片信號(hào) */
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 構(gòu)造圖片 */
78 QImage qImage(pimg, img.cols, img.rows, img.step,
79 QImage::Format_RGB888);
80
81 /* 在不改變實(shí)際圖像數(shù)據(jù)的條件下,交換紅藍(lán)通道 */
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
* @author Deng Zhimao
* @email 1252699831@qq.com
* @net 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 也可以當(dāng)作一種容器 */
26 QWidget *mainWidget;
27
28 /* 滾動(dòng)區(qū)域,方便開發(fā)高分辨率 */
29 QScrollArea *scrollArea;
30
31 /* 將采集到的圖像使用 Widget 顯示 */
32 QLabel *displayLabel;
33
34 /* 界面右側(cè)區(qū)域布局 */
35 QHBoxLayout *hboxLayout;
36
37 /* 界面右側(cè)區(qū)域布局 */
38 QVBoxLayout *vboxLayout;
39
40 /* 界面右側(cè)區(qū)域容器 */
41 QWidget *rightWidget;
42
43 /* 界面右側(cè)區(qū)域顯示拍照的圖片 */
44 QLabel *photoLabel;
45
46 /* 界面右側(cè)區(qū)域攝像頭設(shè)備下拉選擇框 */
47 QComboBox *comboBox;
48
49 /* 兩個(gè)按鈕,一個(gè)為拍照按鈕,另一個(gè)是開啟攝像頭按鈕 */
50 QPushButton *pushButton[2];
51
52 /* 拍照保存的照片 */
53 QImage saveImage;
54
55 /* 攝像頭設(shè)備 */
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 /* 設(shè)置按鈕文本 */
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 * 種方法獲取屏幕分辨率,防上多屏設(shè)備導(dǎo)致對(duì)應(yīng)不上
27 * 注意,這是獲取整個(gè)桌面系統(tǒng)的分辨率
28 */
29 QList <QScreen *> list_screen = QGuiApplication::screens();
30
31 /* 如果是 ARM 平臺(tái),直接設(shè)置大小為屏幕的大小 */
32 #if __arm__
33 /* 重設(shè)大小 */
34 this->resize(list_screen.at(0)->geometry().width(),
35 list_screen.at(0)->geometry().height());
36 #else
37 /* 否則則設(shè)置主窗體大小為 800x480 */
38 this->resize(800, 480);
39 #endif
40
41 /* 實(shí)例化與布局,常規(guī)操作 */
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 /* 自動(dòng)拉伸 */
87 photoLabel->setScaledContents(true);
88 displayLabel->setScaledContents(true);
89
90 /* 設(shè)置一些屬性 */
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 /* 信號(hào)連接槽 */
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 系統(tǒng),一般是攝像頭 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("無攝像頭設(shè)備");
128 return;
129 }
130
131 file.setFileName("/dev/video1");
132
133 if (file.exists()) {
134 comboBox->addItem("video1");
135 /* 開發(fā)板 ov5640 等設(shè)備是 1 */
136 comboBox->setCurrentIndex(1);
137 }
138
139 file.setFileName("/dev/video2");
140
141 if (file.exists())
142 /* 開發(fā)板 USB 攝像頭設(shè)備是 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 /* 判斷圖像是否為空,空則設(shè)置拍照按鈕不可用 */
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 /* 設(shè)置攝像頭設(shè)備 */
173 camera->selectCameraDevice(comboBox->currentIndex());
174 pushButton[1]->setText("關(guān)閉");
175 } else {
176 /* 若關(guān)閉了攝像頭則禁用拍照按鈕 */
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<<"圖片,請(qǐng)稍候..."<<endl;
189
190 /* save(arg1,arg2,arg3)重載函數(shù),arg1 代表路徑文件名,
191 * arg2 保存的類型,arg3 代表保存的質(zhì)量等級(jí) */
192 saveImage.save(fileName, "PNG", -1);
193
194 /* 設(shè)置拍照的圖像為顯示在 photoLabel 上 */
195 photoLabel->setPixmap(QPixmap::fromImage(QImage(fileName)));
196
197 qDebug()<<"保存完成!"<<endl;
198 }
199 }
200
第 111~154 行,判斷 linux 下的設(shè)備/dev/video*。細(xì)心的同學(xué)發(fā)現(xiàn),這個(gè)程序是 Linux 下用
的。當(dāng)然 Windows 也是可以使用 OpenCV 的,需要自己修改 pro 文件鏈接到 Windows 的 OpenCV
庫-L 需要修改為-LD,Windows 下的庫文件是 dll 類型,此外不考慮 macOS 系統(tǒng),具體情況筆
者沒得實(shí)驗(yàn)。
程序運(yùn)行效果
選擇合適的攝像頭設(shè)備,(注意如果在 Ubuntu 使用 USB 攝像頭,需要設(shè)置 USB 的兼容性
為 3.0 反之 2.0,具體需要看不同攝像頭設(shè)備,點(diǎn)擊連接攝像頭到虛擬機(jī)??梢韵仁褂?Ubuntu18.04
自帶的茄子拍照軟件,檢測(cè)攝像頭是否可用)。點(diǎn)擊拍照,可以看程序輸出的 Debug 信息,保
存照片的路徑為當(dāng)前可執(zhí)行程序的路徑,保存照片名稱為 test.png,右上角顯示保存照片的縮略
圖,再次點(diǎn)擊拍照則會(huì)替換已經(jīng)保存過的照片。若想要保存多個(gè)照片可自行設(shè)計(jì)。
若在正點(diǎn)原子 I.MX6U 開發(fā)板上運(yùn)行此程序,先插上攝像頭,確保攝像頭能用,注意不要
選擇 video0,video0 是 NXP 的 pxp 驅(qū)動(dòng)產(chǎn)生的節(jié)點(diǎn),不是攝像頭,否則會(huì)報(bào)錯(cuò)。I.MX6U 開發(fā)
板是單核 A7 的 CPU,性能有限,所以流暢度一般,還可以。但是在保存照片時(shí)會(huì)比 PC 電腦
慢好多,不過也不能太勉強(qiáng)這個(gè) 6ULL 芯片了啦,能拍照已經(jīng)不錯(cuò)了,或者大家可以對(duì)保存照
片步驟進(jìn)行優(yōu)化,開啟一個(gè)線程進(jìn)行優(yōu)化,剩下的交給大家了,大家可以的。
OpenCV 在不設(shè)置攝像頭分辨率時(shí)會(huì)采用默認(rèn)分辨率 640*480 30fps(絕大多數(shù)攝像頭都是
支持這個(gè)分辨率)。USB 免驅(qū)攝像頭可以使用下面的方法來設(shè)置分辨率。
capture->open(1);
capture ->set(CV_CAP_PROP_FRAME_WIDTH, 320);
capture ->set(CV_CAP_PROP_FRAME_HEIGHT, 240);
但是正點(diǎn)原子 6ULL 開發(fā)板上的 OV5640/OV2640/OV7725(不帶 FIFO 款)攝像頭就不可
以直接使用些方法設(shè)置采集分辨率了,因?yàn)轵?qū)動(dòng)里設(shè)置分辨率的方法與標(biāo)準(zhǔn)的 V4L2 設(shè)置分辨
有些差異。也可以直接使用正點(diǎn)原子 I.MX6U 里的攝像頭采集分辨率設(shè)置軟件 camera_settings
直接設(shè)置,注意在處理圖像中的 matToQImage 函數(shù)需要以確認(rèn)的分辨率進(jìn)行轉(zhuǎn)換使用了。文章來源:http://www.zghlxwxcb.cn/news/detail-530529.html
總結(jié),想要在 Qt 中使用 OpenCV,那么我們的開發(fā)板文件系統(tǒng)里或者 Ubuntu 系統(tǒng)必須要
有 OpenCV 的庫。對(duì)于某些非通用的 USB 攝像頭來說,因?yàn)轵?qū)動(dòng)層限制不能直接使用 Qt 自帶
的 QCamera 類。文章來源地址http://www.zghlxwxcb.cn/news/detail-530529.html
到了這里,關(guān)于QT開發(fā)筆記(Camera)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!