小目标检测(1)——大恒(DaHeng)相机操作与控制编程

news2025/2/25 2:59:38

文章目录

    • 引言
    • 正文
      • 相关开发库的介绍
      • 编程准备
        • 配置引用头文件GalaxyIncludes.h
        • 配置lib文件
      • 具体编程过程
        • 初始化和反初始化
        • 枚举设备
        • 开关设备
      • 属性控制
        • 属性控制器种类
      • 图像采集控制和图像处理
        • 采单帧
        • 回调采集
        • 图像处理
        • 流对象属性控制
      • 获取设备事件
        • 获取掉线事件通知
      • 样例程序分析
      • 补充:项目中常用库函数
        • CINI库
    • 总结

引言

  • 在做老师的横向项目时,需要用大恒相机,需要将他的相机控制接入写的程序中,但是对于他的SDK并不了解,所以就好好看了他的SDK文件,并按照他的开发手册写了一个小的demo。

正文

相关开发库的介绍

  • 在使用别人的代码过程中,有很多库自己都看不懂,这里做一下记录
  • GxIAPICPPEx.dll:封装过后的通用并且统一的编程接口
  • IGXFactory:初始化接口库,枚举设备,打开设备
  • IGXDevice:设备对象,以此对象为入口进行属性控制、图像采集,获取相机事件等。
  • IGXStream:流对象,从IGXDevice获得,专门负责图像采集相关职能。
  • IGXFeatureControl:属性控制对象,分别从IGXDevice和IGXStream获得属性控制对象,
  • IImageData:回调采集和采单帧的图像结构体,包括采集输出结果:图像buffer和图像信息等,还自带图像格式转换、图像增强的功能
  • GXBitmap:负责图像的显示和存储功能,具体见示例程序

在这里插入图片描述

编程准备

  • 首先需要下载安装对应设备的SDK文件,具体链接,相关SDK软件下载
  • 这里是结合VS 2022进行打开,如何配置库,如何指定,相关的头文件。
  • 在编程之前,需要配置好指定的项目文件
    • 配置好所需要引用的头文件,Galaxyincludes.h头文件
    • 设置需要引用的库文件,GxlAPICPPEx.lib库文件

配置引用头文件GalaxyIncludes.h

  • 这里安装了SDK的话,需要指定你所运行的项目的配置文件,这里有两种写法,正常来说应该把对应的SDK复制在项目所在的文件里,这样项目的可移植性就比较强。但是我这里已经在工控机上进行 配置了,就直接写了绝对路径。
    在这里插入图片描述

配置lib文件

  • 这里必须配置GxIAPICPPEx.lib静态库文件,这个库是大恒相机对外编程的统一接口。接受一个新的项目文件,一般来说,配置文件里面有,但是属性里面没有配置,踩过坑之后发现需要重新配置。

  • 找到GxlAPICPPEx.lib的路径
    在这里插入图片描述

  • 设置相关的配置文件

在这里插入图片描述

  • 指定对应目录下方的静态库

在这里插入图片描述

具体编程过程

  • 当前章节,主要是涉及到如何调用相关的开发库,对相机进行初始化,并对相机进行控制,同时保存对应的图片。
  • 具体操作如下
    • 初始化获取相关的资源, 反初始化释放所有的资源
    • 枚举设备,获取所有资源
    • 开关设备

初始化和反初始化

  • 在调用GxlAPICPPEx.lib之前,相机必须要进行初始化,初始化是通过IGXFactory进行初始化的。
#include <iostream>
#include "IGXFactory.h"
#include "GalaxyException.h"

using namespace std;

int main()
{
    try {
        // 初始化相机实例
        IGXFactory::GetInstance().Init();
    }
    catch (CGalaxyException&e) {
        cout << "error code " << e.GetErrorCode() << endl;
        cout << "error description" << e.what() << endl;
    }
   


    std::cout << "Hello World!\n";
}
  • 在初始化中遇到CGalaxyException找不到标识符的问题,解决办法如下,在vs中找到异常,会跳转到GXSmartPtr.h头文件中,添加#include “GalaxyException.h”,具体如下

在这里插入图片描述

  • 加上这句之后,后续就没有运行问题了,运行截图如下
    在这里插入图片描述

  • 在调用相机的进程退出之后,必须要进行反初始化,释放GxlAPICPPEx库函数调用的所有资源。

// DahengCameraStart.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
// 基础应用

#include <iostream>
#include "IGXFactory.h"
#include "GalaxyException.h"

using namespace std;

int main()
{
    try {
        // 初始化相机实例
        IGXFactory::GetInstance().Init();
        // 相机的反初始化,释放所有占有的资源
        IGXFactory::GetInstance().Uninit();
    }
    catch (CGalaxyException&e) {
        cout << "error code " << e.GetErrorCode() << endl;
        cout << "error description" << e.what() << endl;
    }
   


    std::cout << "Hello World!\n";
}

