乐趣区

关于qt:视觉实战案例Qt调用Basler网口工业相机SDK实现采图和相机参数设置

1、采图 UI 显示

2、硬件连贯和 IP 配置

2.1 外触发硬件接线


依据相机接线图,连贯相机的电源的触发信号输出;

2.2 IP 配置

Gige 网口相机须要电脑网卡和相机在同一 ip 段内,反对动静、动态等形式配置 IP,关上 Pylon IP Configurator 来匹配 IP,如下

3、代码实现

根本采图性能 Balser 都有对应的 Demo 进行参考,这里只截取相机采图和局部参数设置性能演示。

balser_gigeCamera.h

#ifndef BALSER_GIGECAMERA_H
#define BALSER_GIGECAMERA_H
/***************************
* @projectName   camera_test
* @brief         Basler 相机图像采集及参数设置性能;* @author        Alaric
* @date          2018-11-04
**************************/

#include <QImage>
#include "balser_gigecamera_global.h"
#include <QObject>

#include <pylon/PylonIncludes.h>
#include <pylon/BaslerUniversalInstantCamera.h>
#include <pylon/_BaslerUniversalCameraParams.h>
#include <QMutex>

using namespace std;
using namespace Pylon;
using namespace GenApi;
using namespace Basler_UniversalCameraParams;

class BALSER_GIGECAMERASHARED_EXPORT Balser_GigeCamera : public QObject, public CImageEventHandler
{
    Q_OBJECT
public:
    Balser_GigeCamera(QObject *parent = nullptr);
    ~Balser_GigeCamera();
    
    enum BaslerCamera_Type{
        Type_Basler_Freerun, // 设置相机的内触发
        Type_Basler_Line1, // 设置相机的外触发
        Type_Basler_ExposureTimeAbs, // 设置相机的曝光工夫
        Type_Basler_GainRaw, // 设置相机的增益
        Type_Basler_AcquisitionFrameRateAbs, // 设置相机的频率
        Type_Basler_Width, // 图片的宽度
        Type_Basler_Height, // 图片的高度
        Type_Basler_LineSource, // 灯的触发信号
    };
    
    void initCamera();                   // 初始化相机
    void OpenCamera();                   // 关上相机
    void CloseCamera();                   // 敞开相机
    void deleteAll();                    // 删除相机
    
    int getExposureTime();                // 取得曝光工夫
    void setExposureTime(int time);       // 设置曝光工夫
    int getGain();                        // 取得增益
    void setGain(int value);              // 设置增益
    void setFrameRate(int value);         // 设置帧率
    int getFrameRate();                   // 取得帧率
    void OneKeyAutoExTime();              // 一键主动曝光
    void SetCamera(Balser_GigeCamera::BaslerCamera_Type index, int tmpValue = 0); // 设置各种参数
    int GetCamera(Balser_GigeCamera::BaslerCamera_Type index); // 获取各种参数
    void AutoExposureOnce(CBaslerUniversalInstantCamera& camera);      // 主动曝光
    
    void StartAcquire();  // 开始采集
    void StopAcquire();   // 完结采集
    void StartSnap();     // 抓图
    
    bool GrabOnLine_Signal;     // 实时采图信号
    
signals:
    void canShowImg(QImage img);         // 发送图像数据
    
public slots:
    void WorkTypeSignal(int work_type);         // 接管图像处理信号,0 为 Once,1 为 Online;
private:
    CBaslerUniversalInstantCamera m_basler;
    CGrabResultPtr m_ptrGrabResult;
    CImageFormatConverter m_formatConverter;//Basler 图片格式转换类
    CPylonImage pylonImage; //Basler 图像格式
    QMutex m_mutexLock;
    
    int TestImg_WorkType = -1;          // 图像处理形式,默认 - 1 为不解决,0 为 Once,1 为 Online;QImage CopyImgToQImage(CGrabResultPtr ptrGrabResult);
    
protected:
    virtual void OnImageGrabbed(CInstantCamera &camera, const CGrabResultPtr &grabResult);
};

#endif // BALSER_GIGECAMERA_H

这里 balser 采集到的 BYTE 格局的图像数据依照通道数转换成 QImage 格局,最初发送给 UI 线程进行显示。

balser_gigecamera.cpp

#include "balser_gigecamera.h"
#include <QDebug>

Balser_GigeCamera::Balser_GigeCamera(QObject *parent) : QObject(parent)
{ }

Balser_GigeCamera::~Balser_GigeCamera()
{ }

void Balser_GigeCamera::initCamera()
{PylonInitialize();
    
    m_basler.RegisterImageEventHandler(this, RegistrationMode_Append, Cleanup_Delete);
    m_basler.Attach(CTlFactory::GetInstance().CreateFirstDevice(),Cleanup_Delete);
    qDebug()<<"Using device" << m_basler.GetDeviceInfo().GetModelName()<<endl;
    m_basler.Open();
    if (!m_basler.IsOpen() || m_basler.IsGrabbing())
    {qDebug()<<"camera open failed"<<endl;
        return;
    }
}

