由于学校实验室需要用到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相机
网友评论