Linux系统配置Basler相机驱动(软件触发和硬件触发)OpenCV格式转换

Author Avatar
WoodyXiong 11月 20, 2017
  • 在其它设备中阅读本文章

由于学校实验室需要用到Basler相机,然而网上Basler相机的说明文档是全英文的,对新手不太友好,而且国内关于Basler的硬件触发代码没有。在研究了Basler相机的SDK之后总结出了触发的驱动,还有照片与OpenCV格式转换的代码,希望可以对你们有帮助。

测试环境

  • Ubuntu14.04
  • Pylon5.0.5
  • OpenCV3.4.14
  • 相机型号acA1600-60gm/acA2500-14gm

使用步骤

下载Basler相机的SDK(pylon)

Pylon下载网站下载对应的SDK,此处我下载的是Pylon5.0.5

安装pylon

下载的文件名为pylonSDK-5.0.5.9000-x86_64.tar.gz,将这个文件夹随便解压到一个地方。

进入解压的文件,打开终端,此时的目录为 解压的目录/pylon-5.0.5.9000-x86_64

输入命令,将SDK解压到opt目录下面

 sudo tar -C /opt -xzf pylonSDK*.tar.gz

至此,Basler的SDK(Pylon)安装完成

软件触发

前期准备

将摄像机的电源线插上,电源线的制作方法详见Basler相机的说明PDF

网线也插上,用/opt/pylon5/ipconfiguretion将相机的ip和主机的ip设置在同一网段内

/opt/pylon5/bin/pylon查看相机是否连接成功,是否可以拍摄照片

代码编写

softwareTrigger.cpp源文件

软件触发的源文件,用死循环一直循环取图像,包含拍照的图像转成OpenCV的Mat矩阵

//#include <opencv2/opencv.hpp>
#include <pylon/PylonIncludes.h>
using namespace Pylon;
using namespace GenApi;
//using namespace cv;
using namespace std;

int main(){
    try{
        PylonInitialize();          //初始化相机
        CInstantCamera camera(CTlFactory::GetInstance().CreateFirstDevice());

        cout << "Using device " << camera.GetDeviceInfo().GetModelName() << endl;
        camera.Open();

        camera.StartGrabbing(GrabStrategy_LatestImages);

        CGrabResultPtr ptrGrabResult;   
        CPylonImage image;           //图片结构体

        while(1){
            camera.RetrieveResult(5000, ptrGrabResult, TimeoutHandling_ThrowException);

            CImageFormatConverter fc;
            fc.OutputPixelFormat = PixelType_BGR8packed;
            if (ptrGrabResult->GrabSucceeded())
            {
                cout << "Please wait. Images are grabbed." << endl;
                cout << ptrGrabResult->GetWidth()<<endl;
                cout << ptrGrabResult->GetHeight()<<endl;

                /* 将相机拍的照片转换成OpenCV的Mat矩阵
                // fc.Convert(image, ptrGrabResult);//转换
                // int imRows = ptrGrabResult->GetWidth() / 3;
                // int imCols = ptrGrabResult->GetHeight() / 3;
                // Mat cv_img = Mat(ptrGrabResult->GetHeight(), ptrGrabResult->GetWidth(), CV_8UC3, (uint8_t*)image.GetBuffer());
                // imshow("OpenCVimg",cv_img);
                // waitKey(0);
                */
            }
        }
        camera.Close();//一定要记得关闭,不然重新连接连不上相机
    }
    catch (const GenericException &e)
    {
        // Error handling.
        cerr << "An exception occurred." << endl
        << e.GetDescription() << endl;
    }
    return 0;
}

制作makefile文件,将库引入进来

# Makefile for Basler pylon sample program
.PHONY: all clean

# The program to build
NAME       := SoftwareTrigger

# Installation directories for pylon
PYLON_ROOT ?= /opt/pylon5

