QT Creator下Basler相機二次開發+OpenCV圖像處理

本文介紹了使用QT對Basler相機(GigE接口)進行二次開發,並且把相機的圖像轉換爲OpenCV可處理的圖片格式,以供大家學習參考。

.pro文件:

INCLUDEPATH += $$PWD/include
INCLUDEPATH += $$PWD/include/opencv
INCLUDEPATH += $$PWD/include/opencv2

LIBS    += $$PWD/lib/x64/GCBase_MD_VC141_v3_1_Basler_pylon.lib
LIBS    += $$PWD/lib/x64/GenApi_MD_VC141_v3_1_Basler_pylon.lib
LIBS    += $$PWD/lib/x64/PylonBase_v6_0.lib
LIBS    += $$PWD/lib/x64/PylonC.lib
LIBS    += $$PWD/lib/x64/PylonGUI_v6_0.lib
LIBS    += $$PWD/lib/x64/PylonUtility_v6_0.lib

win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/x64/ -lopencv_world343
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/x64/ -lopencv_world343d
else:unix: LIBS += -L$$PWD/lib/x64/ -lopencv_world343

INCLUDEPATH += $$PWD/lib/x64
DEPENDPATH += $$PWD/lib/x64

.h文件

#include <QObject>
#include <pylon/PylonIncludes.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui.hpp>

#include <QImage>
#include <QTimer>
#include <QDebug>

using namespace std;
using namespace Pylon;
using namespace GenApi;
using namespace cv;

private slots:
    void onTimerGrabImage();

private:
    CInstantCamera m_basler;
    INodeMap *nodemap;//相機屬性節點
    CGrabResultPtr ptrGrabResult;
    CPylonImage pylonImage;

public:
    Mat openCvImage;//用於OpenCV圖像處理

private:
    bool m_isOpenAcquire = false; // 是否開始採集
    bool m_isOpen = false; // 是否打開攝像頭

MainWindow.cpp文件

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    camSDK = new CamSDK();
    PylonInitialize();
    connect(camSDK, &CamSDK::sigCurrentImage, [=](QImage img)
    {
        QPixmap pix = QPixmap::fromImage(img);
        ui->label->setPixmap(pix);
    });

    connect(camSDK,&CamSDK::sigCamBegin,this,&MainWindow::camBeginCtl);
    connect(camSDK,&CamSDK::sigCamStop,this,&MainWindow::camStopCtl);

    camSDK->OpenCamera();
}
void MainWindow::on_pushButton_Start_clicked()
{
    camSDK->StartAcquire();
}

void MainWindow::on_pushButton_Stop_clicked()
{
    camSDK->StopAcquire();
}

CamSDK.cpp文件:

int CamSDK::OpenCamera()
{
    try
    {
        m_basler.Attach(CTlFactory::GetInstance().CreateFirstDevice());//實例化第一個找到的設備
        m_basler.Open();
        m_isOpen = true;
//        emit sigCamBegin();

    }
    catch (GenICam::GenericException &e)
    {
        qDebug() << "OpenCamera Error" << QString(e.GetDescription());
        m_isOpen = false;
        emit sigCamStop();
        return -2;
    }
    return 0;
}

void CamSDK::deleteAll()
{
    //停止採集
    if(m_isOpenAcquire)
    {
        StopAcquire();
    }
    //關閉攝像頭
    CloseCamera();
    //關閉庫
    PylonTerminate();
}

long CamSDK::StopAcquire()
{
    m_isOpenAcquire = false;
    try
    {
        if (m_basler.IsGrabbing())
        {
            m_basler.StopGrabbing();
            emit sigCamStop();
        }
    }
    catch (GenICam::GenericException &e)
    {
        qDebug() << "StopAcquire Error:" << QString(e.GetDescription());
        return -2;
    }
    return 0;
}

int CamSDK::CloseCamera()
{
    if(!m_isOpen)
    {
        return -1;
    }
    try
    {
        if(m_basler.IsOpen())
        {
            m_basler.DetachDevice();
            m_basler.Close();
        }
    }
    catch (GenICam::GenericException &e)
    {
        qDebug() << "CloseCamera Error:" << QString(e.GetDescription());
        return -2;
    }
    return 0;
}

long CamSDK::StartAcquire()
{
    m_isOpenAcquire = true;
    try
    {
        m_basler.StartGrabbing(GrabStrategy_OneByOne);
        onTimerGrabImage();
    }
    catch (GenICam::GenericException &e)
    {
        qDebug() << "StartAcquire Error:" << QString(e.GetDescription());
        return -2;
    }
    return 0;
}

