高版本Opencv內置的videoInput庫的使用方法(2)

環境:

Windows XP

QtCreator

Qt4.8.3

Opencv2.4.3


源代碼下載:

《高版本Opencv內置的videoInput庫的使用方法(2).zip》


特別標註:

有些網站轉載我的文章不標明出處,並且轉載不到位,沒有把相應的鏈接一塊轉過去,比如說下載鏈接或相關文獻的鏈接等,導致一些網友閱讀和使用出現障礙和知識的不連續性,所以在此特別標註:我的這篇文章發表在CSDN博客上,可以到CSDN博客來閱讀。


前言:

對於videoInput這個庫在高版本的opencv2.4.3的使用方法,在前面一篇博文《高版本Opencv內置的videoInput庫的使用方法》已經介紹過。博文主要介紹瞭如何利用videoInput庫打開多個攝像頭,其他的就沒有過多提及。有人就發現,如果我想使用其他的videoInput成員方法改怎麼辦?

更確切地說,比如把所有攝像頭名稱羅列出來,然後能夠對具體攝像頭進行開啓關閉操作等等。

就我目前掌握的opencv的知識來看,還比較難處理這樣的事情的。但如果直接使用videoInput庫的話,這些問題都小菜一碟。再一個,videoInput雖然已經融入opencv了,但就我啃它代碼發現只開放了一個攝像頭創建接口,並且是經過層層封裝的,其他成員函數就沒引出來,所以致使很多人都知道opencv裏面添加了videoInput,但卻不知道怎樣使用。(我也不是很清楚opencv爲什麼這樣做,或者也有可能這些屬性方法在後面版本會陸續出來)


正題:

經過一晚的奮鬥,我在WindowsXP+opencv2.4.3+QtCreator+QT4.8.3的環境裏導入了外來的videoInput庫,實現了多個攝像頭的控制功能。

(對於videoInput庫的介紹和環境搭建過程,請參閱我前幾篇的相關博文,在此就不詳細介紹了)

這個工程的重點不是videoInput或者opencv的使用代碼編寫,而是加入videoInput庫時的編譯環境配置。這個相當重要,否則神仙也救不了大家。很多人就是在這一塊夭折的。

首先,把videoInput和DShow的相關頭文件和庫導入工程文件夾裏面(我的源代碼工程裏面已經附有這些文件,直接下載使用即可)


現在我就把我的配置貼出來(使用者請根據自己的環境重新配置路徑)

<span style="font-size:14px;">#-------------------------------------------------
#
# Project created by QtCreator 2013-01-11T21:49:08
# By JasonQue ([email protected])
# http://blog.csdn.net/jasonque
#
#-------------------------------------------------

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = opencvtest
TEMPLATE = app

SOURCES += main.cpp\
        widget.cpp

HEADERS  += widget.h

FORMS    += widget.ui

INCLUDEPATH +=  E:\opencv\build\include \
                E:\opencv\build\include\opencv \
                E:\opencv\build\include\opencv2 \
                E:\opencvtest\libs\videoInput \
                E:\opencvtest\libs\DShow\Include

LIBS += E:\opencv\build\x86\vc10\lib\opencv_core243d.lib    \
        E:\opencv\build\x86\vc10\lib\opencv_highgui243d.lib  \
        E:\opencv\build\x86\vc10\lib\opencv_imgproc243d.lib \
        E:\opencvtest\libs\videoInput\libvideoInput.a

LIBS += -L E:\opencvtest\libs\DShow\lib \
-lddraw\
-ldxguid\
-lole32\
-loleaut32\
-lstrmbasd\
-lstrmbase\
-lstrmiids\
-luuid
</span>

再下來就是把主要代碼貼出來,關於裏面的邏輯挺簡單的,大家自己看代碼吧。

(main.cpp)

<span style="font-size:14px;">/***************************************************
 *
 * main.cpp
 * By JasonQue ([email protected])
 * http://blog.csdn.net/jasonque
 *
 ****************************************************/

#include "widget.h"
#include <QApplication>
#include <QTextCodec>
#include <QLabel>

int main(int argc, char *argv[])
{

    QApplication a(argc, argv);
    //中文設置,不同的系統可能參數不一樣
    QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));

    Widget w;
    w.show();
    
    return a.exec();
}
</span>

(widget.cpp)

<span style="font-size:14px;">/***************************************************
 *
 * widget.cpp
 * By JasonQue ([email protected])
 * http://blog.csdn.net/jasonque
 *
 ****************************************************/

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

using namespace cv;