# Build tools and flags
LD         := $(CXX)
CPPFLAGS   := $(shell $(PYLON_ROOT)/bin/pylon-config --cflags)
CXXFLAGS   := #e.g., CXXFLAGS=-g -O0 for debugging
LDFLAGS    := $(shell $(PYLON_ROOT)/bin/pylon-config --libs-rpath)
LDLIBS     := $(shell $(PYLON_ROOT)/bin/pylon-config --libs)

# Rules for building
all: $(NAME)

$(NAME): $(NAME).o
    $(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS)

$(NAME).o: $(NAME).cpp
    $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<

clean:
    $(RM) $(NAME).o $(NAME)

运行结果

robot@robot:~/桌面/ubuntu/Trigger/SoftwareTrigger$ ./SoftwareTrigger
Using device acA1600-60gm
Please wait. Images are grabbed.
1600
1200
Please wait. Images are grabbed.
1600
1200
Please wait. Images are grabbed.
1600
1200
Please wait. Images are grabbed.
1600
1200
Please wait. Images are grabbed.
1600
1200
Please wait. Images are grabbed.
1600
1200

硬件触发

前期准备

将摄像机的电源线插上,电源线的制作方法详见Basler相机的说明PDF

网线也插上,用/opt/pylon5/ipconfiguretion将相机的ip和主机的ip设置在同一网段内

/opt/pylon5/bin/pylon查看相机是否连接成功,是否可以拍摄照片

代码编写

按照官方的介绍,需要我们自己定义硬件触发配置的头文件,在头文件定义是哪个线触发,上升沿触发还是下降沿触发。

hardwaretriggerconfiguration.h

#ifndef HARDWARETRIGGERCONFIGURATION_H
#define HARDWARETRIGGERCONFIGURATION_H
#include <pylon/Platform.h>

#ifdef _MSC_VER
#   pragma pack(push, PYLON_PACKING)
#endif /* _MSC_VER */

#include <pylon/InstantCamera.h>

namespace Pylon
{
    /** \addtogroup Pylon_InstantCameraApiGeneric
     * @{
     */