void CamSDK::onTimerGrabImage()
{
    if(m_isOpenAcquire)
    {
        QImage image;
        GrabImage(image, 5000);
        if(!image.isNull())
        {
            emit sigCurrentImage(image);
        }
        QTimer::singleShot(5, this, SLOT(onTimerGrabImage()));
    }
}

long CamSDK::GrabImage(QImage &image, unsigned int timeout)
{
    try
    {
        if (!m_basler.IsGrabbing())
        {
            StartAcquire();
        }

        m_basler.RetrieveResult(timeout, ptrGrabResult, TimeoutHandling_ThrowException);

        if(ptrGrabResult == NULL)
        {
            return -5;
        }
        if (ptrGrabResult->GrabSucceeded())
        {
            qDebug() << "what: ptrGrabResult GrabSucceeded";
            if (!ptrGrabResult.IsValid())
            {
                OutputDebugString(L"GrabResult not Valid Error\n"); return -1;
            }

            // 新建pylon ImageFormatConverter對象
            CImageFormatConverter formatConverter;
            // 創建一個Pylonlmage後續將用來創建OpenCV images
            formatConverter.OutputPixelFormat = PixelType_BGR8packed;

            //將抓取的緩衝數據轉化成pylon image.
            formatConverter.Convert(pylonImage, ptrGrabResult);

            // 將 pylon image轉成OpenCV image.
            openCvImage = Mat(static_cast<int>(ptrGrabResult->GetHeight()), static_cast<int>(ptrGrabResult->GetWidth()), CV_8UC3, static_cast<uint8_t *>(pylonImage.GetBuffer()));

            EPixelType pixelType = ptrGrabResult->GetPixelType();
            switch (pixelType)
            {
                case PixelType_Mono8:
                {
                    CopyToImage(ptrGrabResult, image);//轉爲QImage
                }
                break;
                case PixelType_BayerRG8:
                {
                    qDebug() << "what: PixelType_BayerRG8";
                }
                break;
                default:
                    qDebug() << "what: default"; break;
            }
        }
        else
        {
            qDebug() << "Grab Error!!!";
            return -3;
        }
    }
    catch (GenICam::GenericException &e)
    {
        qDebug() << "GrabImage Error:" << QString(e.GetDescription());
        return -2;
    }
    return 0;
}

void CamSDK::CopyToImage(CGrabResultPtr pInBuffer, QImage &OutImage)
{
    try
    {
        uchar* buff = static_cast<uchar*>(pInBuffer->GetBuffer());
        int nHeight = static_cast<int>(pInBuffer->GetHeight());
        int nWidth = static_cast<int>(pInBuffer->GetWidth());

        QImage imgBuff(buff, nWidth, nHeight, QImage::Format_Indexed8);
        OutImage = imgBuff;
        if(pInBuffer->GetPixelType() == PixelType_Mono8)
        {
            uchar* pCursor = OutImage.bits();
            if ( OutImage.bytesPerLine() != nWidth )
            {
                for ( int y=0; y<nHeight; ++y )
                {
                    pCursor = OutImage.scanLine( y );
                    for ( int x=0; x<nWidth; ++x )
                    {
                        *pCursor =* buff;
                        ++pCursor;
                        ++buff;
                    }
                }
            }
            else
            {
                memcpy( OutImage.bits(), buff, static_cast<size_t>(nWidth * nHeight));
            }
        }
    }
    catch (GenICam::GenericException &e)
    {
        qDebug() << "CopyToImage Error:" << QString(e.GetDescription());
    }
}

在學習的過程中總結出以下幾點:

  1. 不要用MinGW,用MSVC編譯 。
  2. SetCamera(Type_Basler_GevSCPSPacketSize, size);
    不可在讀取圖像的同時運行該屬性設置。
  3. 主程序也要加以下內容,不光是自己創建的類中要加。
    #include <opencv2/core.hpp>
    #include <opencv2/highgui.hpp>
    using namespace cv;
  4. 以下內容不可缺少:
    formatConverter.OutputPixelFormat = PixelType_BGR8packed;

> 參考博客:

https://msd.misuland.com/pd/2878646270447061120
[BASLER+OpenCV]:
https://www.cnblogs.com/star91/p/6747946.html
[QT+OpenCV]:
https://baijiahao.baidu.com/s?id=1648921394348848148&wfr=spider&for=pc
https://blog.csdn.net/zong596568821xp/article/details/78819275
[Qt+BASLER+OpenCV]:
https://blog.csdn.net/zong596568821xp/article/details/78790363

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