最近对灰点的工业网口相机进行了调试,最终目标是要实现多相机的同时采集。
使用工业网口相机
第一步要安装相机的SDK:
包含spinnaker软件包和pyhton扩展。
这个软件包不好下载,可以去下载上传的版本,下载地址稍后上传。
第二步是配置网卡地址:
按照readme中的提示配置就可以,如果使用多个网口,需要配置到不同的网段。在Windows系统下成功实现了配置2个网段的网口分别采集2路相机,总共采集4个相机。但是在Ubuntu18.04系统下,不管怎么配置,都只有一个网段能使用相机,最后只好采用1个网口通过交换机连接4个相机的方式,这样在全分辨率情况下不能做到满帧率。目前还不知道怎么解决。
第三步是按照提供的例程,修改得到多相机同时采集的程序:
#include "Spinnaker.h"
#include "SpinGenApi/SpinnakerGenApi.h"
#include
#include
#include
#include
#include
using namespace cv;
using namespace Spinnaker;
using namespace Spinnaker::GenApi;
using namespace Spinnaker::GenICam;
using namespace std;
CameraList camList;
SystemPtr camsystem;
enum triggerType
{
SOFTWARE,
HARDWARE
};
const triggerType chosenTrigger = SOFTWARE;
int ConfigureTrigger(INodeMap & nodeMap)
{
int result = 0;
if (chosenTrigger == SOFTWARE)
{
cout << "Software trigger chosen..." << endl;
}
else if (chosenTrigger == HARDWARE)
{
cout << "Hardware trigger chosen..." << endl;
}
try
{
CEnumerationPtr ptrTriggerMode = nodeMap.GetNode("TriggerMode");
if (!IsAvailable(ptrTriggerMode) || !IsReadable(ptrTriggerMode))
{
cout << "Unable to disable trigger mode (node retrieval). Aborting..." << endl;
return -1;
}
CEnumEntryPtr ptrTriggerModeOff = ptrTriggerMode->GetEntryByName("Off");
if (!IsAvailable(ptrTriggerModeOff) || !IsReadable(ptrTriggerModeOff))
{
cout << "Unable to disable trigger mode (enum entry retrieval). Aborting..." << endl;
return -1;
}
ptrTriggerMode->SetIntValue(ptrTriggerModeOff->GetValue());
cout << "Trigger mode disabled..." << endl;
CEnumerationPtr ptrTriggerSource = nodeMap.GetNode("TriggerSource");
if (!IsAvailable(ptrTriggerSource) || !IsWritable(ptrTriggerSource))
{
cout << "Unable to set trigger mode (node retrieval). Aborting..." << endl;
return -1;
}
if (chosenTrigger == SOFTWARE)
{
// Set trigger mode to software
CEnumEntryPtr ptrTriggerSourceSoftware = ptrTriggerSource->GetEntryByName("Software");
if (!IsAvailable(ptrTriggerSourceSoftware) || !IsReadable(ptrTriggerSourceSoftware))
{
cout << "Unable to set trigger mode (enum entry retrieval). Aborting..." << endl;
return -1;
}
ptrTriggerSource->SetIntValue(ptrTriggerSourceSoftware->GetValue());
cout << "Trigger source set to software..." << endl;
}
else if (chosenTrigger == HARDWARE)
{
// Set trigger mode to hardware ('Line0')
CEnumEntryPtr ptrTriggerSourceHardware = ptrTriggerSource->GetEntryByName("Line0");
if (!IsAvailable(ptrTriggerSourceHardware) || !IsReadable(ptrTriggerSourceHardware))
{
cout << "Unable to set trigger mode (enum entry retrieval). Aborting..." << endl;
return -1;
}
ptrTriggerSource->SetIntValue(ptrTriggerSourceHardware->GetValue());
cout << "Trigger source set to hardware..." << endl;
}
CEnumEntryPtr ptrTriggerModeOn = ptrTriggerMode->GetEntryByName("On");
if (!IsAvailable(ptrTriggerModeOn) || !IsReadable(ptrTriggerModeOn))
{
cout << "Unable to enable trigger mode (enum entry retrieval). Aborting..." << endl;
return -1;
}
ptrTriggerMode->SetIntValue(ptrTriggerModeOn->GetValue());
// TODO: Blackfly and Flea3 GEV cameras need 1 second delay after trigger mode is turned on
cout << "Trigger mode turned back on..." << endl << endl;
}
catch (Spinnaker::Exception &e)
{
cout << "Error: " << e.what() << endl;
result = -1;
}
return result;
}
int ResetTrigger(INodeMap & nodeMap)
{
int result = 0;
try
{
//
// Turn trigger mode back off
//
// *** NOTES ***
// Once all images have been captured, turn trigger mode back off to
// restore the camera to a clean state.
//
CEnumerationPtr ptrTriggerMode = nodeMap.GetNode("TriggerMode");
if (!IsAvailable(ptrTriggerMode) || !IsReadable(ptrTriggerMode))
{
cout << "Unable to disable trigger mode (node retrieval). Non-fatal error..." << endl;
return -1;
}
CEnumEntryPtr ptrTriggerModeOff = ptrTriggerMode->GetEntryByName("Off");
if (!IsAvailable(ptrTriggerModeOff) || !IsReadable(ptrTriggerModeOff))
{
cout << "Unable to disable trigger mode (enum entry retrieval). Non-fatal error..." << endl;
return -1;
}
ptrTriggerMode->SetIntValue(ptrTriggerModeOff->GetValue());
cout << "Trigger mode disabled..." << endl << endl;
}
catch (Spinnaker::Exception &e)
{
cout << "Error: " << e.what() << endl;
result = -1;
}
return result;
}
int DisableHeartbeat(CameraPtr pCam, INodeMap & nodeMap, INodeMap & nodeMapTLDevice)
{
cout << "Checking device type to see if we need to disable the camera's heartbeat..." << endl << endl;
CEnumerationPtr ptrDeviceType = nodeMapTLDevice.GetNode("DeviceType");
if (!IsAvailable(ptrDeviceType) && !IsReadable(ptrDeviceType))
{
cout << "Error with reading the device's type. Aborting..." << endl << endl;
return -1;
}
else
{
if (ptrDeviceType->GetIntValue() == DeviceType_GEV)
{
cout << "Working with a GigE camera. Attempting to disable heartbeat before continuing..." << endl << endl;
CBooleanPtr ptrDeviceHeartbeat = nodeMap.GetNode("GevGVCPHeartbeatDisable");
if (!IsAvailable(ptrDeviceHeartbeat) || !IsWritable(ptrDeviceHeartbeat))
{
cout << "Unable to disable heartbeat on camera. Continuing with execution as this may be non-fatal..." << endl << endl;
}
else
{
ptrDeviceHeartbeat->SetValue(true);
cout << "WARNING: Heartbeat on GigE camera disabled for the rest of Debug Mode." << endl;
cout << " Power cycle camera when done debugging to re-enable the heartbeat..." << endl << endl;
}
}
else
{
cout << "Camera does not use GigE interface. Resuming normal execution..." << endl << endl;
}
}
return 0;
}
bool InitCamera()
{
camsystem = System::GetInstance();
const LibraryVersion spinnakerLibraryVersion = camsystem->GetLibraryVersion();
cout << "Spinnaker library version: "
<< spinnakerLibraryVersion.major << "."
<< spinnakerLibraryVersion.minor << "."
<< spinnakerLibraryVersion.type << "."
<< spinnakerLibraryVersion.build << endl << endl;
camList = camsystem->GetCameras();
unsigned int numCameras = camList.GetSize();
cout << "Number of cameras detected: " << numCameras << endl << endl;
if (numCameras == 0)
{
camList.Clear();
camsystem->ReleaseInstance();
return false;
}
return true;
}
bool UnInitCamera()
{
camList.Clear();
camsystem->ReleaseInstance();
return true;
}
int main()
{
clock_t start, finish;
double totaltime;
CameraPtr pCam[4] = {NULL};
try
{
if (!InitCamera())
return -1;
int cameranumber = camList.GetSize();
for (unsigned int i = 0; i < cameranumber; i++)
{
pCam[i] = camList.GetByIndex(i);
pCam[i]->Init();
cout << "camera " << i << " init su" << endl;
INodeMap & nodeMap = pCam[i]->GetNodeMap();
ConfigureTrigger(nodeMap);
cout << "camera " << i << "set to software trigger" << endl;
//CIntegerPtr ptrWidth = nodeMap.GetNode("Width");
//ptrWidth->SetValue(320);
//CIntegerPtr ptrHeight = nodeMap.GetNode("Height");
//ptrHeight->SetValue(240);
//DisableHeartbeat(pCam[i], pCam[i]->GetNodeMap(), pCam[i]->GetTLDeviceNodeMap());
pCam[i]->BeginAcquisition();
}
while (1)
{
start = clock();
//cout << "send trigger command" << endl;
CCommandPtr ptrSoftwareTriggerCommand[4];
ImagePtr pResultImage[4];
for (unsigned int i = 0; i < cameranumber; i++)
{
ptrSoftwareTriggerCommand[i] = pCam[i]->GetNodeMap().GetNode("TriggerSoftware");
if (!IsAvailable(ptrSoftwareTriggerCommand[i]) || !IsWritable(ptrSoftwareTriggerCommand[i]))
{
cout << "Unable to execute trigger. Aborting..." << endl;
return -1;
}
}
for (unsigned int i = 0; i < cameranumber; i++)
{
ptrSoftwareTriggerCommand[i]->Execute();
pResultImage[i] = pCam[i]->GetNextImage();
if (!pResultImage[i]->IsIncomplete())
{
// Convert image to mono 8
ImagePtr bgrImage = pResultImage[i]->Convert(PixelFormat_BGR8, HQ_LINEAR);
Mat image = Mat(bgrImage->GetHeight(), bgrImage->GetWidth(), CV_8UC3, bgrImage->GetData());
string windowname = "image" + to_string(i);
namedWindow(windowname);
imshow(windowname, image);
waitKey(1);
}
else
cout << "Image incomplete with image status " << pResultImage[i]->GetImageStatus() << "..." << endl << endl;
//sleep(50);
}
finish = clock();
totaltime = (double)(finish - start) / CLOCKS_PER_SEC;
cout << "\n time is:" << totaltime << " " << endl;
}
for (unsigned int i = 1; i GetNodeMap();
ResetTrigger(nodeMap);
pCam[i]->DeInit();
}
}
catch (Spinnaker::Exception &e)
{
cout << "Error: " << e.what() << endl;
}
UnInitCamera();
return 0;
}
cmakelist文件内容
cmake_minimum_required(VERSION 3.5)
add_definitions(-std=c++11)
#项目名称
project(camera)
#代码路径
aux_source_directory(. DIR_TOOT_SRCS)
#dubug 模式
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
include_directories("/usr/include/spinnaker")
#生成可执行的文件
add_executable(camera ${DIR_TOOT_SRCS})
target_link_libraries(camera
${OpenCV_LIBS}
Spinnaker )
这里用到了opencv进行图像的显示。