在Qt5.2上配置opencv2.9

我們的作業環境是在win10

使用的IDE為  Qt Creator (Community)  /  Qt 5.2
使用opencv249版   也可用2411、或者opencv3



動機是  覺得  Qt   和opencv的媒合性很高

是很有潛力的技術



而且可以寫 視窗介面   是 還不錯的  一個  C++ 框架

成品效果




最主要是用來和影像處理來做結合

讓使用者更能體會到  user friendly

XDD所以可以學習一下



還沒下載Qt的
附上連結給大家

https://download.qt.io/archive/qt/5.2/5.2.0/




5.2只支援到 Microsoft Visual Studio 2012


如果要到2013 就升到5.3喔




最新5.7有支援   vs2015


不過經過測試發現最穩定的是5.2這版



【第一階段 - 新增Qt專案】

首先開啟 Qt 之後


New   一個 新的  project

Application -->  Qt Console Application












【第二階段 - 配置opencv】


到 .pro 區塊 去配置opencv



【配置】


#-------------------------------------------------
#
# Project created by QtCreator 2016-07-25T03:23:43
#
#-------------------------------------------------

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = Qt_opencv_webcam
TEMPLATE = app


SOURCES += main.cpp\
        mainwindow.cpp

HEADERS  += mainwindow.h

FORMS    += mainwindow.ui

INCLUDEPATH += C:\opencv249\opencv\build\include
               C:\opencv249\opencv\build\include\opencv
               C:\opencv249\opencv\build\include\opencv2
CONFIG(debug,debug|release)
{
    LIBS += C:\opencv249\opencv\build\x64\vc12\lib\opencv_core249d.lib
    LIBS += C:\opencv249\opencv\build\x64\vc12\lib\opencv_highgui249d.lib
    LIBS += C:\opencv249\opencv\build\x64\vc12\lib\opencv_imgproc249d.lib
    LIBS += C:\opencv249\opencv\build\x64\vc12\lib\opencv_objdetect249d.lib
    LIBS += C:\opencv249\opencv\build\x64\vc12\lib\opencv_contrib249d.lib
    LIBS += C:\opencv249\opencv\build\x64\vc12\lib\opencv_ml249d.lib
}
CONFIG(release,debug|release)
{
    LIBS += C:\opencv249\opencv\build\x64\vc12\lib\opencv_core249.lib
    LIBS += C:\opencv249\opencv\build\x64\vc12\lib\opencv_highgui249.lib
    LIBS += C:\opencv249\opencv\build\x64\vc12\lib\opencv_imgproc249.lib
    LIBS += C:\opencv249\opencv\build\x64\vc12\lib\opencv_objdetect249.lib
    LIBS += C:\opencv249\opencv\build\x64\vc12\lib\opencv_contrib249.lib
    LIBS += C:\opencv249\opencv\build\x64\vc12\lib\opencv_ml249.lib
}


還有一步就是動態涵式庫
記得要加入剛剛設定的編譯資料夾中或者在環境設定中加入連結喔~~


法一、

C:\OpenCV_2_4_9\build\x86\vc12\bin資料夾底下的dll檔複製至剛剛設定的編譯資料夾,如F:\cv_Qt\build-Qt_opencv_webcam-Desktop_Qt_5_2_0_MSVC2012_OpenGL_64bit-Debug。


法二、

電腦->內容->進階系統設定->環境變數中的Path加入

C:\OpenCV_2_4_9\build\x86\vc11\bin連結。




【第三階段 - 視窗的拖拉設計】


捨麼c++竟然也可以進行視窗的配置

沒錯 在 Qt Creator 的強大之下

開發者可根據自己的需求去進行視窗設置






【第四階段 - 按鈕觸發事件撰寫】

右鍵 --> 跳到信號槽

可以選擇  clicked 事件






首先是  mainwindow.h

如果你懶的話

預設就叫做 mainwindow

mainwindow.h



