作者:billy
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处
操作系统:Windows 10 1903 18362.778
相机型号:BASLER acA 1300-60gm
相机软件:pylon_Runtime_6.0.0.17906,Basler_pylon_5.0.10.10613
软件版本:Qt 5.12.8, vs2017 Community
通信方式:GigE - 千兆以太网通信协议
开发包和驱动下载地址
提取码:lg0i
驱动安装完成之后需要完成一些配置才能成功连接相机:
安装驱动和开发包完成之后,可以找到以下目录:
巴斯勒相机实时获取图像的原理就是对每一帧数据的处理,即 拍照 - 处理数据 - 拍照 - 处理数据 …
SDK中提供了两种方式来处理图像,我们先来看一下最主要的开始抓取图像的函数 StartGrabbing:
virtual void StartGrabbing( EGrabStrategy strategy = GrabStrategy_OneByOne,
EGrabLoop grabLoopType = GrabLoop_ProvidedByUser);
来看一下函数的两个参数代表什么含义:
One by One Grab Strategy
这种模式是最简单的,也是 CInstantCamera 默认的图像获取策略。
获取到的图像放到一个FIFO 队列中。每次我们从队列中取的(RetrieveResult)都是最早放到队列中的图像。
Latest Image Only Grab Strategy
这个策略下只有最新到的图像保存在输出队列中。
如果一份旧图像还没被读取新图像就又来了,那么旧图像就被舍弃。这样可以保证读取到图像永远都是读取时刻最新的。
Latest Images Grab Strategy
这个模式下输出队列可以保存不止一张图像,具体最多能保存几张图象由 CInstantCamera::OutputQueueSize 来指定。
当新的图像来了,而队列已满时,旧的图像被舍弃。
当 CInstantCamera::OutputQueueSize 为 1 时就是 Latest Image Only Grab Strategy。
当 CInstantCamera::OutputQueueSize = CInstantCamera::MaxNumBuffer,就和 One by One Grab Strategy 一样了。
Upcoming Image Grab Strategy
这个模式很特别,只有当 CInstantCamera::RetrieveResult() 被调用后才会采集图像。USB 相机不支持这种策略。
GrabLoop_ProvidedByUser
用户在代码中循环调用RetrieveResult() 来处理抓取的图像和相机事件。默认使用这种模式。
GrabLoop_ProvidedByInstantCamera
抓取循环线程由即时相机提供。它会不断循环调用RetrieveResult()。抓取的图像由注册的图像事件处理程序处理。抓取循环线程在抓取启动时启动。
StartGrabbing的第一个参数代表获取图像的策略,第二个参数代表的是使用哪个循环线程来抓取图像。由第二个参数我们就可以分两种方式来处理图像数据:
m_baslerCamera.StartGrabbing(GrabStrategy_OneByOne, GrabLoop_ProvidedByUser);
m_baslerCamera.RetrieveResult(1000, ptrGrabResult, TimeoutHandling_ThrowException);
CImagePersistence::Save(ImageFileFormat_Bmp, filename, ptrGrabResult);
m_baslerCamera.RegisterImageEventHandler(this, RegistrationMode_Append, Cleanup_Delete);
virtual void OnImageGrabbed(CInstantCamera &camera, const CGrabResultPtr &grabResult) override;
m_baslerCamera.StartGrabbing(GrabStrategy_OneByOne, GrabLoop_ProvidedByInstantCamera);
实现功能:相机图像的实时显示,并且可以在需要的时候获取当前帧数据,用于分析或者保存;
首先需要在pro中配置头文件和库文件
INCLUDEPATH += $$PWD/include/ \
$$PWD/include/pylon
windows {
contains(DEFINES, WIN64) {
LIBS += -L$$PWD/lib/x64/ -lGCBase_MD_VC120_v3_0_Basler_pylon_v5_0
LIBS += -L$$PWD/lib/x64/ -lGenApi_MD_VC120_v3_0_Basler_pylon_v5_0
LIBS += -L$$PWD/lib/x64/ -lPylonBase_MD_VC120_v5_0
LIBS += -L$$PWD/lib/x64/ -lPylonC_MD_VC120
LIBS += -L$$PWD/lib/x64/ -lPylonGUI_MD_VC120_v5_0
LIBS += -L$$PWD/lib/x64/ -lPylonUtility_MD_VC120_v5_0
} else {
LIBS += -L$$PWD/lib/Win32/ -lGCBase_MD_VC120_v3_0_Basler_pylon_v5_0
LIBS += -L$$PWD/lib/Win32/ -lGenApi_MD_VC120_v3_0_Basler_pylon_v5_0
LIBS += -L$$PWD/lib/Win32/ -lPylonBase_MD_VC120_v5_0
LIBS += -L$$PWD/lib/Win32/ -lPylonC_MD_VC120
LIBS += -L$$PWD/lib/Win32/ -lPylonGUI_MD_VC120_v5_0
LIBS += -L$$PWD/lib/Win32/ -lPylonUtility_MD_VC120_v5_0
}
}
自定义相机基类 Camera
#ifndef CAMERA_H
#define CAMERA_H
#include
#include
#include
#include
#include
class Camera : public QObject
{
Q_OBJECT
public:
enum CameraType {
Basler = 1, // 巴斯勒相机
IC_Imaging, // 映美精相机
MV, // 海康威视相机
Virtual // 虚拟相机
};
explicit Camera(CameraType type = Basler) : m_type(type) {}
virtual void initCamera() = 0; // 初始化相机
virtual void destroyCamera() = 0; // 销毁相机
virtual void openCamera() = 0; // 打开相机
virtual void closeCamera() = 0; // 关闭相机
virtual void startWork() = 0; // 开始工作
virtual void stopWork() = 0; // 停止工作
virtual cv::Mat takeAPic() = 0; // 获取当前图像
void start() { m_timer.start(); }
void stop() { m_timer.stop(); }
void setInterval(int time) { m_timer.setInterval(time); }
CameraType getCameraType() { return m_type; }
signals:
void updateImage(QImage image);
protected:
CameraType m_type;
QMutex m_mutex;
QTimer m_timer;
};
#endif // CAMERA_H
自定义 BBaslerCamerControl 相机控制类
#ifndef BBASLERCAMERCONTROL_H
#define BBASLERCAMERCONTROL_H
#include "../camera.h"
#include "PylonIncludes.h"
using namespace std;
using namespace Pylon;
using namespace GenApi;
class BBaslerCamerControl : public Camera
{
Q_OBJECT
public:
enum BaslerCameraProperty {
DeviceModelName, // 相机名称
DeviceID, // 相机SN号
ResultingFrameRateAbs, // 相机帧率
AcquisitionFrameRateAbs, // 相机频率
Freerun, // 相机内触发
Line1, // 相机外触发
ExposureTimeAbs, // 相机曝光时间
GainRaw, // 相机增益
SensorWidth, // 传感器宽度
SensorHeight, // 传感器高度
Width, // 图片宽度
Height, // 图片高度
PixelFormat, // 图片的格式
};
explicit BBaslerCamerControl(Camera::CameraType type = Camera::CameraType::Basler);
virtual void initCamera() override;
virtual void destroyCamera() override;
virtual void openCamera() override;
virtual void closeCamera() override;
virtual void startWork() override;
virtual void stopWork() override;
virtual cv::Mat takeAPic() override;
QString getCameraProperty(BBaslerCamerControl::BaslerCameraProperty type); // 获取相机参数
void setCameraProperty(BBaslerCamerControl::BaslerCameraProperty type, double value = 0.0); // 设置相机参数
public slots:
void updateFrame();
private:
CInstantCamera m_baslerCamera; // 实例化相机对象
INodeMap *m_nodeMap; // 相机属性节点
QString m_currentMode; // 相机触发模式
};
#endif // BBASLERCAMERCONTROL_H
#include "bbaslercamercontrol.h"
#include "globalfun.h"
BBaslerCamerControl::BBaslerCamerControl(Camera::CameraType type) : Camera(type)
{
m_timer.setInterval(GlobalValue::cam_itl);
connect(&m_timer, &QTimer::timeout, this, &BBaslerCamerControl::updateFrame);
}
void BBaslerCamerControl::initCamera()
{
try {
Pylon::PylonInitialize(); // 调用其他 pylon 函数之前必须调用 PylonInitialize 完成初始化
} catch (GenICam::GenericException &e) {
qDebug() << "initCamera erroer: " + QString::fromLocal8Bit(e.what());
}
}
void BBaslerCamerControl::destroyCamera()
{
try {
stopWork();
closeCamera();
Pylon::PylonTerminate(); // 释放 pylon 运行时系统分配的资源
} catch (GenICam::GenericException &e) {
qDebug() << "destroyCamera erroer: " + QString::fromLocal8Bit(e.what());
}
}
void BBaslerCamerControl::openCamera()
{
try {
m_baslerCamera.Attach(CTlFactory::GetInstance().CreateFirstDevice()); //实例化找到的第一个相机
m_baslerCamera.Open(); // 打开相机
m_nodeMap = &m_baslerCamera.GetNodeMap(); // 获取相机属性节点
m_currentMode = getCameraProperty(Line1); // 获取相机触发模式
} catch (GenICam::GenericException &e) {
qDebug() << "openCamera erroer: " + QString::fromLocal8Bit(e.what());
}
}
void BBaslerCamerControl::closeCamera()
{
try {
if ( m_baslerCamera.IsOpen() ) {
m_baslerCamera.DetachDevice(); // 分离连接的 pylon 设备
m_baslerCamera.Close(); // 关闭连接的 pylon 设备
m_nodeMap = nullptr; // 相机属性节点置空
m_currentMode = ""; // 相机触发模式置空
}
} catch (GenICam::GenericException &e) {
qDebug() << "closeCamera erroer: " + QString::fromLocal8Bit(e.what());
}
}
void BBaslerCamerControl::startWork()
{
// Check if camera is open.
if ( !m_baslerCamera.IsOpen() ) {
return;
}
try {
m_baslerCamera.StartGrabbing(GrabStrategy_LatestImageOnly, GrabLoop_ProvidedByUser); // 开始抓取图像
m_timer.start();
} catch (GenICam::GenericException &e) {
qDebug() << "startWork erroer: " + QString::fromLocal8Bit(e.what());
}
}
void BBaslerCamerControl::stopWork()
{
try {
if ( m_baslerCamera.IsGrabbing() ) {
m_baslerCamera.StopGrabbing(); // 停止抓取图像
m_timer.stop();
}
} catch (GenICam::GenericException &e) {
qDebug() << "stopWork erroer: " + QString::fromLocal8Bit(e.what());
}
}
cv::Mat BBaslerCamerControl::takeAPic()
{
// Check if camera is open.
if ( !m_baslerCamera.IsOpen() ) {
return cv::Mat();
}
QMutexLocker locker(&m_mutex);
try {
CGrabResultPtr ptrGrabResult;
m_baslerCamera.RetrieveResult(1000, ptrGrabResult, TimeoutHandling_ThrowException);
if ( ptrGrabResult->GrabSucceeded() ) {
CPylonImage pylogimage;
CImageFormatConverter formatconverter;
formatconverter.OutputPixelFormat = PixelType_RGB8packed;
formatconverter.Convert(pylogimage, ptrGrabResult);
cv::Mat mat = cv::Mat(int( ptrGrabResult->GetHeight() ),
int( ptrGrabResult->GetWidth() ),
CV_8UC3,
static_cast< uchar* >( pylogimage.GetBuffer() ));
return mat.clone();
} else {
return cv::Mat();
}
} catch (GenICam::GenericException &e) {
qDebug() << "takeAPic erroer: " + QString::fromLocal8Bit(e.what());
return cv::Mat();
}
}
QString BBaslerCamerControl::getCameraProperty(BBaslerCamerControl::BaslerCameraProperty type)
{
// Check if camera is open.
if ( !m_baslerCamera.IsOpen() ) {
return "";
}
QString ret = "";
try {
switch (type) {
case DeviceModelName: {
const CStringPtr deviceModelName = m_nodeMap->GetNode("DeviceModelName");
ret = QString::fromLocal8Bit(deviceModelName->ToString().c_str());
} break;
case DeviceID: {
const CStringPtr deviceID = m_nodeMap->GetNode("DeviceID");
ret = QString::fromLocal8Bit(deviceID->ToString().c_str());
} break;
case ResultingFrameRateAbs: {
const CFloatPtr resultingFrameRateAbs = m_nodeMap->GetNode("ResultingFrameRateAbs");
ret = QString::number(resultingFrameRateAbs->GetValue());
} break;
case AcquisitionFrameRateAbs: {
const CBooleanPtr acquisitionFrameRateEnable = m_nodeMap->GetNode("AcquisitionFrameRateEnable");
acquisitionFrameRateEnable->SetValue(TRUE);
const CFloatPtr acquisitionFrameRateAbs = m_nodeMap->GetNode("AcquisitionFrameRateAbs");
ret = QString::number(acquisitionFrameRateAbs->GetValue());
} break;
case Freerun:
case Line1: {
const CEnumerationPtr triggerSelector = m_nodeMap->GetNode("TriggerSelector");
triggerSelector->FromString("FrameStart");
CEnumerationPtr triggerSource = m_nodeMap->GetNode("TriggerSource");
ret = QString::fromLocal8Bit(triggerSource->ToString().c_str());
} break;
case ExposureTimeAbs: {
const CFloatPtr exposureTimeAbs = m_nodeMap->GetNode("ExposureTimeAbs");
ret = QString::number(exposureTimeAbs->GetValue());
} break;
case GainRaw: {
const CIntegerPtr gainRaw = m_nodeMap->GetNode("GainRaw");
ret = QString::number(gainRaw->GetValue());
} break;
case SensorWidth: {
const CIntegerPtr sensorWidth = m_nodeMap->GetNode("SensorWidth");
ret = QString::number(sensorWidth->GetValue());
} break;
case SensorHeight: {
const CIntegerPtr sensorHeight = m_nodeMap->GetNode("SensorHeight");
ret = QString::number(sensorHeight->GetValue());
} break;
case Width: {
const CIntegerPtr width = m_nodeMap->GetNode("Width");
ret = QString::number(width->GetValue());
} break;
case Height: {
const CIntegerPtr height = m_nodeMap->GetNode("Height");
ret = QString::number(height->GetValue());
} break;
case PixelFormat: {
const CEnumerationPtr pixelFormat = m_nodeMap->GetNode("PixelFormat");
ret = QString::fromLocal8Bit(pixelFormat->ToString().c_str());
} break;
default: ret = ""; break;
}
} catch (GenICam::GenericException &e) {
qDebug() << "getCameraProperty erroer: " + QString::fromLocal8Bit(e.what());
}
return ret;
}
void BBaslerCamerControl::setCameraProperty(BBaslerCamerControl::BaslerCameraProperty type, double value)
{
// Check if camera is open.
if ( !m_baslerCamera.IsOpen() ) {
return;
}
try {
switch (type) {
case AcquisitionFrameRateAbs: {
const CBooleanPtr acquisitionFrameRateEnable = m_nodeMap->GetNode("AcquisitionFrameRateEnable");
acquisitionFrameRateEnable->SetValue(TRUE);
const CFloatPtr acquisitionFrameRateAbs = m_nodeMap->GetNode("AcquisitionFrameRateAbs");
acquisitionFrameRateAbs->SetValue(value);
} break;
case Freerun: {
CEnumerationPtr triggerSelector = m_nodeMap->GetNode("TriggerSelector");
triggerSelector->FromString("FrameStart");
CEnumerationPtr triggerMode = m_nodeMap->GetNode("TriggerMode");
triggerMode->SetIntValue(1);
CEnumerationPtr triggerSource = m_nodeMap->GetNode("TriggerSource");
triggerSource->FromString("Software");
} break;
case Line1: {
CEnumerationPtr triggerSelector = m_nodeMap->GetNode("TriggerSelector");
triggerSelector->FromString("FrameStart");
CEnumerationPtr triggerMode = m_nodeMap->GetNode("TriggerMode");
triggerMode->SetIntValue(1);
CEnumerationPtr triggerSource = m_nodeMap->GetNode("TriggerSource");
triggerSource->FromString("Line1");
} break;
case ExposureTimeAbs: {
const CFloatPtr exposureTimeAbs = m_nodeMap->GetNode("ExposureTimeAbs");
exposureTimeAbs->SetValue(value);
} break;
case GainRaw: {
const CIntegerPtr gainRaw = m_nodeMap->GetNode("GainRaw");
gainRaw->SetValue(value);
} break;
case Width: {
const CIntegerPtr width = m_nodeMap->GetNode("Width");
width->SetValue(value);
} break;
case Height: {
const CIntegerPtr height = m_nodeMap->GetNode("Height");
height->SetValue(value);
} break;
default: break;
}
} catch (GenICam::GenericException &e) {
qDebug() << "setCameraProperty erroer: " + QString::fromLocal8Bit(e.what());
}
}
void BBaslerCamerControl::updateFrame()
{
QMutexLocker locker(&m_mutex);
try {
CGrabResultPtr ptrGrabResult;
m_baslerCamera.RetrieveResult(1000, ptrGrabResult, TimeoutHandling_ThrowException);
if ( ptrGrabResult->GrabSucceeded() ) {
CPylonImage pylogimage;
CImageFormatConverter formatconverter;
formatconverter.OutputPixelFormat = PixelType_RGB8packed;
formatconverter.Convert(pylogimage, ptrGrabResult);
cv::Mat mat = cv::Mat(int( ptrGrabResult->GetHeight() ),
int( ptrGrabResult->GetWidth() ),
CV_8UC3,
static_cast< uchar* >( pylogimage.GetBuffer() ));
QImage image((const unsigned char *)(mat.data), mat.cols, mat.rows, mat.cols * 3, QImage::Format_RGB888);
emit updateImage(image.rgbSwapped());
}
} catch (GenICam::GenericException &e) {
qDebug() << "updateFrame erroer: " + QString::fromLocal8Bit(e.what());
}
}