#define _width 320  //圖像寬度
#define _height 240 //圖像高度
#define image_Format  QImage::Format_RGB888//圖片顯示格式

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

    int cameraCount = 0;
    cameraCount = VI.listDevices(false);    //攝像頭設備個數

    //在combox裏羅列出所有攝像頭
    QStringList cameraList;
    QString cameraName;
    cameraList.clear();
    ui->cameraSelectBox->clear();
    for (int i=0; i<cameraCount; i++){
        cameraName = tr(VI.getDeviceName(i));
        cameraList << cameraName+tr("攝像頭")+QString::number(i, 10);
    }
    ui->cameraSelectBox->addItems(cameraList);
    ui->cameraSelectBox->setCurrentIndex(0);

    //開闢圖像空間,用於存儲攝像頭圖像
    cameraImage0 = cvCreateImage(cvSize(_width,_height), IPL_DEPTH_8U, 3);
    cameraImage1 = cvCreateImage(cvSize(_width,_height), IPL_DEPTH_8U, 3);
    cameraImage2 = cvCreateImage(cvSize(_width,_height), IPL_DEPTH_8U, 3);
    cameraImage3 = cvCreateImage(cvSize(_width,_height), IPL_DEPTH_8U, 3);

    cameraFlag0 = false;
    cameraFlag1 = false;
    cameraFlag2 = false;
    cameraFlag3 = false;

    //設置定時器,每30毫秒更新圖顯狀態
    timer = new QTimer(this);
    connect(timer,SIGNAL(timeout()),this,SLOT(startLoopSlot()));
    timer->start(30);
}

Widget::~Widget()
{
    delete timer;
    cvReleaseImage(&cameraImage0);
    cvReleaseImage(&cameraImage1);
    cvReleaseImage(&cameraImage2);
    cvReleaseImage(&cameraImage3);

    delete ui;
}

//打開或者關閉攝像頭
void Widget::on_cameraButton_clicked()
{
    //計算攝像頭個數
    int index = ui->cameraSelectBox->currentIndex();
    //檢測攝像頭開啓狀態,然後做出相反的操作
    if (VI.isDeviceSetup(index)){
        VI.stopDevice(index);

        switch (index){
        case 0:
            cameraFlag0 = false;
            ui->camera0->clear();
            break;
        case 1:
            cameraFlag1 = false;
            ui->camera1->clear();
            break;
        case 2:
            cameraFlag2 = false;
            ui->camera2->clear();
            break;
        case 3:
            cameraFlag3 = false;
            ui->camera3->clear();
            break;
        }
        ui->cameraButton->setText(tr("打開攝像頭"));
        update();
    }
    else {
        VI.setupDevice(index, _width, _height); //設置並打開攝像頭

        switch (index){
        case 0:
            cameraFlag0 = true;
            break;
        case 1:
            cameraFlag1 = true;
            break;
        case 2:
            cameraFlag2 = true;
            break;
        case 3:
            cameraFlag3 = true;
            break;
        }
        ui->cameraButton->setText(tr("關閉攝像頭"));
    }

}

void Widget::on_cameraSelectBox_activated(int index)
{
    if (VI.isDeviceSetup(index)){
        ui->cameraButton->setText(tr("關閉攝像頭"));
    }
    else ui->cameraButton->setText(tr("打開攝像頭"));
}

//攝像頭顯示的主要處理函數
void Widget::startLoopSlot()
{
    if(cameraFlag0 || cameraFlag1 || cameraFlag2 || cameraFlag3)
    {
        if (cameraFlag0){
            if (VI.isFrameNew(0)){
                showImage(0, cameraImage0);
            }
        }

        if (cameraFlag1){
            if (VI.isFrameNew(1)){
                showImage(1, cameraImage1);
            }
        }

        if (cameraFlag2){
            if (VI.isFrameNew(2)){
                showImage(2, cameraImage2);
            }
        }

        if (cameraFlag3){
            if (VI.isFrameNew(3)){
                showImage(3, cameraImage3);
            }
        }

    }
}

//顯示圖像函數
void Widget::showImage(int deviceID, IplImage *imge)
{
    VI.getPixels(deviceID, (unsigned char *)imge->imageData, false, true);
    QImage qimage = QImage((uchar *)imge->imageData, imge->width,imge->height, image_Format);
    qimage = qimage.rgbSwapped();
    switch(deviceID){
    case 0:
        ui->camera0->setPixmap(QPixmap::fromImage(qimage));
        break;
    case 1:
        ui->camera1->setPixmap(QPixmap::fromImage(qimage));
        break;
    case 2:
        ui->camera2->setPixmap(QPixmap::fromImage(qimage));
        break;
    case 3:
        ui->camera3->setPixmap(QPixmap::fromImage(qimage));
        break;
    }
}
</span>

再下來就是亮相的時刻了大笑

(啓動界面):

(四個攝像頭同時打開的情況)

(選擇打開或者關閉某一個攝像頭的情況)

ok,工程羅列完畢!

有時間再研究研究看能不能自己寫代碼吧opencv裏面內置的videoInput的屬性方法引出來,重新編譯highgui模塊,到那時使用就很方便。

文章到處結束,祝大家好運!


參考文獻:

1、關於“library in .pro file for qt”的討論

2、 《VideoInput庫 + Opencv2.3.1 + 無線攝像頭 + VC2010》

3、 《高版本Opencv內置的videoInput庫的使用方法(1)》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章