void Balser_GigeCamera::CloseCamera()
{if(m_basler.IsOpen()) {m_basler.DetachDevice();
        m_basler.Close();
        m_basler.DestroyDevice();
        m_ptrGrabResult.Release();}
}

void Balser_GigeCamera::deleteAll()
{
    // 进行采集
    if(GrabOnLine_Signal) {StopAcquire();
    }
    // 敞开摄像头
    try
    {CloseCamera();
        m_basler.DeregisterImageEventHandler(this);
        
        // 敞开库
        qDebug() << "SBaslerCameraControl deleteAll: PylonTerminate" ;
        PylonTerminate();}
    catch (const Pylon::GenericException& e)
    {qDebug() << e.what();}
}

int Balser_GigeCamera::getExposureTime()
{return GetCamera(Type_Basler_ExposureTimeAbs);
}

void Balser_GigeCamera::setExposureTime(int time)
{SetCamera(Type_Basler_ExposureTimeAbs, time);
}

void Balser_GigeCamera::setGain(int value)
{SetCamera(Type_Basler_GainRaw, value);
}

int Balser_GigeCamera::getGain()
{return GetCamera(Type_Basler_GainRaw);
}

int Balser_GigeCamera::getFrameRate()
{return GetCamera(Type_Basler_AcquisitionFrameRateAbs);
}

void Balser_GigeCamera::setFrameRate(int value)
{SetCamera(Type_Basler_AcquisitionFrameRateAbs, value);
}

void Balser_GigeCamera::OneKeyAutoExTime()
{AutoExposureOnce(m_basler);
}

void Balser_GigeCamera::SetCamera(Balser_GigeCamera::BaslerCamera_Type index, int tmpValue)
{INodeMap &cameraNodeMap = m_basler.GetNodeMap();
    switch (index) {
    case Type_Basler_Freerun: {CEnumerationPtr  ptrTriggerSel = cameraNodeMap.GetNode ("TriggerSelector");
        ptrTriggerSel->FromString("FrameStart");
        CEnumerationPtr  ptrTrigger  = cameraNodeMap.GetNode ("TriggerMode");
#ifdef Real_Freerun
        ptrTrigger->SetIntValue(0);
#else //Software
        ptrTrigger->SetIntValue(1);
        CEnumerationPtr  ptrTriggerSource = cameraNodeMap.GetNode ("TriggerSource");
        ptrTriggerSource->FromString("Software");
#endif
    } break;
    case Type_Basler_Line1: {CEnumerationPtr  ptrTriggerSel = cameraNodeMap.GetNode ("TriggerSelector");
        ptrTriggerSel->FromString("FrameStart");
        CEnumerationPtr  ptrTrigger  = cameraNodeMap.GetNode ("TriggerMode");
        ptrTrigger->SetIntValue(1);
        CEnumerationPtr  ptrTriggerSource = cameraNodeMap.GetNode ("TriggerSource");
        ptrTriggerSource->FromString("Line1");
    } break;
    case Type_Basler_ExposureTimeAbs: {const CFloatPtr exposureTime = cameraNodeMap.GetNode("ExposureTimeAbs");
        exposureTime->SetValue(tmpValue);
    } break;
    case Type_Basler_GainRaw: {const CIntegerPtr cameraGen = cameraNodeMap.GetNode("GainRaw");
        cameraGen->SetValue(tmpValue);
    } break;
    case Type_Basler_AcquisitionFrameRateAbs: {const CBooleanPtr frameRate = cameraNodeMap.GetNode("AcquisitionFrameRateEnable");
        frameRate->SetValue(TRUE);
        const CFloatPtr frameRateABS = cameraNodeMap.GetNode("AcquisitionFrameRateAbs");
        frameRateABS->SetValue(tmpValue);
    } break;
    case Type_Basler_Width: {const CIntegerPtr widthPic = cameraNodeMap.GetNode("Width");
        widthPic->SetValue(tmpValue);
    } break;
    case Type_Basler_Height: {const CIntegerPtr heightPic = cameraNodeMap.GetNode("Height");
        heightPic->SetValue(tmpValue);
    } break;
    case Type_Basler_LineSource: {CEnumerationPtr  ptrLineSource = cameraNodeMap.GetNode ("LineSource");
        ptrLineSource->SetIntValue(2);
    } break;
    default:
        break;
    }
}