#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include<QFileDialog>
#include <QTimer>
#include <iostream>
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include"opencv2/imgproc/imgproc.hpp"
#include"opencv2/opencv.hpp"
using namespace cv;
using namespace std;

namespace Ui {
    class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void nextFrame();   

    void on_pushButton_clicked();  // open file

    void on_pushButton_2_clicked(); // open webcam

    void on_pushButton_3_clicked(); // process

    void on_pushButton_4_clicked(); //

    void on_pushButton_5_clicked();

private:
    Ui::MainWindow *ui;
    Mat frame;
    VideoCapture capture;
    QImage image , image1;
    QTimer *timer;
    double rate;//fps
    VideoWriter writer;
};

#endif // MAINWINDOW_H


openCV打開視頻文件

創建一個cv::VideoCapture類的實體,
然後在迴圈中照一定的時間間隔
讀取每一frame影像即可實現視頻文件的讀取。

cv::VideoCapture類提供一個方法是open( ),可以打開一個video或者webcam來獲取視頻流

我們為了實現點擊相應的按鍵打開文件或攝像頭,可以在槽函數中實現該過程,代碼如下。




mainwindow.cpp



#include "mainwindow.h"
#include "ui_mainwindow.h"

QImage  Mat2QImage(cv::Mat cvImg) // opencv 轉 QImage 的方法
{
    QImage qImg;
    if(cvImg.channels()==3)                             //3 channels color image
    {
        //首先因為opencv的Mat容器盛載的通道順序為B->G->R
        //在Qt中使用的是QImage通道順序是R->G->B因此我們須將opencv的Mat通道反敘(轉換)
        cv::cvtColor(cvImg,cvImg,CV_BGR2RGB);

        qImg =QImage((const unsigned char*)(cvImg.data),
                    cvImg.cols, cvImg.rows,
                    cvImg.cols*cvImg.channels(),
                    QImage::Format_RGB888);
    }
    else if(cvImg.channels()==1)                    //grayscale image
    {
        qImg =QImage((const unsigned char*)(cvImg.data),
                        cvImg.cols,cvImg.rows,
                        cvImg.cols*cvImg.channels(),
                    QImage::Format_Indexed8);
    }
    else
    {
        qImg =QImage((const unsigned char*)(cvImg.data),
                    cvImg.cols,cvImg.rows,
                    cvImg.cols*cvImg.channels(),
                    QImage::Format_RGB888);
    }
    return qImg;
}





MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->label->setScaledContents(true);
    //fit video to label area
    //capture.open(0);           //open the default camera
    if (capture.isOpened())
    {
        rate= capture.get(CV_CAP_PROP_FPS);
        capture >> frame;
        //capture >> frame;
        if (!frame.empty())
        {

            image = Mat2QImage(frame);
            ui->label->setPixmap(QPixmap::fromImage(image));
            timer = new QTimer(this);
            timer->setInterval(1000/rate);   //set timer match with FPS
            connect(timer, SIGNAL(timeout()), this, SLOT(nextFrame()));
            timer->start();
        }
    }
}

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


void MainWindow::nextFrame()
{
    capture>>frame;
    if(!frame.empty())
    {
        image = Mat2QImage(frame);
        ui->label->setPixmap(QPixmap::fromImage(image));
    }

}

void MainWindow::on_pushButton_clicked()
{
    if (capture.isOpened())
            capture.release();     //decide if capture is already opened; if so,close it
        QString filename =QFileDialog::getOpenFileName(this,tr("Open Video File"),".",tr("Video Files(*.avi *.mp4 *.flv *.mkv)"));
        capture.open(filename.toLocal8Bit().data());
        if (capture.isOpened())
        {
            rate= capture.get(CV_CAP_PROP_FPS);
            capture >> frame;
            if (!frame.empty())
            {

                image = Mat2QImage(frame);
                ui->label->setPixmap(QPixmap::fromImage(image));
                timer = new QTimer(this);
                timer->setInterval(1000/rate);   //set timer match with FPS
                connect(timer, SIGNAL(timeout()), this, SLOT(nextFrame()));
                timer->start();
            }
        }
}

