Basler 多个网口相机出图(SDK版)

时间:2024-05-23 14:03:47

利用basler相机自带的SDK进行多相机出图,为了便于理解,特将多相机出图部分的程序拷贝出来,在win32控制台环境下,配合OpenCV进行出图测试。

运行环境:VS2013、OpenCV2410

OpenCV的安装流程可参考其它的文档

此外需要安装basler相机的驱动程序,特别地,需要选择开发者模式(pylon5.0)。

一切就绪后,新建win32控制台程序,并添加basler目录,具体如下:

1.在“配置属性”->“C/C++”的附加包含目录中,添加 $(PYLON_DEV_DIR)\include

2.在“配置属性”->“链接器”的附加目录中,添加 $(PYLON_DEV_DIR)\lib\win32

特别地,选择win32的库,还是x64的库,需要看模拟计算机的类型(我的电脑是x64,但是VS2013是32位,调试器也是win32,所以我使用win32的库)。

我连接的是两个相机,可以在程序中测试两个相机的抓图效果。

特别地,网口相机需要进行IP配置,配置的方式比较简单,可以参考其它文档,并用basler自带的IP Configurator来进行IP设置和相机状态检测。

Basler 多个网口相机出图(SDK版)

win32控制台主程序如下:

-------------------------------------------------------

#include <iostream>
#include <fstream>
#include <windows.h>
#include <opencv2/opencv.hpp>
#include <pylon/PylonIncludes.h>

using namespace Pylon;

static const int imagesGrabNum = 10;//处理的帧数
static const int maxCameras = 6;//限制相机个数
#define CAMEID1 21686511//相机ID
#define CAMEID2 21687637
static const int IDN = 1;//相机序号,0 1 2 ...

int main()
{

    Pylon::PylonInitialize();

    try
    {
        CTlFactory &tlFactory = CTlFactory::GetInstance();//
        DeviceInfoList_t devices;
        if (tlFactory.EnumerateDevices(devices) == 0)
        {
            throw RUNTIME_EXCEPTION("没有检测到可用相机!");
        }
        CInstantCameraArray cameras(MIN(devices.size(), maxCameras));
        for (int i = 0; i < (int)cameras.GetSize(); i++)
        {
            cameras[i].Attach(tlFactory.CreateDevice(devices[i]));
            std::cout << "第 " << i + 1 << " 个相机的型号为:" <<cameras[i].GetDeviceInfo().GetModelName()<<" ID为:"<< cameras[i].GetDeviceInfo().GetSerialNumber() << std::endl;
        }
        std::cout << std::endl;
        cameras[IDN].StartGrabbing();//相机开始抓图,序号为IDN的相机
        CGrabResultPtr ptrGrabResult;//存储抓图结果信息
        for (int i = 0; i < imagesGrabNum ; i++)
        {
            cameras[IDN].RetrieveResult(5000, ptrGrabResult, TimeoutHandling_ThrowException);//将抓取后的数据存储在ptrGrabResult中
            int cameraContextValue = ptrGrabResult->GetCameraContext();//相机序号
            std::cout << i+1<<"----------相机ID:" << cameras[cameraContextValue].GetDeviceInfo().GetSerialNumber() << "----------" << std::endl;
            std::cout << "图像抓取状态:" << (ptrGrabResult->GrabSucceeded() ? "成功" : "失败") << std::endl;
            std::cout << "相机水平分辨率:" << ptrGrabResult->GetWidth() << ";相机垂直分辨率:" << ptrGrabResult->GetHeight() << std::endl;
            unsigned char *pImageBuffer = (unsigned char *)ptrGrabResult->GetBuffer();
            std::cout << "图像第一个像素点的灰度值为:" << (int)pImageBuffer[0] << std::endl;
            std::cout << std::endl;
#if 1//测试buffer
            cv::Mat img = cv::Mat((int)ptrGrabResult->GetHeight(), (int)ptrGrabResult->GetWidth(), CV_8UC1);
            for (int i = 0; i < (int)ptrGrabResult->GetHeight(); i++)
            {
                for (int j = 0; j < (int)ptrGrabResult->GetWidth(); j++)
                {
                    img.at<uchar>(i, j) = pImageBuffer[i*(int)ptrGrabResult->GetWidth() + j];
                }
            }
#endif
        }
        cameras[IDN].StopGrabbing();
    }
    catch (GenericException &e)
    {
        std::cerr << "抓图出现异常!" << std::endl << e.GetDescription() << std::endl;
    }

    std::cout << "程序处理完毕,按任意键退出程序..." << std::endl;
    while (std::cin.get())
    {
        break;
    }
    PylonTerminate();
    
    return 0;
}

