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

由于学校实验室需要用到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/1QsJy4h_DZhQUEGiaT0qo9g
提取码:zrci

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

相机图片

Basler相机

Basler相机
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,185评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,652评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,524评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,339评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,387评论 6 391
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,287评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,130评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,985评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,420评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,617评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,779评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,477评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,088评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,716评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,857评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,876评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,700评论 2 354

推荐阅读更多精彩内容