void MainWindow::on_pushButton_2_clicked()
{
    if (capture.isOpened())
            capture.release();     //decide if capture is already opened; if so,close it
        capture.open(0);           //open the default camera
        if (capture.isOpened())
        {
            rate= capture.get(CV_CAP_PROP_FPS);
            capture >> frame;
            if (!frame.empty())
            {

                image = Mat2QImage(frame);
                ui->label->setPixmap(QPixmap::fromImage(image));
                timer = new QTimer(this);
                timer->setInterval(1000/rate);   //set timer match with FPS
                connect(timer, SIGNAL(timeout()), this, SLOT(nextFrame()));
                timer->start();
            }
        }
}

void MainWindow::on_pushButton_3_clicked()
{
    //if (capture.isOpened())
      //      capture.release();     //decide if capture is already opened; if so,close it
    //if (capture.isOpened())
    //{
    Mat cannyImg ;

    if (capture.isOpened())
            capture.release();     //decide if capture is already opened; if so,close it
        //capture.open(0);           //open the default camera
        if (capture.isOpened())
        {
            rate= capture.get(CV_CAP_PROP_FPS);
            capture >> frame;
            Canny(frame, cannyImg, 0, 30, 3);
            //image = Mat2QImage(cannyImg);
            if (!frame.empty())
            {
                Canny(frame, cannyImg, 0, 30, 3);
                image = Mat2QImage(cannyImg);
                ui->label->setPixmap(QPixmap::fromImage(image));
                timer = new QTimer(this);
                timer->setInterval(1000/rate);   //set timer match with FPS
                connect(timer, SIGNAL(timeout()), this, SLOT(nextFrame()));
                timer->start();
            }
        }




    //ui->label->setPixmap(QPixmap::fromImage(image));
    //ui->label->resize(ui->label->pixmap()->size());

    //namedWindow("Canny");
    //imshow("Canny", cannyImg);

}

void MainWindow::on_pushButton_4_clicked()
{

    writer.open("F:/cv_Qt/myrec.avi",CV_FOURCC('P','I','M','1'), /*capture.get(CV_CAP_PROP_FPS)*/30, cv::Size(frame.cols, frame.rows),true);
    int t=300;
    while(t--)
    {
        writer.write(frame);
    } //record 100 frames

    ui->pushButton_4->setDisabled(true);
    //if successfully start videoWriter, disable the button
}




void MainWindow::on_pushButton_5_clicked()
{
    writer.release();
}



Mat類型轉換為QImage類型



在上述代碼中,我們看到有個Mat2QImage函數,

可將openCV的Mat轉換為QImage型態,以便在Qt下顯示視頻圖像。

其中需要將cv::Mat的BGR通道順序變換為QImage的RGB順序,

可以使用cv::cvtColor函數實現,

以上是對兩種圖像類型的data部分的格式進行調整,

下一步只需要明確Mat的頭結構裡的變量與QImage的頭結構裡的變量的

對應關係即可實現轉換,有如下對應關係


QImage Mat 指標

uchar* bits()

uchar* data

寬度int width() int cols

高度int height() int rows

步長int bytesPerLine() cols * channels()

格式
Format_Indexed8 8UC1, GRAY,灰度圖     
Format_RGB888 8UC3, BGR ,3通道真彩色(需要使用cvtColor調換順序)     Format_ARGB32 8UC4, BGRA,4通道真彩色(需要使用cvtColor調換順序)







留言

這個網誌中的熱門文章

何謂淨重(Net Weight)、皮重(Tare Weight)與毛重(Gross Weight)

Architecture(架構) 和 Framework(框架) 有何不同?_軟體設計前的事前規劃的藍圖概念

經得起原始碼資安弱點掃描的程式設計習慣培養(五)_Missing HSTS Header