枚举设备

  • 用户通过枚举设备来获取当前计算机中,可以使用的设备,并进行相关的调用
  • 用户通过调用 IGXFactory::GetInstance().UpdateDeviceList 枚举当前所有可用设备,获取一个设备信息列表,列表类型为 GxIAPICPP::gxdeviceinfo_vector。
  • 具体代码如下
int main()
{
    try {
        // 初始化相机实例
        IGXFactory::GetInstance().Init();

        // 使用GxIAPICPP列表类保存相关的信息
        GxIAPICPP::gxdeviceinfo_vector  vectorDeviceInfo;
        // 第一个参数是扫描的时长,第二个参数是将获取的信息保存到对应的列表中
        IGXFactory::GetInstance().UpdateDeviceList(10000,vectorDeviceInfo);
        cout << "the camera num:" << vectorDeviceInfo.size() << endl;
        for (int i = 0; i < vectorDeviceInfo.size(); i++) {
            cout << vectorDeviceInfo[i].GetVendorName() << endl;
            cout << vectorDeviceInfo[i].GetModelName() << endl;
        }


        // 相机的反初始化,释放所有占有的资源
        IGXFactory::GetInstance().Uninit();
    }
    catch (CGalaxyException&e) {
        cout << "error code " << e.GetErrorCode() << endl;
        cout << "error description" << e.what() << endl;
    }
   


    std::cout << "Hello World!\n";
}

开关设备

  • 控制设备关闭或者打开,由于这里使用的是ME2P-1230-23U3M/C相机,是通过USB3.0接口进行控制,并不是千兆网相机,所以MAC地址和IP地址都是空的,

在这里插入图片描述

  • 控制相机关闭打开总共有四种方式
      1. SN 为设备序列号。
      1. UserID 为用户自定义名称(不支持 UserID 的设备此项为空字符串)。
      1. MAC 为设备 MAC 地址(非千兆网相机此项为空字符串)。
      1. IP 为设备 IP 地址(非千兆网相机此项为空字符串)。
  • 打开对应函数的对应函数接口是
    • IGXFactory::GetInstance().OpenDeviceBySN
    • IGXFactory::GetInstance().OpenDeviceByUserID
    • IGXFactory::GetInstance().OpenDeviceByMAC
    • IGXFactory::GetInstance().OpenDeviceByIP
  • 关闭对应相机的函数如下
//关闭设备之后不允许再调用 IDevice 以及设备的 IFeatureControl、IStream 的所有接口
objDevicePtr->Close();
  • 最终的代码,我手上还没有相机,老师就给我代码让我先看一下,这里参考的是官方的参考手册代码
GxIAPICPP::gxdeviceinfo_vector vectorDeviceInfo;
IGXFactory::GetInstance().UpdateDeviceList(1000, vectorDeviceInfo);
if (vectorDeviceInfo.size()> 0)
{
//打开链表中的第一个设备
CGXDevicePointerobjDevicePtr;
GxIAPICPP::gxstringstrSN = vectorDeviceInfo[0].GetSN();
GxIAPICPP::gxstringstrUserID = vectorDeviceInfo[0].GetUserID();
GxIAPICPP::gxstringstrMAC = vectorDeviceInfo[0].GetMAC();
GxIAPICPP::gxstringstrIP = vectorDeviceInfo[0].GetIP();
//用户也可以直接指定打开的设备信息,下面代码中使用的信息为伪造信息,用户以实际设备为准
//GxIAPICPP::gxstring strSN = "GA0140100002";
//GxIAPICPP::gxstring strUserID = "MyUserName";
//GxIAPICPP::gxstring strMAC = "A1-0B-32-7C-6F-81";
//GxIAPICPP::gxstring strIP = "192.168.0.100";
objDevicePtr = IGXFactory::GetInstance().OpenDeviceBySN(strSN, GX_ACCESS_EXCLUSIVE);
//objDevicePtr = IGXFactory::GetInstance().OpenDeviceByUserID(strUserID, 
//GX_ACCESS_EXCLUSIVE);
//objDevicePtr = IGXFactory::GetInstance().OpenDeviceByMAC(strMAC, 
//GX_ACCESS_EXCLUSIVE);
//objDevicePtr = IGXFactory::GetInstance().OpenDeviceByIP(strIP, 
//GX_ACCESS_EXCLUSIVE);
}

属性控制

  • 这部分东西比较琐碎,并且不是重点,就简单写一下

