2023-02-20 Qt5.13.1 + MinGW730 + OpenCV4.5.4環境編譯

引言

OpenCV圖像處理在Qt中編譯記錄。
之前一直是在Python中使用OpenCV,Python中使用某些模塊使用pip工具很容易將對應的模塊安裝在系統中。根據項目需求項目都要轉移在國產化中使用,為了適應國產化需求,將代碼轉移到Qt開發環境中,Qt使用OpenCV需要使用源碼編譯對應的庫文件,在這里做個記錄。

OpenCV網站也有對應在Windows環境中已經編譯好的安裝包,我也下載安裝了,但是在使用過程中還是有問題。根據筆者編譯后的心得,OpenCV編譯后的庫是根編譯器有關的,不知道官網中使用的什么編譯器,也只是編譯好了,如果你系統中的編譯環境與那個一樣,那么也許正好就能用了。筆者這里使用的是安裝Qt時自身的編譯環境MinGW730_64。這個環境使用OpenCV預編譯的就用不成,具體啥原因也還不清楚,這里就不過多的折騰,那么就根據自己的開發環境來編譯一套OpenCV的庫。

筆者的環境是Windows 10,Qt5.13.1,OpenCV4.5.4,編譯工具cmake3.25.2。

在Python中使用筆者使用的是OpenCV4.5.5,所以剛開始也想編譯OpenCV4.5.5,但是一直不成功,看到有網友說是:該版本的protobuf版本為3.19,使用的Qt5.13.1自帶的MinGW編譯會報錯誤編譯不過去。這是由于protobuf這個版本太新了,Qt5.13.1中MinGW的gcc版本還不支持這種C++新語法,所以我再去查看OpenCV 4.5.4版本中protobuf版本發現是3.5.1,這個版本舊沒有用到C++語法的新特性,所以編譯沒有出現問題。因此筆者也編譯了4.5.4。

文件準備

下載Qt:https://download.qt.io/archive/qt/5.13/5.13.1/

2023-02-20_162344.png

下載OpenCV源碼:https://codeload.github.com/opencv/opencv/zip/refs/tags/4.5.4

2023-02-20_164038.png

下載opencv_contrib源碼:https://codeload.github.com/opencv/opencv_contrib/zip/refs/tags/4.5.4

2023-02-20_164122.png

下載cmake:https://cmake.org/download/

2023-02-20_164206.png

下載完成后你將得到以下文件


2023-02-20_164539.png

版本

名稱 版本
OS Windows 10
Qt 5.13.1
Qt Creator 4.10.0
MinGW 730
OpenCV 4.5.4
opencv_contrib 4.5.4
cmake 3.25.2

安裝

注意事項

在使用cmake時會需要聯網下載一些文件,所以你的電腦是需要互聯網的。如果是局域網環境不方便上網,那你可以找一臺可以上網的電腦,根據局域網電腦的軟件環境編譯一套OpenCV庫,再通過別的方式拷貝到局域網點中,編譯完成后就是一些庫文件是可以轉移的,當然轉移后也記得配置環境變量。

環境準備

首先你要安裝Qt,這里安裝過程不做介紹,主要要安裝MinGW編譯器。我想你既然要在Qt中使用OpenCV,那么你對Qt的認識肯定可以跳過這一步,如果你也是新手,那么你可以先看一下其他關于Qt安裝的內容。


2023-02-20_164843.png

上文中下載的cmake是一個綠色版的壓縮包,解壓出來就可以用。


2023-02-20_164832.png

OpenCV和opencv_contrib也是2個源碼壓縮包,準備你的目錄將2個壓縮包解壓出來,筆者是在D盤下創建opencv文件夾,將2個壓縮包解壓在這個文件夾內。
需要注意的是路徑不要有空格等特殊字符

2023-02-20_164949.png

完成上述操作后配置環境變量,這里配置2個Qt的MinGW的和一個cmake的,具體路徑按照你的安裝路徑來。


2023-02-20_165218.png

編譯OpenCV

可以先看一下上文中解壓出來的OpenCV源碼文件夾里面的內容,因為后面我們編譯后編譯的文件會在這里,至少你要知道編譯后你得到了哪些文件。


2023-02-20_165709.png

打開cmake的可視化工具cmake-gui.exe


2023-02-20_165847.png
2023-02-20_165939.png

我們要操作的就是如下幾個位置,在where is the source code選擇上文中解壓的OpenCV源碼的文件夾。where to build the binaries選擇你要將OpenCV編譯到哪個文件夾,筆者這里選擇在源碼文件夾中創建一個build文件夾,在每編譯的時候這個文件夾里面還沒有內容。


2023-02-20_170328.png
2023-02-20_170340.png

點擊configure,選擇你的編譯器


2023-02-20_170514.png

下一步選擇C和C++編譯器,這里選擇你Qt安裝文件夾中Qt自帶的gcc和g++。