    /*!
    \class  CSoftwareTriggerConfiguration
    \brief  Changes the configuration of the camera so that the acquisition of frames is triggered by software trigger.
            Use together with CInstantCamera::WaitForFrameTriggerReady() and CInstantCamera::ExecuteSoftwareTrigger().

        The %CSoftwareTriggerConfiguration is provided as header-only file.
        The code can be copied and modified for creating own configuration classes.
    */
    class CHardwareTriggerConfiguration : public CConfigurationEventHandler
    {
    public:
        /// Apply software trigger configuration.
        static void ApplyConfiguration( GENAPI_NAMESPACE::INodeMap& nodemap)
        {
            using namespace GENAPI_NAMESPACE;

            // Disable all trigger types except the trigger type used for triggering the acquisition of
            // frames.
            {
                // Get required enumerations.
                CEnumerationPtr triggerSelector( nodemap.GetNode("TriggerSelector"));
                CEnumerationPtr triggerMode( nodemap.GetNode("TriggerMode"));

                // Check the available camera trigger mode(s) to select the appropriate one: acquisition start trigger mode
                // (used by older cameras, i.e. for cameras supporting only the legacy image acquisition control mode;
                // do not confuse with acquisition start command) or frame start trigger mode
                // (used by newer cameras, i.e. for cameras using the standard image acquisition control mode;
                // equivalent to the acquisition start trigger mode in the legacy image acquisition control mode).
                String_t triggerName( "FrameStart");
                if ( !IsAvailable( triggerSelector->GetEntryByName(triggerName)))
                {
                    triggerName = "AcquisitionStart";
                    if ( !IsAvailable( triggerSelector->GetEntryByName(triggerName)))
                    {
                        throw RUNTIME_EXCEPTION( "Could not select trigger. Neither FrameStart nor AcquisitionStart is available.");
                    }
                }

                // Get all enumeration entries of trigger selector.
                GENAPI_NAMESPACE::NodeList_t triggerSelectorEntries;
                triggerSelector->GetEntries( triggerSelectorEntries );

                // Turn trigger mode off for all trigger selector entries except for the frame trigger given by triggerName.
                for ( GENAPI_NAMESPACE::NodeList_t::iterator it = triggerSelectorEntries.begin(); it != triggerSelectorEntries.end(); ++it)
                {
                    // Set trigger mode to off if the trigger is available.
                    GENAPI_NAMESPACE::CEnumEntryPtr pEntry(*it);
                    if ( IsAvailable( pEntry))
                    {
                        String_t triggerNameOfEntry( pEntry->GetSymbolic());
                        triggerSelector->FromString( triggerNameOfEntry);
                        if ( triggerName == triggerNameOfEntry)
                        {
                            // Activate trigger.
                            triggerMode->FromString( "On");

                            // The trigger source must be set to 'Software'.
//                            CEnumerationPtr(nodemap.GetNode("TriggerSource"))->FromString("Software");

                            //// Alternative hardware trigger configuration:
                            //// This configuration can be copied and modified to create a hardware trigger configuration.
                            //// Remove setting the 'TriggerSource' to 'Software' (see above) and
                            //// use the commented lines as a starting point.
                            //// The camera user's manual contains more information about available configurations.
                            //// The Basler pylon Viewer tool can be used to test the selected settings first.

                            //// The trigger source must be set to the trigger input, e.g. 'Line1'.
                            CEnumerationPtr(nodemap.GetNode("TriggerSource"))->FromString("Line1");

                            ////The trigger activation must be set to e.g. 'RisingEdge'.
                            CEnumerationPtr(nodemap.GetNode("TriggerActivation"))->FromString("RisingEdge");//上升延触发
                            CEnumerationPtr(nodemap.GetNode("TriggerActivation"))->FromString("FallingEdge");//下降延触发
                        }
                        else
                        {
                            triggerMode->FromString( "Off");
                        }
                    }
                }
                // Finally select the frame trigger type (resp. acquisition start type
                // for older cameras). Issuing a software trigger will now trigger
                // the acquisition of a frame.
                triggerSelector->FromString(triggerName);
            }


            //Set acquisition mode to "continuous"
            CEnumerationPtr(nodemap.GetNode("AcquisitionMode"))->FromString("Continuous");
        }

        //Set basic camera settings.
        virtual void OnOpened( CInstantCamera& camera)
        {
            try
            {
                ApplyConfiguration( camera.GetNodeMap());
            }
            catch (const GenericException& e)
            {
                throw RUNTIME_EXCEPTION( "Could not apply configuration. Pylon::GenericException caught in OnOpened method msg=%hs", e.what());
            }
            catch (const std::exception& e)
            {
                throw RUNTIME_EXCEPTION( "Could not apply configuration. std::exception caught in OnOpened method msg=%hs", e.what());
            }
            catch (...)
            {
                throw RUNTIME_EXCEPTION( "Could not apply configuration. Unknown exception caught in OnOpened method.");
            }
        }
    };

    /**
     * @}
     */
}

#ifdef _MSC_VER
#   pragma pack(pop)
#endif /* _MSC_VER */


#endif // HARDWARETRIGGERCONFIGURATION_H

HardwareTrigger.cpp

#include <pylon/PylonIncludes.h>
#include "hardwaretriggerconfiguration.h"
using namespace Pylon;
using namespace GenApi;
using namespace std;