属性控制器种类

  • 主要是通过IGXFeatureControl进行属性控制,分别是有两类控制对象,分别是设备Device和流Stream
      1. IGXFeatureControl IGXDevice::GetRemoteFeatureControl //包含主要设备信息,比如宽高、曝光增益等,一般用户主要使用此属性控制器即可
      1. IGXFeatureControl IGXDevice::GetFeatureControl //包含一些本地属性,不同类型的设备具备的功能也不一样。
      1. IGXFeatureControl IGXStream::GetFeatureControl //流对象属性控制器,关于采集控制和采集数据统计的属性访问控制器

图像采集控制和图像处理

  • 所有和图像采集和控制的相关接口都在CGXStreamPointer指定的对象上,获取和打开流对象的方法是通过这个流对象来获得,但是这个流对象是通过设备对象获得,设备对象打开之后返回的就是流对象,具体如下,更详细的在上一节
objDevicePtr = IGXFactory::GetInstance().OpenDeviceBySN(strSN, GX_ACCESS_EXCLUSIVE);
  • 基本操作,是枚举并获取对应的设备,然后获取设备对应的流,然后打开流才能进行图片采集。

获取设备之后,需要打开设备对象的流OpenStream,具体代码如下

uint32_t_t nStreamNum = objDevicePtr->GetStreamCount();
if (nStreamNum > 0)
{
CGXStreamPointer objStreamPtr = objDevicePtr->OpenStream(0);
//流对象控制或者采集
//当用户不使用流对象的时候,需要将其关闭
objStreamPtr->Close();
}

采单帧

  • 用户开启流对象采集,并且给设备发送采集命令,就而可以调用GetImage接口采集单帧
  • 具体流程如下
    • 打开流通道
    • 发送采集命令
    • 开始采集,采单帧
    • 获取图片并进行处理
    • 停采
    • 关闭流通道
  • 注意:不适用高清相机的快速采集
// 打开对应设备对应的流
CGXStreamPointer objStreamPtr = objDevicePtr->OpenStream();

// 开启流通道的采集命令
objStreamPtr->StartGrab();

//给设备发送采集命令,进行开采
CGXFeatureControlPointer objFeatureControlPtr = objDevicePtr->GetRemoteFeatureControl();
objFeatureControlPtr ->GetCommandFeature("AcquisitionStart")->Execute();

//采单帧
CImageDataPointer objImageDataPtr;

objImageDataPtr = objStreamPtr->GetImage(500);//超时时间使用 500ms,用户可以自行设定
if (objImageDataPtr->GetStatus() == GX_FRAME_STATUS_SUCCESS)
{
//采图成功而且是完整帧,可以进行图像处理 ...
}
//停采
objFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute();
objStreamPtr->StopGrab();
//关闭流通道
objStreamPtr->Close();



回调采集

  • 回调采集:当图片已经可以获取,或者当目标已经就位的时候,会自动调用一个函数,来处理存储对应的图片。很符合我们的应用场景。
  • 在大恒摄像中的回调处理虚基类是ICaptureEventHandler,如果要实现对应的回调采集,需要继承并实现虚基类
class CSampleCaptureEventHandler : public ICaptureEventHandler
{
	public:
	void DoOnImageCaptured(CImageDataPointer& objImageDataPointer, void* pUserParam)
	{
	if (objImageDataPointer->GetStatus() == GX_FRAME_STATUS_SUCCESS)
		{
			//图像获取为完整帧,可以读取图像宽、高、数据格式等
			uint64_t nWidth = objImageDataPointer->GetWidth();
			uint64_t nHeight = objImageDataPointer->GetHeight();
			GX_PIXEL_FORMAT_ENTRY emPixelFormat =
			objImageDataPointer->GetPixelFormat();
			//其他图像信息的获取参见 IImageData 接口定义
		}
	}
};
  • 定义完自己的回调处理程序之后,需要将对应的函数注册到回调采集函数中
// 打开设备的输入流
CGXStreamPointer objStreamPtr = objDevicePtr->OpenStream(0);

//注册采集回调函数,注意第一个参数是用户私有参数,用户可以传入任何 object 对象,也可以是 null
//用户私有参数在回调函数内部还原使用,如果不使用私有参数,可以传入 null
// 创建一个自己定义的回调函数的实例对象
ICaptureEventHandler* pCaptureEventHandler = new CSampleCaptureEventHandler();
// 将对应的实例采集对象注册到回调采集函数中
objStreamPtr->RegisterCaptureCallback(pCaptureEventHandler,NULL);

//开启流通道采集
objStreamPtr->StartGrab();
//给设备发送开采命令
CGXFeatureControlPointer objFeatureControlPtr =
objDevicePtr->GetRemoteFeatureControl();
objFeatureControlPtr->GetCommandFeature("AcquisitionStart")->Execute();
//回调采集过程,参见回调函数