2023-02-20_170705.png
2023-02-20_170733.png
2023-02-20_170855.png

點擊finish,cmake進入配置環節,配置環節會出現一些錯誤,筆者看很多人說的都不一樣,有很多其實不用管的,比如這里的紅色警告,筆者就沒有管,當然后面還有的是需要修改的。


2023-02-20_170926.png

等待一會出現configuring done日志后就配置完成,此時cmake會有很多紅色警告,這里不用管。


2023-02-20_171257.png

在這里我們添加opencv_contrib擴展,在search位置輸入OPENCV_EXTRA_MODULES_PATH搜索OpenCV擴展模塊,填入opencv_contrib擴展的modules文件夾路徑,


2023-02-20_171455.png
2023-02-20_171650.png

再搜索WITH_QT,默認是不選中的,這里我們選中它


2023-02-20_171745.png

再搜索WITH_OPENGL,默認是不選中的,我們選中它


2023-02-20_171858.png

再點擊configure,進行配置


2023-02-20_172102.png

等一會出現配置完成。

再次進入配置選項界面,有網友說繼續配置QT_QMAKE_EXECUTABLE屬性,但是筆者這里搜索不出來這個屬性,因此跳過。


2023-02-20_172436.png

繼續搜索Qt5_DIR屬性,有網友說是要配置到Qt/Qtxxx/xxx/mingwxxx/bin/qmake.exe這個qmake文件,但是在選擇的時候這個屬性很明顯是需要一個文件夾,而不是一個文件。因此對這個屬性進行說明,筆者這里找到這個屬性,看了一下默認的配置屬性,主機上是有這個文件夾的,因此沒有修改,就使用默認的配置屬性


2023-02-20_172620.png
2023-02-20_172454.png
2023-02-20_172845.png

再點擊configure,等一會出現配置完成并且cmake中沒有紅色錯誤就說明配置成功(如果你看到配置成功日志,那就多執行幾次configure)。


2023-02-20_173028.png

再次查看build文件夾,里面已經有一些文件了。


2023-02-20_173209.png

點擊generate生成工程文件


2023-02-20_173618.png
2023-02-20_173634.png

再看build文件夾又會多一些新的文件


2023-02-20_173816.png

在cmd命令行中進入到build路徑,執行命令mingw32-make進行編譯,這個命令可以添加參數-j 8,表示開啟8線程同時編譯,這樣會增加電腦CPU的使用率從而加快速度。筆者這里使用的編譯命令就是:

mingw32-make -j 8
2023-02-21_085613.png

編譯需要等一會,過程中會出現一些如下的錯誤日志,都不用管


2023-02-21_085827.png
2023-02-21_090214.png
2023-02-21_091212.png

出現如下日志說明構建完成


2023-02-21_091422.png

構建完成后繼續在build路徑下執行命令mingw32-make install進行安裝,此時就默認安裝在../build/install文件夾中。


2023-02-21_091637.png
2023-02-21_091718.png
2023-02-21_091821.png

等待命令執行完成,在看build文件夾中出現了install文件夾,說明安裝成功,后面就可以使用了。


2023-02-21_091856.png

使用

環境變量

將上文中安裝的路徑配置到環境變量中


2023-02-21_092026.png

Qt5.13.1使用

使用Qt Creator創建一個工程,筆者這里命名OpenCV2。


2023-02-21_092237.png

build system選擇默認的qmake


2023-02-21_092317.png

details可以默認


2023-02-21_092325.png

kits選擇注意要選擇MinGW,因為我們使用的是MinGW編譯的OpenCV,這也是我們編譯的目的。而且要注意版本,比如筆者電腦上裝了一個Qt5.13.1,裝了一個Qt5.4.1,所以這里的kits選項就出現了2個MinGW,因為我們是使用Qt5.13.1中的MinGW進行編譯的,所以這里要選擇Qt5.13.1的MinGW。


2023-02-21_092345.png

剩下的就是默認,我們能看到初始化的代碼,并且程序能運行啟動我們的初始化窗口。


2023-02-21_092835.png

在pro文件中添加OpenCV的庫鏈接。在pro文件的最后添加2行鏈接代碼,這里的路徑填寫你自己電腦上面的路徑地址

INCLUDEPATH += D:\opencv\opencv-4.5.4\build\install\include
LIBS += -L D:\opencv\opencv-4.5.4\build\install\x64\mingw\lib\libopencv_*.a
2023-02-21_093020.png

在主界面中添加使用OpenCV的代碼,這里的代碼是使用OpenCV讀取本地的一張圖像,在Qt主窗口中將這個圖像顯示出來。其中使用到一個Mat2QImage函數,這個函數是因為OpenCV讀取的圖像是Mat對象,需要轉成QImage對象。


