c++ 多品牌工业相机SDK开发

一、背景

实际工程中逃不掉使用工业相机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;
}

三、完整代码上传在资源

有海康大恒巴斯勒三类相机代码,请大家下载使用有问题可反馈。

如果有遇到高帧率采集,可以使用队列方式,先将回调获取的图片存入队列,再依次出列进行图像处理。