//停采、注销采集回调函数
objFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute();
objStreamPtr->StopGrab();
objStreamPtr->UnregisterCaptureCallback();
delete pCaptureEventHandler;
pCaptureEventHandler = NULL;
//关闭流通道
objStreamPtr->Close();

图像处理

  • 在大恒相机的图片处理中,可以实现如下功能

    • 图像格式转换:将任何数据转成指定获取的8位有效数字或者是RGB的24位
    • 图像效果增强:可以实现对图片的坏点矫正、锐化、对比度、亮度等图像效果增强的操作
  • 具体的实现方式有两种

  • 设置调试的配置文件,然后直接进行调试

//通过设备对象构建图像处理配置对象
CImageProcessConfigPointer objImageProcessConfigPtr = objDevicePtr->CreateImageProcessConfig();
//objImageDataPtr 可以是采集回调函数传入的还可以是 GetImage 获取的
void*pRGB24Processed = NULL;
//返回结果就是经过图像效果增强之后的 RGB24 格式的数据
pRGB24Processed = objIBaseData>ImageProcess(objImageProcessConfigPtr);
  • 调用语句进行微调
//通过设备对象构建图像处理配置对象
CImageProcessConfigPointer objImageProcessConfigPtr =
objDevicePtr->CreateImageProcessConfig();
//objImageProcessConfigPtr 对象在构建的时候会初始化默认配置参数,用户可以选择对配置
//参数进行微调,如下:
objImageProcessConfigPtr->SetValidBit(GX_BIT_0_7);
//选择有效数据位 0~7
objImageProcessConfigPtr->EnableDefectivePixelCorrect(true);//使能坏点校正功能
objImageProcessConfigPtr->EnableSharpen(true);//使能锐化
objImageProcessConfigPtr->SetSharpenParam(1);//设置锐化强度因子 1
objImageProcessConfigPtr->SetContrastParam(0);//设置对比度调节参数
objImageProcessConfigPtr->SetGammaParam(1);//设置 Gamma 系数
objImageProcessConfigPtr->SetLightnessParam(0);//设置亮度调节参数
objImageProcessConfigPtr->EnableDenoise(true);//使能降噪开关(黑白相机不支持)

流对象属性控制

  • 我们是通过流对象来控制设备进行图片采集的,也是通过流对象来控制相机采集相关的属性和统计信息
  • 对于流属性的控制,主要是通过IGXStream进行控制的
//objGXStream 为通过 IGXDevice::OpenStream 获取到的 CGXStreamPointer 对象
CGXFeatureControlPointer objStreamFeatureControlPtr = objGXStream->GetFeatureControl();
//查看采集统计信息
//buffer 不足导致丢帧数
objStreamFeatureControlPtr->GetIntFeature("StreamLostFrameCount")->GetValue();
//接收的残帧个数
objStreamFeatureControlPtr->GetIntFeature("StreamIncompleteFrameCount")->GetValue();
//接收到的包数
objStreamFeatureControlPtr->GetIntFeature("StreamDeliveredPacketCount")->GetValue();
//重传包个数
objStreamFeatureControlPtr->GetIntFeature("StreamResendPacketCount")->GetValue();
//设置采集配置参数
//设置块超时时间 200ms
objStreamFeatureControlPtr->GetIntFeature("BlockTimeout")->SetValue(200);
  • 通过改变流对象属性中“StreamBufferHandlingMode”可以设置 Buffer 的处理模式,Buffer 处理模式目前支持三种
    • 1)OldestFirst:默认值。图像缓冲区遵守先进先出的原则,所有的缓冲区全部填满后,新的图像数据会被丢弃,直到用户完成已经填满图像数据的缓冲区处理。典型应用场景是,要求接收到相机采集的每帧图像,不丢帧。该模式实现不丢帧,还需要图像数据的传输与处理的速度尽量快(至少小于帧周期)。
    • 2)OldestFirstOverwrite:同样遵守先进先出的原则。与 OldestFirst 模式的区别是,当所有的缓冲区全部填满后,SDK 将主动丢弃缓冲区中时间戳最旧的一帧图像缓冲区,用于接收新的图像数据。典型的应用成绩是,不要求接收相机采集的每帧图像,应用环境下图像传输与处理速度较慢。
    • 3)NewestOnly:该模式下用户拿到的始终是 SDK 接收到的最新图。SDK 每接收到一帧新的图像数据,就会主动丢弃旧时间戳的图像,因此当用户图像处理不及时或者速度较慢时,就会出现丢帧。该模式主要应用场合是,对图像采集与显示实时性要求比较高,且不要求接收到相机采集的每帧图像。但是受相机的采集帧率和内部缓存,以及传输速度、用户使用场景的限制,SDK 接收的最新图与相机最新曝光的图像可能有延迟。

获取设备事件

  • 在回调函数中,可以获取设备发生的具体事件,并进行相关的处理。可以获取的五类事件如下