int Balser_GigeCamera::GetCamera(Balser_GigeCamera::BaslerCamera_Type index)
{INodeMap &cameraNodeMap = m_basler.GetNodeMap();
    switch (index) {
    case Type_Basler_ExposureTimeAbs: {const CFloatPtr exposureTime = cameraNodeMap.GetNode("ExposureTimeAbs");
        return exposureTime->GetValue();} break;
    case Type_Basler_GainRaw: {const CIntegerPtr cameraGen = cameraNodeMap.GetNode("GainRaw");
        return cameraGen->GetValue();} break;
    case Type_Basler_AcquisitionFrameRateAbs: {const CBooleanPtr frameRate = cameraNodeMap.GetNode("AcquisitionFrameRateEnable");
        frameRate->SetValue(TRUE);
        const CFloatPtr frameRateABS = cameraNodeMap.GetNode("AcquisitionFrameRateAbs");
        return frameRateABS->GetValue();} break;
    case Type_Basler_Width: {const CIntegerPtr widthPic = cameraNodeMap.GetNode("Width");
        return widthPic->GetValue();} break;
    case Type_Basler_Height: {const CIntegerPtr heightPic = cameraNodeMap.GetNode("Height");
        return heightPic->GetValue();} break;
    default:
        return -1;
        break;
    }
}

void Balser_GigeCamera::OnImageGrabbed(CInstantCamera &camera, const CGrabResultPtr &grabResult)
{m_mutexLock.lock();
    qDebug() <<"Capturest"<<endl;
    if (grabResult->GrabSucceeded())
    {
        m_ptrGrabResult = grabResult;// 将捕捉到的图像传递进来
        qDebug() <<"Captureok"<<endl;
        QImage CurrentImg;
        CurrentImg = CopyImgToQImage(m_ptrGrabResult);
        if(TestImg_WorkType == 1)
        {emit canShowImg(CurrentImg);
            //            startImgProcess(CurrentImg);
            qDebug() <<"Captureok"<<endl;}
        else{emit canShowImg(CurrentImg);
        }
    }
    
    m_mutexLock.unlock();}

void Balser_GigeCamera::StartAcquire()
{if ( !m_basler.IsGrabbing() ){qDebug()<<"grabstart"<<endl;
        GrabOnLine_Signal = true;
        m_basler.StartGrabbing(GrabStrategy_LatestImageOnly,GrabLoop_ProvidedByInstantCamera);
    }
    else {qDebug()<<"error"<<endl;
    }
}

void Balser_GigeCamera::StartSnap()
{m_basler.StartGrabbing(1);
    CBaslerUniversalGrabResultPtr ptrGrabResult;
    m_basler.RetrieveResult(5000, ptrGrabResult, TimeoutHandling_ThrowException);
    if (ptrGrabResult->GrabSucceeded())
    {qDebug()<<"snapok"<<endl;
        QImage CurrentImg = CopyImgToQImage(ptrGrabResult);
        emit canShowImg(CurrentImg);
        if(TestImg_WorkType == 0){//            startImgProcess(CurrentImg);
            TestImg_WorkType = -1;
        }
    }
}

void Balser_GigeCamera::StopAcquire()
{if ( m_basler.IsGrabbing()){
        GrabOnLine_Signal = false;
        m_basler.StopGrabbing();  // 进行抓取图像}
}

void Balser_GigeCamera::AutoExposureOnce(CBaslerUniversalInstantCamera& camera)
{if ( !camera.ExposureAuto.IsWritable())
    {
        cout << "The camera does not support Exposure Auto." << endl << endl;
        return;
    }
    
    camera.ExposureAuto.SetValue(ExposureAuto_Once);
    int n = 0;
    while (camera.ExposureAuto.GetValue() != ExposureAuto_Off)
    {
        ++n;
        
        //For demonstration purposes only. Wait until the image is shown.
        WaitObject::Sleep(100);
        
        //Make sure the loop is exited.
        if (n > 100)
        {throw TIMEOUT_EXCEPTION( "The adjustment of auto exposure did not finish.");
        }
    }
}

void Balser_GigeCamera::WorkTypeSignal(int work_type)
{TestImg_WorkType = work_type;}

QImage Balser_GigeCamera::CopyImgToQImage(CGrabResultPtr ptrGrabResult)
{
    QImage Qimg;
    // 格局转换
    m_formatConverter.Convert(pylonImage, ptrGrabResult);
    uchar * din = (uchar *)(pylonImage.GetBuffer()); // 数据指针
    
    // 单通道 Momo
    if(IsMono(pylonImage.GetPixelType()))
    {qDebug()<<"黑白图像";
        Qimg = QImage(din, ptrGrabResult->GetWidth(), ptrGrabResult->GetHeight(), QImage::Format_Indexed8);
    }
    else
    {
        // 此处能够依据相机的格局获取特定格局的彩色图像
        if(IsRGB(pylonImage.GetPixelType()))
        {Qimg = QImage(din, ptrGrabResult->GetWidth(), ptrGrabResult->GetHeight(), QImage::Format_RGB888);
        }
    }
    
    return Qimg;
}

4、源码下载

相机采图及相机设置局部封装成动静库,能够在 UI 线程调用相机类来实现相机的加载,采图及参数设置操作。
源码下载:https://download.csdn.net/dow…

退出移动版