利用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设置和相机状态检测。
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;
}
---------------------------------
测试效果如下:
特别地,对上述程序进行适当的修改,可以进行相机的同步出图,以及出图效果测试。
---------------------------------------------------------
//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;
}
-------------------