在这里插入图片描述

  • 获取设备事件之后,指定对应的回调函数,然后在进行注册,相关设备事件发生之后,会自动调用相关的处理函数

  • 下述代码是定义了设备发生曝光事件的处理函数

classCSampleFeatureEventHandler : public IFeatureEventHandler
{
	public:void DoOnFeatureEvent(
		constGxIAPICPP::gxstring& strFeatureName, void* pUserParam)
	{
		cout <<"发生曝光结束事件!"<<endl;
		//pUserParam 是用户注册回调函数的时候传入的 ,此处将其还原用来获取事件数据
		CGXFeatureControlPointer* pObjFeatureControlPtr =(CGXFeatureControlPointer*)pUserParam;
		//获取曝光结束事件时间戳
		(*pObjFeatureControlPtr)->GetIntFeature("EventExposureEndTimestamp")->GetValue();
		//获取曝光结束事件帧 ID
		(*pObjFeatureControlPtr)->GetIntFeature("EventExposureEndFrameID")->GetValue();
	}
};
  • 下述代码为具体的注册回调函数
//objDevicePtr 为 CGXDevicePointer 设备对象,设备已经打开
//设备事件属性在远端设备属性控制器上,首先应该获取远端设备属性控制器
CGXFeatureControlPointer objFeatureControlPtr =
objDevicePtr->GetRemoteFeatureControl();
//选择事件源
objFeatureControlPtr->GetEnumFeature("EventSelector")->SetValue(
"ExposureEnd");
//使能事件
objFeatureControlPtr->GetEnumFeature(
"EventNotification")->SetValue("On");
//注册事件回调函数,注意参数三是用户私有参数,用户可以传入任何指针
//此处我们演示传入属性控制器指针,因为稍后会在回调函数内部使用此对象获取曝光结束事
//件数据信息
//此私有参数在回调函数内部可以被还原供用户使用 ,如果用户不使用私有参数,可以简单的将
//此参数设置为 NULL
GX_FEATURE_CALLBACK_HANDLE hEventHandle = NULL;
IFeatureEventHandler* pFeatureEventHandler =
new CSampleFeatureEventHandler();
hEventHandle = objFeatureControlPtr->RegisterFeatureCallback(
"EventExposureEnd",pFeatureEventHandler,&objFeatureControlPtr);
//开启流通道采集
objStreamPtr->StartGrab();
//给设备发送开采命令
objFeatureControlPtr->GetCommandFeature("AcquisitionStart")->Execute();

//发送开采命令,相机开始曝光输出图像,当曝光结束的时候会产生曝光结束事件,此时就会
//激活回调 OnFeatureCallback 接口
//接收曝光结束事件,见 OnFeatureCallback
//发送停采命令
objFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute();
objStreamPtr->StopGrab();
//注销事件
objFeatureControlPtr->UnregisterFeatureCallback(objEventHandle);
delete pFeatureEventHandler;
pFeatureEventHandler = NULL;

获取掉线事件通知

  • 这个和回调采集的道理是一样,发生了掉线事件之后,会自动调用这些函数进行反馈
    在这里插入图片描述
  • 将自己定义的回调函数进行注册的代码

在这里插入图片描述

  • 这个比较特殊,如果要关闭设备,需要提前注销事件

在这里插入图片描述

样例程序分析

  • 当前这部分用来展示一个完整的控制台程序,实现了三个功能,分别是
    • 注册掉线设备:定义设备掉线的处理方案
    • 注册远端设备事件:定义远端设备发生发生某个事件之后的处理方案
    • 注册采集回调事件:定义图片采集之后的处理事件
#include "stdafx.h"
#include <isostream>

// 这里需要提前配置好工程头文件,这个头文件基本上包含了所有的头文件,加上这个了就不需要在二次调用了
#include "GalaxyIncludes.h"

// 用户定义掉线的处理事件,设备掉线会自动调用的程序
// 需要继承并实现虚基类:IDeviceOfflineEventHandler
class CSampleDeivceOfflineEventHandler:public IDeviceOfflineEventHandler{
public:
	// pUserParam用户传入的参数
	void DoOnDeviceOfflineEvent(void *pUserParam){
		cout<<"设备已经掉线了,请注意处理"<<endl;
	}
}

// 用户定义属性更新事件的处理函数,当属性发生改变时,自动调用该函数
// 需要继承并实现虚基类
class CSampleCaptureEventHandler:Public ICaptureEventHandler{
public:
	void DoOnFeatureEvent(const GxIAPICPP:gxstring &strFeatureName,void *pUserParam){
		cout<<"收到曝光事件"<<endl;
	}

}