2023-02-21_102510.png
#include "widget.h"
#include "ui_widget.h"

#include "QDebug"

#include <QImage>
#include <QLabel>
#include <opencv2/opencv.hpp>
#include <opencv2/core/mat.hpp>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    setWindowTitle("Qt OpenCV 圖像顯示");

    //OpenCV讀取本地圖像
    cv::Mat src = cv::imread("D:/dr.jpg");

    QImage img = Mat2QImage(src);
    img = img.scaled(img.width()/2, img.height()/2);
    QPixmap pixmap = QPixmap::fromImage(img);
    QLabel *label = new QLabel();
    label->setParent(this);
    label->setPixmap(pixmap);
    this->window()->resize(img.width(), img.height());
}

Widget::~Widget()
{
    delete ui;
}

/**
 * OpenCV 的Mat類型圖像轉Qt中的QImage
 * @brief Widget::Mat2QImage
 * @param mat
 * @return
 */
QImage Widget::Mat2QImage(cv::Mat mat)
{
    const unsigned char* data = mat.data;

    int width = mat.cols;
    int height = mat.rows;
    int bytesPerLine = static_cast<int>(mat.step);
    switch(mat.type())
    {
        //ARGB
        case CV_8UC4:
        {
            QImage image(data, width, height, bytesPerLine, QImage::Format_ARGB32);
            return image;
        }
        //BGR
        case CV_8UC3:
        {
            QImage image(data, width, height, bytesPerLine, QImage::Format_RGB888);
            //swap blue and red channel
            return image.rgbSwapped();
        }
        //Gray shale
        case CV_8UC1:
        {
            QImage image(data, width, height, bytesPerLine, QImage::Format_Grayscale8);
            return image;
        }
        //
        default:
        {
            //Unsupported format
            qDebug()<<"Unsupported cv::Mat type:"<<mat.type()<<", Empty QImage will be returned!";
            return QImage();
        }
    }
}
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <opencv2/opencv.hpp>
#include <opencv2/core/mat.hpp>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;

    QImage Mat2QImage(cv::Mat src);
};
#endif // WIDGET_H

上述代碼是將圖像顯示在QT程序窗口中,QT程序就一個窗口時只能顯示一個圖片,在調試過程中我們可能會需要顯示多個圖片進行對比,一個窗口就不夠了,所以可以使用OpenCV提供的窗口進行查看,將Mat轉QImage在label中顯示的代碼注釋掉,使用cv::imshow();函數調用OpenCV顯示圖像的方式可以單獨開一個OpenCV窗口顯示圖像。這個窗口與QT程序窗口是獨立的,這個窗口關閉,程序沒有退出,程序窗口關閉,這個窗口會關閉。

#include "widget.h"
#include "ui_widget.h"

#include "QDebug"

#include <QImage>
#include <QLabel>
#include <opencv2/opencv.hpp>
#include <opencv2/core/mat.hpp>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    setWindowTitle("Qt OpenCV 圖像顯示");
    //OpenCV讀取本地圖像
    cv::Mat src = cv::imread("D:/normal.png");
//    QImage img = Mat2QImage(src);
//    img = img.scaled(img.width() / 2, img.height() / 2);
//    QPixmap pixmap = QPixmap::fromImage(img);
//    QLabel *label = new QLabel();
//    label->setParent(this);
//    label->setPixmap(pixmap);
//    this->window()->resize(img.width(), img.height());
    cv::imshow("OpenCV", src);
}

Widget::~Widget()
{
    delete ui;
}

/**
 * OpenCV 的Mat類型圖像轉Qt中的QImage
 * @brief Widget::Mat2QImage
 * @param mat
 * @return
 */
QImage Widget::Mat2QImage(cv::Mat mat)
{
    const unsigned char* data = mat.data;
    int width = mat.cols;
    int height = mat.rows;
    int bytesPerLine = static_cast<int>(mat.step);
    switch (mat.type())
    {
        //ARGB
        case CV_8UC4:
        {
            QImage image(data, width, height, bytesPerLine, QImage::Format_ARGB32);
            return image;
        }
        //BGR
        case CV_8UC3:
        {
            QImage image(data, width, height, bytesPerLine, QImage::Format_RGB888);
            //swap blue and red channel
            return image.rgbSwapped();
        }
        //Gray shale
        case CV_8UC1:
        {
            QImage image(data, width, height, bytesPerLine, QImage::Format_Grayscale8);
            return image;
        }
        //
        default:
        {
            //Unsupported format
            qDebug() << "Unsupported cv::Mat type:" << mat.type() << ", Empty QImage will be returned!";
            return QImage();
        }
    }
}
2024-02-22_091305.jpg
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,517評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,087評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 177,521評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,493評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,207評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,603評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,624評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,813評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,364評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,110評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,305評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,874評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,532評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,953評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,209評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,033評論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,268評論 2 375