---------------------------------

测试效果如下:

Basler 多个网口相机出图(SDK版)

特别地,对上述程序进行适当的修改,可以进行相机的同步出图,以及出图效果测试。

---------------------------------------------------------

//2018.07.26 更新

今天补充一下在程序中设置相机的曝光参数(增益参数类似,再次不作介绍)。

最好不要随便设置增益,因为噪音对增益很敏感,一般设置相机的曝光即可。

设置曝光参数,需要用到对象函数 .ExposureTimeAbs.SetValue(value);

以下是利用网口相机进行相机曝光设置的简单代码(借鉴SDK):

-------------------

#include <iostream>
#include <fstream>
#include <windows.h>
#include <opencv2/opencv.hpp>
#include <pylon/PylonIncludes.h>
#include <pylon/gige/BaslerGigEInstantCamera.h>
#include <pylon/gige/_BaslerGigECameraParams.h>
#include <pylon/PylonGUI.h>

using namespace std;
using namespace Pylon;
using namespace Basler_GigECameraParams;

typedef Pylon::CBaslerGigEInstantCamera Camera_t;
typedef Camera_t::GrabResultPtr_t GrabResultPtr_t;


int main()
{
    int exitCode = 0;
    PylonInitialize();
    
    
    try
    {
        //only look for cameras supported by Camera_t
        CDeviceInfo info;
        info.SetDeviceClass(Camera_t::DeviceClass());

        Camera_t camera(CTlFactory::GetInstance().CreateDevice(info));//如何区别不同的相机?
        std::cout << "所使用的相机SN号为:" << camera.GetDeviceInfo().GetSerialNumber() << std::endl;

        //auto function do not require grabbing!
        camera.RegisterConfiguration(new CAcquireContinuousConfiguration, RegistrationMode_ReplaceAll, Cleanup_Delete);

        
        //open camera
        camera.Open();

        //turn test image off
        camera.TestImageSelector = TestImageSelector_Off;

        //Only area scan cameras support auto functions!
        if (camera.DeviceScanType.GetValue() == DeviceScanType_Areascan)//面阵相机
        {

#if 1    //程控测试
            std::cout << "程控测试。需要终止请按 回车 键..." << std::endl;
            GrabResultPtr_t ptrGrabResult;
            int n = 20;
            while (--n>0)
            {
                camera.ExposureTimeAbs.SetValue(n*10000);
                camera.GrabOne(5000, ptrGrabResult);
#ifdef PYLON_WIN_BUILD
                Pylon::DisplayImage(1, ptrGrabResult);//界面刷新不同曝光值的出图效果
#endif
                WaitObject::Sleep(1);
            }


#endif
            
        }
        else
        {
            std::cerr << "只有面阵相机才支持自动功能!" << std::endl;
        }

        //close camera
        camera.Close();
    }
    catch (const TimeoutException &e)
    {
        std::cerr << e.GetDescription() << std::endl;
        std::cin.get();
        return 0;
    }
    catch (const GenericException &e)
    {
        std::cerr << e.GetDescription() << std::endl;
        std::cin.get();
        return 0;
    }

    PylonTerminate();
    
    std::cin.get();
    return 0;
}

-------------------