// 用户定义回调采集函数的具体实现,当回调采集事件发生时,自动调用该函数
// 需要继承实现虚基类
class CSampleCaptureHandler : public ICaptureEventHandler{

public:
	void DoOnImageCapture(CImageDataPointer &objImageDataPointer,void * pUserParam){
		cout<<"收到一帧图像 !"<<endl;
		cout<<"ImageInfo: "<<objImageDataPointer->GetStatus() <<endl;
		cout<<"ImageInfo: "<<objImageDataPointer->GetWidth() <<endl;
		cout<<"ImageInfo: "<<objImageDataPointer->GetHeight() <<endl;
		cout<<"ImageInfo: "<<objImageDataPointer->GetPayloadSize() <<endl;
	}
}

// main函数需要注册掉线事件、属性变动事件以及采集回调事件
int main(int argc,_TCHAR* argv[]){

	//定义事件回调的指针
	IDeviceOfflineEventHandler* pDeviceOfflineEventHandler = NULL;//<掉线事件回调对象
	IFeatureEventHandler* pFeatureEventHandler = NULL;//<远端设备事件回调对象
	ICaptureEventHandler* pCaptureEventHandler = NULL;//<采集回调对象

	// 初始化库,才能调用相关的功能
	IGXFactory::GetInstance().Init()

	try
	{
		do
		{
			//枚举设备
			gxdeviceinfo_vector vectorDeviceInfo;
			IGXFactory::GetInstance().UpdateDeviceList(1000, vectorDeviceInfo);
			if (0 == vectorDeviceInfo.size())
			{
				cout<<"无可用设备!"<<endl;
				break;
			}
			//打开第一台设备以及设备下面第一个流
			CGXDevicePointer ObjDevicePtr = IGXFactory::GetInstance().OpenDeviceBySN(vectorDeviceInfo[0].GetSN(),GX_ACCESS_EXCLUSIVE);
			CGXStreamPointer ObjStreamPtr = ObjDevicePtr->OpenStream(0);
			//获取远端设备属性控制器
			CGXFeatureControlPointer ObjFeatureControlPtr =
			ObjDevicePtr->GetRemoteFeatureControl();
			//获取流层属性控制器
			CGXFeatureControlPointer objStreamFeatureControlPtr =
			ObjStreamPtr->GetFeatureControl();
			//设置 Buffer 处理模式
			objStreamFeatureControlPtr->GetEnumFeature("StreamBufferHandlingMode")->SetValue("OldestFirst");
			
			//注册设备掉线事件(目前只有千兆网系列相机支持此事件通知 )
			GX_DEVICE_OFFLINE_CALLBACK_HANDLE hDeviceOffline = NULL;
			pDeviceOfflineEventHandler =new CSampleDeviceOfflineEventHandler();
			hDeviceOffline = ObjDevicePtr->RegisterDeviceOfflineCallback(pDeviceOfflineEventHandler, NULL);

			//设置曝光时间(示例中写死 us,只是示例,并不代表真正可工作参数)
			//ObjFeatureControlPtr->GetFloatFeature("ExposureTime")->SetValue(50);
			//注册远端设备事件:曝光结束事件(目前只有千兆网系列相机支持曝光结束事件 )
			//选择事件源
			ObjFeatureControlPtr->GetEnumFeature("EventSelector")->SetValue("ExposureEnd");
			//使能事件
			ObjFeatureControlPtr->GetEnumFeature("EventNotification")->SetValue("On");
			GX_FEATURE_CALLBACK_HANDLE hFeatureEvent = NULL;
			pFeatureEventHandler = new CSampleFeatureEventHandler();
			hFeatureEvent = ObjFeatureControlPtr->RegisterFeatureCallback(
				"EventExposureEnd", pFeatureEventHandler, NULL);
			
			//注册回调采集
			pCaptureEventHandler = new CSampleCaptureEventHandler();
			ObjStreamPtr->RegisterCaptureCallback(pCaptureEventHandler,NULL);
			
			//发送开采命令
			ObjStreamPtr->StartGrab();
			ObjFeatureControlPtr->GetCommandFeature("AcquisitionStart")->Execute();

			//此时开采成功,控制台打印信息,直到输入任意键继续
			getchar();
			
			//发送停采命令
			ObjFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute();
			ObjStreamPtr->StopGrab();

			//注销采集回调
			ObjStreamPtr->UnregisterCaptureCallback();

			//注销远端设备事件
			ObjFeatureControlPtr->UnregisterFeatureCallback(hFeatureEvent);

			//注销设备掉线事件
			ObjDevicePtr->UnregisterDeviceOfflineCallback(hDeviceOffline);
			
			//释放资源
			ObjStreamPtr->Close();
			ObjDevicePtr->Close();
		} while (0);
	}
	catch(CGalaxyException&e)
	{
		cout<<"错误码: "<<e.GetErrorCode() <<endl;
		cout<<"错误描述信息 : "<<e.what() <<endl;
	}
	catch(std::exception&e)
	{
		cout<<"错误描述信息 : "<<e.what() <<endl;
	}
	
	//反初始化库
	IGXFactory::GetInstance().Uninit();

	//销毁事件回调指针
	if (NULL != pCaptureEventHandler)
	{
		delete pCaptureEventHandler;
		pCaptureEventHandler = NULL;
	}
	if (NULL != pDeviceOfflineEventHandler)
	{
		delete pDeviceOfflineEventHandler;
		pDeviceOfflineEventHandler = NULL;
	}
	if (NULL != pFeatureEventHandler)
	{
		delete pFeatureEventHandler;
		pFeatureEventHandler = NULL;
	}
	return 0;
}

