一、背景
实际工程中逃不掉使用工业相机sdk获取图片,那么就有需求将多品牌相机开发集成到一个工具类,使用统一接口,具体使用哪个品牌相机就初始化哪种子类;且编译阶段通过宏定义屏蔽或开放指定相机的代码,防止编译需要用到的lib库缺失导致编译失败
二、设计
1.设计一个基函数类,所有相机子类继承自该基类并实现
2.基类中包含一个工厂方法,用来new一个实例类
3.定义一个回调函数,规范化注册回调函数
基类代码如下:
cpp
#pragma once
#include<Windows.h>
#include <string>
#include<vector>
#include <memory>
// 统一图像帧结构体
struct CameraFrame {
int width = 0; // 图像宽度
int height = 0; // 图像高度
int size = 0;
};
// 相机信息结构体
struct CameraInfo {
std::string model; // 型号
std::string serialNumber; // 序列号(唯一标识)
std::string ipAddress; // IP地址(网口相机)
};
enum class TriggerMode {
Off,
On
};
enum class TriggerSource {
Software,
Line0,
Line2,
};
enum class CameraBrand {
HIK,
Basler,
DaHeng
};
/// <summary>
/// 回调函数
/// </summary>
typedef void(__stdcall* ImageCallback)(BYTE* pBuffer, CameraFrame& dwBufSize, void* dwUser);
class ICamera
{
public:
virtual ~ICamera() = default;
// 枚举所有可用相机
virtual std::vector<CameraInfo> enumDevices() = 0;
// 打开相机(通过序列号)
virtual bool open(const std::string& serialNumber) = 0;
// 关闭相机
virtual void close() = 0;
// 开始采集
virtual bool startGrab() = 0;
// 停止采集
virtual void stopGrab() = 0;
// 设置采集回调(异步模式)
virtual bool setFrameCallback(ImageCallback, void* user)=0;
// 设置曝光时间(微秒)
virtual bool setExposureTime(double exposureTimeUs) = 0;
// 获取当前曝光时间
virtual bool getExposureTime(double& exposureTimeUs) = 0;
// 设置增益(dB)
virtual bool setGain(double gainDb) = 0;
// 获取当前增益
virtual bool getGain(double& gainDb) = 0;
// 设置触发模式
virtual bool setTriggerMode(TriggerMode enable) = 0;
//设置触发源
virtual bool setTriggerSource(TriggerSource triggerSource) = 0;
// 软件触发一次
virtual bool softwareTrigger() = 0;
// 获取相机是否已打开
virtual bool isOpened() const = 0;
// 获取相机是否正在采集
virtual bool isGrabbing() const = 0;
// 获取当前相机信息
virtual CameraInfo getCurrentCameraInfo() const = 0;
// 工厂方法作为静态成员
static std::unique_ptr<ICamera> createCamera(const CameraBrand& cameraType);
};
静态工厂方法实现:
cpp
#include "ICamera.h"
#include"HIKCamera.h"
#include"BaslerCamera.h"
#include"DaHengCamera.h"
std::unique_ptr<ICamera> ICamera::createCamera(const CameraBrand& cameraType)
{
switch (cameraType) {
case CameraBrand::HIK:
#ifdef Hik_SUPPORT
return std::make_unique<HIKCamera>();
#else
std::cerr << "Error: 未开启HIK相机支持(Hik_SUPPORT宏未定义)" << std::endl;
#endif
break;
case CameraBrand::Basler:
#ifdef Basler_SUPPORT
return std::make_unique<BaslerCamera>();
#else
std::cerr << "Error: 未开启Basler相机支持(Basler_SUPPORT宏未定义)" << std::endl;
#endif
break;
case CameraBrand::DaHeng:
#ifdef DaHeng_SUPPORT
return std::make_unique<DahengCamera>();
#else
std::cerr << "Error: 未开启大恒相机支持(DaHeng_SUPPORT宏未定义)" << std::endl;
#endif
break;
default:
std::cerr << "Error: 未知相机类型枚举" << std::endl;
return nullptr;
}
// 所有不支持的分支最终返回空
return nullptr;
}
三、完整代码上传在资源
有海康大恒巴斯勒三类相机代码,请大家下载使用有问题可反馈。
如果有遇到高帧率采集,可以使用队列方式,先将回调获取的图片存入队列,再依次出列进行图像处理。