写在前面
本篇文章仅为工作记录,以下是本篇文章的开发环境
开发平台:Windows11
开发环境:QT5.15.2
开发语言:C++
编译器:MSVC 2019 64bit
线扫相机:LA-CM-16K05A-00-R
SDK版本:SaperaLTSDKSetup_8.20
采集卡:Xtium-CL_MX4
设计外触发之前要先确认内触发正常
内触发相关代码见上篇文章:Dalsa线扫相机SDK二次开发(内触发 QT开发)
刚开始接触外触发时我一直不理解外触发到底是怎样传递信号的,实操之后才明白了一些。简单来说,会有另一台控制器给采集卡发送PSO信号(高/低电平信号),如果将触发模式设置为高电平/低电平/上升沿/下降沿,那么在遇到对应的电流信号时采集卡会发送采集命令给相机,然后相机采图并将图像传给采集卡,这个时候如果不上传在采集卡数据(执行grab函数)到缓冲区,那你就无法图像数据,所以在给外触发信号之前一定要执行grab函数上传采集卡资源,这样等外触发信号来了之后才能收到采集的图像数据,外触发结束之后执行Freeze()函数停止上传采集卡资源。所以本质上在上篇内触发代码的基础上,将相机模式调整为外触发后,代码不用动直接运行,然后点击连续采图,接着给外触发信号,他就能根据外触发信号采图了,我这里根据工作需要做了一些改动。
相机类CCamera头文件接口
主要优化了一下接口,和内触发区别不大,部分代码如下:
enum ETriggerMode {internal, //内触发,即不需要触发,自动运行external, //外触发 (可能需要选择触发通道) };class CCamera : public QObject {Q_OBJECT public:CCamera(QObject *parent = nullptr);~CCamera();bool init_camera(); //初始化设备bool stopGrab(); //关闭采集(内/外触发)bool startGrab(); //开启采集等待外触发信号bool grabOnce(int num); //单步采集(内触发)bool grabContinues(); //持续采集(内/外触发)bool initDevice(char *m_serverName, const char *ccfPath); //初始化采集卡void free(); //释放资源void saveImage(); //保存图像数据void setETriggerMode(ETriggerMode mode); //设置触发模式void setConfigPath(std::string DevicePath, std::string ImagePath); //设置采集卡配置路径、图像保存路径private:std::string m_ccfPath{}; //配置文件路径std::string m_ImagePath{}; //图像保存路径char *m_ServerName{nullptr}; //服务器名称、即采集卡名称ETriggerMode m_mode{external}; //触发模式、默认是外触发SapAcquisition *m_Acquisition{nullptr}; //控制与板卡相连接的设备,即线扫相机,仅用于存储采集资源参数,SapBufferWithTrash *m_Buffers{nullptr}; //带垃圾缓冲区的buffer,(常用于处理速度跟不上数据采集速度时)SapTransfer *m_Xfer{nullptr}; //管理通用传输过程的功能,即将数据从一个源节点传输到目标节点的操作//SapView *m_View{nullptr}; //在窗口中显示SapBuffer对象的资源, };
相机类部分实现
1、采集卡初始化:枚举连接到计算机上的采集卡设备->获取采集卡名称->打开采集卡设备
2、设置参数:采集卡所有参数信息都在配置文件中记录,可以打开 Sapera CamExpert设置相应的参数,然后保存到相应的配置文件中;
3、创建底层资源:主要是创建缓冲区、传输模式、注册回调函数,用来保存/转移图像数据,
4、采集图像:可以选择连续采集图像或者采集有限帧的图像序列,采图时可以选择等待时间/立即返回
代码相比内触发模式下仅有部分变动:
初始化时设置配置文件路径:
std::string ccfPath = "E:\\ExternalConfig.ccf"; //配置文件路径std::string ImagePath = "D:\\test\\bmp\\"; //保存图像路径setConfigPath(ccfPath, ImagePath);
配置路径setConfigPath函数:
void CCamera::setConfigPath(std::string DevicePath, std::string ImagePath) //采集卡配置文件、图像保存路径 {m_ccfPath = DevicePath;m_ImagePath = ImagePath; }
内/外触发模式下连续采集图像:由于内触发只是做测试没有别的操作,这里就没做复杂处理
bool CCamera::grabContinues() //连续传输 {bool isok = false;framcount = 0;if (internal == m_mode) {isok = startGrab();} else if (external == m_mode) {isok = startGrab();}qDebug() << "Start Grab Continues: " << isok;return isok; }
设置触发模式:
void CCamera::setETriggerMode(ETriggerMode mode) //设置触发模式 {m_mode = mode; }
其他也有些变动,但改动不大,自己对着改一下就行了,例如:saveImage里保存路径换成了m_ImagePath ,m_ImagePath 在初始化时设置为了你要保存的路径,
void CCamera::saveImage() //保存图像数据 {std::stringstream ss;ss << m_ImagePath << framcount << ".bmp";std::string name = ss.str();const char *savename = name.c_str();m_Buffers->Save(savename, "-format bmp"); //保存为bmp格式qDebug() << "framcount: " << framcount;framcount++; }