补充:项目中常用库函数

CINI库

  • 介绍:专门用来处理INI文件的C++库,INI是一种简单的数据存储格式,用于存储应用程序的配置信息
  • 主要特性
    • 读取和写入INI文件:CINI库提供了函数来读取和写入INI文件。这使得你可以在你的程序中方便地使用INI文件来存储和检索配置信息。
    • 支持多种数据类型:CINI库支持多种数据类型,包括整数、浮点数、字符串等。这使得你可以在INI文件中存储各种类型的数据。
    • 错误处理:CINI库提供了错误处理机制,可以帮助你检测和处理可能出现的错误。
    • 跨平台:CINI库可以在多种操作系统上使用,包括Windows、Linux等。

总结

  • 目前没有设备,就不看他的说明文档了,等我手里 有具体的相机了,再继续开始写一些控制相机的基础代码了,这里直接去看老师给的代码了, 不往外放了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/812592.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

6.3.tensorRT高级(1)-yolov5模型导出、编译到推理(无封装)

目录 前言1. YOLOv5导出2. YOLOv5推理3. 补充知识总结 前言 杜老师推出的 tensorRT从零起步高性能部署 课程&#xff0c;之前有看过一遍&#xff0c;但是没有做笔记&#xff0c;很多东西也忘了。这次重新撸一遍&#xff0c;顺便记记笔记。 本次课程学习 tensorRT 高级-yolov5模…

复习之linux高级存储管理

一、lvm----逻辑卷管理 1.lvm定义 LVM是 Logical Volume Manager&#xff08;逻辑卷管理&#xff09;的简写&#xff0c;它是Linux环境下对磁盘分区进行管理的一种机制。 逻辑卷管理器(LogicalVolumeManager)本质上是一个虚拟设备驱动&#xff0c;是在内核中块设备和物理设备…

内网隧道代理技术(十五)之 Earthworm的使用(二级代理)

Earthworm的使用(二级代理) 本文紧接着上一篇文章继续讲解Earthworm工具的使用 (二级代理)正向连接 二级正向代理发生在如下的情况: 1、Web服务器在公网,黑客可以直接访问 2、B机器在内网,黑客不能直接访问 3、Web服务器可以访问内网机器B 4、内网机器B可以访问公司…

jdk1.7与jdk1.8的HashMap区别1-基本结构与属性对比

一、数据结构差别 1.7&#xff1a;数组链表 1.8&#xff1a;数组链表红黑树 当链表的长度大于8时&#xff0c;数组长度大于64&#xff0c;原来的链表数据结构变为红黑树 二、HashMap中的关键属性和方法区别 方法/变量/类 JDK7 JDK8 备注 DEFAULT_INITIAL_CAPACITY 16 16…

js中的设计模式

设计模式 代码整体的结构会更加清楚&#xff0c;管理起来会更加方便&#xff0c;更好地维护 设计模式是一种思想 发布订阅 模块化开发 导入很多模块 容器即数组存储未来要执行的方法&#xff0c;同addEventListener 数组塌陷问题* 由于删除了元素&#xff0c;导致从删除元素的位…

【网络】应用层——HTTP协议

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《网络》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; &#x1f3c0;认识HTTP协议 上篇文章中&#xff0c;本喵带着大家对HTTP有了一个初步的认识&#xff0…

Java进阶之Dump文件初体验

视频地址&#xff1a;https://www.bilibili.com/video/BV1Ak4y137oh 学习文章&#xff1a;https://d9bp4nr5ye.feishu.cn/wiki/VQoAwlzrXiLFZekuLIyc1uK5nqc 最近线上频繁的内存告警&#xff0c;同事A通过分析dump文件解决了这个问题&#xff0c;我当然是不会放过这种学习的机…

【C++】做一个飞机空战小游戏(三)——模块化程序设计

[导读]本系列博文内容链接如下&#xff1a; 【C】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值 【C】做一个飞机空战小游戏(二)——利用getch()函数实现键盘控制单个字符移动【C】做一个飞机空战小游戏(三)——模块化程设设计 在前两讲当中&#xff0c;介绍了利用…