int main(){
    // The exit code of the sample application.
    int exitCode = 0;

    // Before using any pylon methods, the pylon runtime must be initialized.
    PylonInitialize();

    try
    {
        // This smart pointer will receive the grab result data.
        CGrabResultPtr ptrGrabResult;

        // Create an instant camera object for the camera device found first.
        CInstantCamera camera( CTlFactory::GetInstance().CreateFirstDevice());

        // Register the standard configuration event handler for enabling software triggering.
        // The software trigger configuration handler replaces the default configuration
        // as all currently registered configuration handlers are removed by setting the registration mode to RegistrationMode_ReplaceAll.
        camera.RegisterConfiguration( new CHardwareTriggerConfiguration, RegistrationMode_ReplaceAll, Cleanup_Delete);

        // For demonstration purposes only, add sample configuration event handlers to print out information
        // about camera use and image grabbing.
//        camera.RegisterConfiguration( new CConfigurationEventPrinter, RegistrationMode_Append, Cleanup_Delete);
//        camera.RegisterImageEventHandler( new CImageEventPrinter, RegistrationMode_Append, Cleanup_Delete);

        // Print the model name of the camera.
        cout << "Using device " << camera.GetDeviceInfo().GetModelName() << endl;

        // The MaxNumBuffer parameter can be used to control the count of buffers
        // allocated for grabbing. The default value of this parameter is 10.
        camera.MaxNumBuffer = 10;

        // Open the camera.
        camera.Open();

        camera.StartGrabbing(GrabStrategy_LatestImages);
        CPylonImage image;

        while(1){
            //第一个参数是两次触发间隔的时间
            camera.RetrieveResult(50000, ptrGrabResult, TimeoutHandling_ThrowException);

            CImageFormatConverter fc;
            fc.OutputPixelFormat = PixelType_BGR8packed;
            if (ptrGrabResult->GrabSucceeded())
            {
                cout << "Please wait. Images are grabbed." << endl;
                cout << ptrGrabResult->GetWidth()<<endl;
                cout << ptrGrabResult->GetHeight()<<endl;

                // fc.Convert(image, ptrGrabResult);//转换
                // int imRows = ptrGrabResult->GetWidth() / 3;
                // int imCols = ptrGrabResult->GetHeight() / 3;
                // Mat cv_img = Mat(ptrGrabResult->GetHeight(), ptrGrabResult->GetWidth(), CV_8UC3, (uint8_t*)image.GetBuffer());
                // imshow("img",cv_img);
                // waitKey(0);
            }
        }
    }
    catch (const GenericException &e)
    {
        // Error handling.
        cerr << "An exception occurred." << endl
        << e.GetDescription() << endl;
        exitCode = 1;
    }
    // Releases all pylon resources.
    PylonTerminate();

    return 0;
}

Makefile文件

# Makefile for Basler pylon sample program
.PHONY: all clean

# The program to build
NAME       := HardwareTrigger

# Installation directories for pylon
PYLON_ROOT ?= /opt/pylon5

# Build tools and flags
LD         := $(CXX)
CPPFLAGS   := $(shell $(PYLON_ROOT)/bin/pylon-config --cflags)
CXXFLAGS   := #e.g., CXXFLAGS=-g -O0 for debugging
LDFLAGS    := $(shell $(PYLON_ROOT)/bin/pylon-config --libs-rpath)
LDLIBS     := $(shell $(PYLON_ROOT)/bin/pylon-config --libs)

# Rules for building
all: $(NAME)

$(NAME): $(NAME).o
    $(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS)

$(NAME).o: $(NAME).cpp
    $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<

clean:
    $(RM) $(NAME).o $(NAME)

运行编译出的可执行文件之后,不断触发相机,可得出一下的结果即触发成功

Using device acA1600-60gm
Please wait. Images are grabbed.
1600
1200
Please wait. Images are grabbed.
1600
1200
Please wait. Images are grabbed.
1600
1200
Please wait. Images are grabbed.
1600
1200
Please wait. Images are grabbed.
1600
1200
Please wait. Images are grabbed.
1600
1200

示例下载

以上代码的示例链接: https://pan.baidu.com/s/1b8DRlk 密码: nr2x

Qt+OpenCV版本代码链接: https://pan.baidu.com/s/1CEOOwS-Qw7GB_UDiZRyW5g
提取码:q5z1

相机图片

Basler相机
Basler相机