深度学习实践——模型推理优化练习

系列实验 深度学习实践——卷积神经网络实践&#xff1a;裂缝识别 深度学习实践——循环神经网络实践 深度学习实践——模型部署优化实践 深度学习实践——模型推理优化练习 深度学习实践——模型推理优化练习 模型推理优化练习架构设计练习知识蒸馏练习模型剪枝练习参数量化练…

【PWN · 栈迁移】[BUUCTF]ciscn_2019_es_2

第一道栈迁移题目&#xff0c;跌跌撞撞理解了 前言 当前溢出可用空间比较少时&#xff08;极端情况下仅能覆写ebp和ret&#xff09;&#xff0c;可以通过栈迁移的方式&#xff0c;扩大shellcode的容纳空间&#xff0c;其核心是将esp移动到一段shellocode开头。而esp总是由ebp赋…

【我们一起60天准备考研算法面试(大全)-第二十九天 29/60】【二进制】

专注 效率 记忆 预习 笔记 复习 做题 欢迎观看我的博客&#xff0c;如有问题交流&#xff0c;欢迎评论区留言&#xff0c;一定尽快回复&#xff01;&#xff08;大家可以去看我的专栏&#xff0c;是所有文章的目录&#xff09;   文章字体风格&#xff1a; 红色文字表示&#…

【SpringBoot】18张图,详解SpringBoot解析yml全流程

文章目录 加载监听器执行run方法加载配置文件封装Node调用构造器思考 前几天的时候&#xff0c;项目里有一个需求&#xff0c;需要一个开关控制代码中是否执行一段逻辑&#xff0c;于是理所当然的在yml文件中配置了一个属性作为开关&#xff0c;再配合nacos就可以随时改变这个值…

基于RASC的keil电子时钟制作(瑞萨RA)(6)----定时器驱动数码管

基于RASC的keil电子时钟制作6_定时器驱动数码管 概述硬件准备视频教程选择定时器定时器做计数器配置定时器回调函数timer_smg.ctimer_smg.h演示效果主程序 概述 要想让每个数码管显示不同的数字&#xff0c;但是数码管必须依次地被持续驱动&#xff0c;数码管之间的刷新速度应…

KY222 打印日期+KY111日期差值

一、KY222题目 二、代码 #include <climits> #include <iostream> using namespace std; class Date{public:Date(int year 1,int month 2,int day 3){_year year;_month month;_day day;}int GetDay(int year ,int month);void Define(int n);public:int _yea…

mysql的json处理

写在前面 需要注意&#xff0c;5.7以上版本才支持&#xff0c;但如果是生产环境需要使用的话&#xff0c;尽量使用8.0版本&#xff0c;因为8.0版本对json处理做了比较大的性能优化。你你可以使用select version();来查看版本信息。 本文看下MySQL的json处理。在正式开始让我们先…

从使用回溯分割字符串的技巧到前向搜索

题目 131. 分割回文串 给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个子串都是 回文串 。返回 s 所有可能的分割方案。 回文串 是正着读和反着读都一样的字符串。 答案&#xff1a; class Solution {boolean[][] f;List<List<String>>…

【多模态】21、BARON | 通过引入大量 regions 来提升模型开放词汇目标检测能力

文章目录 一、背景二、方法2.1 主要过程2.2 Forming Bag of Regions2.3 Representing Bag of Regions2.4 Aligning bag of regions 三、效果 论文&#xff1a;Aligning Bag of Regions for Open-Vocabulary Object Detection 代码&#xff1a;https://github.com/wusize/ovdet…

彻底理解Java中的各种锁

1、乐观锁 乐观锁是一种乐观思想&#xff0c;假定当前环境是读多写少&#xff0c;遇到并发写的概率比较低&#xff0c;读数据时认为别的线程不会正在进行修改&#xff08;所以没有上锁&#xff09;。写数据时&#xff0c;判断当前 与期望值是否相同&#xff0c;如果相同则进行…

linux(centos) docker 安装 nginx

​1、拉取nginx最新版本镜像 docker pull nginx:latest 查看镜像 docker images 或者 docker images -a 2.启动nginx容器 docker run -d -p 80:80 --name nginx nginx 使用docker run命令&#xff0c;启动nginx容器。 --name&#xff0c;设置容器名。为方便记忆&#xff…

【TypeScript】TS入门及基础学习(一)

【TypeScript】TS入门及基础学习&#xff08;一&#xff09; 【TypeScript】TS入门及基础学习&#xff08;一&#xff09;一、前言二、基本概念1.强类型语言和弱类型语言2.动态语言和静态语言 三、TypeScript与JavaScript的区别四、环境搭建及演练准备4.1 安装到本地4.2 在线运…