首先学习Aravis 库和CDevice,
Aravis 是实现相机通信的 底层工具,直接与硬件交互。
CDevice 是应用层的 抽象接口,通过封装 Aravis 或其他 SDK,提供统一的设备操作方式。
关系:CDevice 的子类(如 CGige)使用 Aravis 实现具体功能,但对上层代码隐藏了底层细节。
namespace GigeAravis
{
class ARAVIS_API CDevice
{
public:
CDevice();
virtual ~CDevice();
virtual void OnInitialize() = 0;
protected:
ArvCamera* m_pGige;
tagGigeInfo m_info;
tagGigeParam m_param;
m_pGige 是 Aravis 库的核心相机对象,用于与相机硬件交互
tagGigeInfo 和 tagGigeParam 是自定义结构体:
tagGigeInfo 包含相机标识、IP 地址、基本尺寸等信息
tagGigeParam 包含相机的各种可配置参数和范围
下面是该三个变量的定义
struct tagGigeInfo包含设备索引、尺寸、ID、网络信息
{
int index;
int width;
int height;
tagGigeID id;
tagGigeStr vendor;
tagGigeStr manufacturer;
tagGigeStr model;
tagGigeStr serial;
tagGigeIP ip;
tagGigeIP mask;
tagGigeIP gateway;
tagGigeStr mac;
tagGigeStr protocol;
tagGigeStr format;
};
tagGigeParam图像采集参数配置
struct tagGigeParam
{
int curWidth;
int minWidth;
int maxWidth;
int incWidth;
int curHeight;
int minHeight;
int maxHeight;
int incHeight;
int curFrameRate;
int minFrameRate;
int maxFrameRate;
BYTE autoBlackLevel;
int curBlackLevel;
int minBlackLevel;
int maxBlackLevel;
BYTE autoGain;
int curGain;
int minGain;
int maxGain;
BYTE ExposureMode;
BYTE autoExposureTime;
int curExposureTime;
int minExposureTime;
int maxExposureTime;
int nPixelFormatCount;
tagGigeStr curPixelFormat;
tagGigeStr PixelFormat[MAX_PF_COUNT];
};
下面依次看实现方式
扫描 → 选择设备 → 打开 → 获取参数 → 参数设置 → 采集
一.扫描
1.首先要遍历接口,遍历list
ARV_API unsigned int arv_get_n_devices (void);
2.根据索引(如 0、1、2)获取特定设备的详细信息(必须先调用 GetAllDevices() 获取设备列表/必须先通过 SetIndex() 或直接设置 m_info.id 指定目标设备)
GetDeviceInfo(unsigned int index)/GetDeviceInfo()(无参数版本)
3.获取相机的详细参数(如分辨率、帧率、像素格式等)(必须先调用 GetDeviceInfo() 且设备已成功打开(m_pGige 有效))
int GetBitCount();
int CDevice::GetBitCount()
{
int bits = 8;
GError* error = NULL;
ArvCamera* camera = m_pGige;
ArvPixelFormat pixel = arv_camera_get_pixel_format(camera, &error);
if (!error) bits = pixel >> 16 & 0xff;
g_clear_error(&error);
return bits;
}
int CDevice::GetBitCount() { int bits = 8; // 默认位深度设为8位
GError* error = NULL;
ArvCamera* camera = m_pGige; // 获取Aravis相机对象
// 获取相机的像素格式
ArvPixelFormat pixel = arv_camera_get_pixel_format(camera, &error); // 若获取成功(error为NULL),解析位深度
if (!error) bits = pixel >> 16 & 0xff; g_clear_error(&error); // 清理错误信息 return bits;
}
该方法通过 Aravis 库获取相机像素格式,并从中解析出位深度信息。位深度是图像采集的关键参数,直接影响图像质量、数据量和后续处理方式。在工业视觉应用中,正确获取位深度有助于合理配置图像处理流程和存储资源。
// 设备连接管理
virtual void Close(); // 关闭设备连接
COMMON_ERR Open(char* szMsg = NULL); // 按预存ID打开设备
COMMON_ERR Open(char* szPID, char* szMsg); // 按指定ID打开设备
// 信息获取
COMMON_ERR GetCameraInfo(); // 获取相机参数信息
COMMON_ERR GetDeviceInfo(); // 获取当前设备基础信息
COMMON_ERR GetDeviceInfo(unsigned int index); // 按索引获取设备信息
// 参数设置(像素格式/区域/帧率)
COMMON_ERR SetPixelFormat(const char* szValue, char* szMsg = NULL); // 设置像素格式
COMMON_ERR SetFrameRate(const int nFrameRate, char* szMsg = NULL); // 设置帧率
COMMON_ERR SetRegion(const int nWidth, const int nHeight, char* szMsg = NULL); // 设置采集区域
// 参数设置(增益/黑电平/曝光)
COMMON_ERR SetGain(const int nGain, char* szMsg = NULL); // 设置增益
COMMON_ERR SetAutoGain(ArvAuto autoValue, char* szMsg = NULL); // 设置自动增益模式
COMMON_ERR SetBlackLevel(const int nBlackLevel, char* szMsg = NULL); // 设置黑电平
COMMON_ERR SetAutoBlackLevel(ArvAuto autoValue, char* szMsg = NULL); // 设置自动黑电平模式
COMMON_ERR SetExposureTime(const int nExposureTime, char* szMsg = NULL); // 设置曝光时间
COMMON_ERR SetAutoExposureTime(ArvAuto autoValue, char* szMsg = NULL); // 设置自动曝光模式
// 内部辅助方法(保护成员)
void __GetBaseInfo(); // 获取相机基本属性
void __GetNetInfo(); // 获取网络配置
void __GetControlInfo(); // 获取控制参数
virtual void Close();
void CDevice::Close() {
if (Invalidate()) return; // 检查设备是否已无效(NULL)
g_object_unref(&m_pGige); // 减少Aravis相机对象的引用计数
g_clear_object(&m_pGige); // 确保对象被正确释放
m_pGige = NULL; // 将指针置为NULL,避免悬空指针 }
g_object_unref() 是 GLib 库中的函数,用于减少 GObject 对象的引用计数。
Aravis 库基于 GLib,其相机对象(ArvCamera)是 GObject 的子类。
当引用计数降为 0 时,对象会被自动销毁并释放资源。
g_clear_object() 是 GLib 提供的安全释放宏
二.选择设备
COMMON_ERR GetCameraInfo();
COMMON_ERR GetDeviceInfo();
COMMON_ERR GetDeviceInfo(unsigned int index);
COMMON_ERR GetDeviceInfo(unsigned int index);/COMMON_ERR GetDeviceInfo();
COMMON_ERR CDevice::GetDeviceInfo(unsigned int index)
{
COMMON_ERR nErrCode = COMMON_OK;
m_info.index = index;
const char* szID = arv_get_device_id(index);
if (szID) memcpy(m_info.id, szID, sizeof(tagGigeID));
const char* szVendor = arv_get_device_vendor(index);
if (szVendor) memcpy(m_info.vendor, szVendor, sizeof(tagGigeStr));
const char* szModel = arv_get_device_model(index);
if (szModel) memcpy(m_info.model, szModel, sizeof(tagGigeStr));
const char* szSerial = arv_get_device_serial_nbr(index);
if (szSerial) memcpy(m_info.serial, szSerial, sizeof(tagGigeStr));
const char* szManufacturer = arv_get_device_manufacturer_info(index);
if(szManufacturer) memcpy(m_info.manufacturer, szManufacturer, sizeof(tagGigeStr));
const char* szIP = arv_get_device_address(index);
if (szIP) memcpy(m_info.ip, szIP, sizeof(tagGigeIP));
const char* szMac = arv_get_device_physical_id(index);
if (szMac) memcpy(m_info.mac, szMac, sizeof(tagGigeStr));
const char* pp = arv_get_device_protocol(index);
if (pp) memcpy(m_info.protocol, pp, sizeof(tagGigeStr));
return nErrCode;
}
//——————————
COMMON_ERR CDevice::GetDeviceInfo()
{
COMMON_ERR nErrCode = COMMON_OK;
if (Invalidate()) return ERR_CAMERA_INVALID;
GError* error = NULL;
ArvCamera* camera = m_pGige;
const char* szVendor = arv_camera_get_vendor_name(camera, &error);
if (szVendor) memcpy(m_info.vendor, szVendor, sizeof(tagGigeStr));
const char* szModel = arv_camera_get_model_name(camera, &error);
if (szModel) memcpy(m_info.model, szModel, sizeof(tagGigeStr));
const char* szSerial = arv_camera_get_device_serial_number(camera, &error);
if (szSerial) memcpy(m_info.serial, szSerial, sizeof(tagGigeStr));
if (!error && szVendor && szModel && szSerial)
sprintf(m_info.id, “%s-%s-%s”, szVendor, szModel, szSerial);
else nErrCode = error->code;
g_error_free(error);
return nErrCode;
}
以外部index收到的参数来返回相机在列表中的位置,对对应的index进行参数获取标定来设计m_info。
COMMON_ERR GetCameraInfo();
COMMON_ERR CDevice::GetCameraInfo()
{
__GetBaseInfo();
__GetNetInfo();
__GetControlInfo();
return 0;
}
__GetBaseInfo():获取相机基本属性
__GetNetInfo():获取相机网络配置
__GetControlInfo():获取相机控制参数
void CDevice::__GetBaseInfo()
{
if (Invalidate()) return; // 检查相机是否已打开
GError* error = NULL;
ArvCamera* camera = m_pGige;
// 获取像素格式
const char* pp = arv_camera_get_string(camera, "PixelFormat", &error);
if (!error) memcpy(m_info.format, pp, sizeof(tagGigeStr));
// 获取图像宽度
int nWidth = arv_camera_get_integer(camera, "Width", &error);
if (!error && nWidth > 0) m_info.width = nWidth;
// 获取图像高度
int nHeight = arv_camera_get_integer(camera, "Height", &error);
if (!error && nHeight > 0) m_info.height = nHeight;
// 获取数据包延迟(GigE相机特有)
gint64 delay = arv_camera_gv_get_packet_delay(camera, &error);
g_error_free(error); // 释放错误信息
}
核心功能:
检查相机是否已打开(Invalidate() 检查 m_pGige 是否为 NULL)
使用 Aravis API 获取相机的像素格式、宽度和高度
特别针对 GigE 相机获取数据包延迟参数
所有操作都包含错误检查,确保安全性
void CDevice::__GetNetInfo()
{
if (Avalidate()) // 检查相机是否已打开
{
GError* error = NULL;
ArvCamera* camera = m_pGige;
GInetAddress* ip = NULL;
GInetAddressMask* mask = NULL;
GInetAddress* gateway = NULL;
// 获取相机的持久IP配置
arv_camera_gv_get_persistent_ip(camera, &ip, &mask, &gateway, &error);
if (!error)
{
// 转换并存储IP地址
char* szIP = g_inet_address_to_string(ip);
sprintf(m_info.ip, "%s", szIP);
// 转换并存储子网掩码
char* szMask = g_inet_address_mask_to_string(mask);
sprintf(m_info.mask, "%s", szMask);
// 转换并存储网关(注意:这里可能有错误,重复使用了ip变量)
char* szGate = g_inet_address_to_string(ip);
sprintf(m_info.gateway, "%s", szGate);
}
g_error_free(error); // 释放错误信息
}
}
核心功能:
检查相机是否已打开(Avalidate() 检查 m_pGige 是否非 NULL)
使用 Aravis API 获取相机的 IP 地址、子网掩码和网关
使用 GLib 函数将网络地址转换为字符串格式
注意到一个潜在问题:网关地址获取时错误地使用了 ip 变量,应该使用 gateway 变量
void CDevice::__GetControlInfo()
{
if (Invalidate()) return; // 检查相机是否已打开
GError* error = NULL;
ArvCamera* camera = m_pGige;
guint count = 0;
double dmin = 0, dmax = 0;
gint gmin = 0, gmax = 0;
// 获取像素格式信息
const char* pp = arv_camera_get_pixel_format_as_string(camera, &error);
if (!error) memcpy(m_param.curPixelFormat, pp, sizeof(tagGigeStr));
const char** ptr = arv_camera_dup_available_pixel_formats_as_strings(camera, &count, &error);
if (!error) m_param.nPixelFormatCount = count;
for (int i = 0; i < count && i < MAX_PF_COUNT; i++)
{
if (!error) memcpy(m_param.PixelFormat[i], ptr[i], sizeof(tagGigeStr));
}
// 获取帧率信息
double rate = arv_camera_get_frame_rate(camera, &error);
if (!error) m_param.curFrameRate = int(rate + 0.5); // 四舍五入转换为整数
arv_camera_get_frame_rate_bounds(camera, &dmin, &dmax, &error);
if (!error) m_param.minFrameRate = int(dmin + 0.5);
if (!error) m_param.maxFrameRate = int(dmax + 0.5);
// 获取增益信息
double dGain = arv_camera_get_gain(camera, &error);
if (!error) m_param.curGain = int(10 * dGain + 0.5); // 转换为整数(可能单位为0.1)
arv_camera_get_gain_bounds(camera, &dmin, &dmax, &error);
if (!error) m_param.minGain = int(10 * dmin + 0.5);
if (!error) m_param.maxGain = int(10 * dmax + 0.5);
// 检查增益自动功能是否可用
gboolean bAvailable = arv_camera_is_gain_available(camera, &error);
if (!error && bAvailable == 1)
{
gboolean bAutoable = arv_camera_is_gain_auto_available(camera, &error);
if (!error && bAutoable == 1)
{
ArvAuto autoGain = arv_camera_get_gain_auto(camera, &error);
if (!error) m_param.autoGain = autoGain;
}
else m_param.autoGain = ARV_AUTO_DISABLE;
}
else m_param.autoGain = ARV_FUNC_DISABLE;
// 获取曝光时间信息(类似增益处理逻辑)
double dtime = arv_camera_get_exposure_time(camera, &error);
if (!error) m_param.curExposureTime = int(dtime + 0.5);
arv_camera_get_exposure_time_bounds(camera, &dmin, &dmax, &error);
if (!error) m_param.minExposureTime = int(dmin + 0.5);
if (!error) m_param.maxExposureTime = int(dmax + 0.5);
// 检查曝光自动功能是否可用(逻辑同增益)
bAvailable = arv_camera_is_exposure_time_available(camera, &error);
if (!error && bAvailable == 1)
{
gboolean bAutoable = arv_camera_is_exposure_auto_available(camera, &error);
if (!error && bAutoable == 1)
{
ArvAuto autoExposureTime = arv_camera_get_exposure_time_auto(camera, &error);
if (!error) m_param.autoExposureTime = autoExposureTime;
}
else m_param.autoExposureTime = ARV_AUTO_DISABLE;
}
else m_param.autoExposureTime = ARV_FUNC_DISABLE;
// 获取图像区域信息(宽度和高度)
gint width = 0, height = 0;
arv_camera_get_region(camera, NULL, NULL, &width, &height, &error);
if (!error) m_param.curWidth = width;
if (!error) m_param.curHeight = height;
// 获取宽度和高度的范围和增量
arv_camera_get_width_bounds(camera, &gmin, &gmax, &error);
if (!error) m_param.minWidth = gmin;
if (!error) m_param.maxWidth = gmax;
arv_camera_get_height_bounds(camera, &gmin, &gmax, &error);
if (!error) m_param.minHeight = gmin;
if (!error) m_param.maxHeight = gmax;
width = arv_camera_get_width_increment(camera, &error);
if (!error) m_param.incWidth = width;
height = arv_camera_get_height_increment(camera, &error);
if (!error) m_param.incHeight = height;
// 获取黑电平信息
double BlackLevel = arv_camera_get_black_level(camera, &error);
if (!error) m_param.curBlackLevel = int(BlackLevel + 0.5);
arv_camera_get_black_level_bounds(camera, &dmin, &dmax, &error);
if (!error) m_param.minBlackLevel = int(dmin + 0.5);
if (!error) m_param.maxBlackLevel = int(dmax + 0.5);
// 检查黑电平自动功能是否可用(逻辑同增益)
if (error) g_clear_error(&error); error = NULL;
bAvailable = arv_camera_is_black_level_available(camera, &error);
if (!error && bAvailable == 1)
{
gboolean bAutoable = arv_camera_is_black_level_auto_available(camera, &error);
if (!error && bAutoable == 1)
{
ArvAuto autoBlackLevel = arv_camera_get_black_level_auto(camera, &error);
if (!error) m_param.autoBlackLevel = autoBlackLevel;
}
else m_param.autoBlackLevel = ARV_AUTO_DISABLE;
}
else m_param.autoBlackLevel = ARV_FUNC_DISABLE;
g_clear_error(&error); // 释放错误信息
}
核心功能:
像素格式管理:
获取当前像素格式
获取所有可用像素格式列表
帧率控制:
获取当前帧率
获取帧率范围
增益控制:
获取当前增益值(转换为整数,可能单位为 0.1)
获取增益范围
检查并获取增益自动功能状态
曝光时间控制:
获取当前曝光时间
获取曝光时间范围
检查并获取曝光自动功能状态
图像区域控制:
获取当前图像宽度和高度
获取宽度和高度的范围和增量
黑电平控制:
获取当前黑电平值
获取黑电平范围
检查并获取黑电平自动功能状态
实现特点:
所有操作都包含完整的错误检查
数值转换时使用四舍五入(int(value + 0.5))
自动功能的处理采用统一的逻辑模式
资源管理完善,最后释放错误信息
![图片[1] - Gige协议的二次开发 - 宋马](https://pic.songma.com/blogimg/20250715/632aabc1e9cb4d9daeb7ce4c65e67a18.png)
三. 打开
COMMON_ERR Open(char* szMsg = NULL);
COMMON_ERR Open(char* szPID, char* szMsg);
COMMON_ERR CDevice::Open(char* szMsg/*= NULL*/)
{
char* szPID = m_info.id; // 从类成员获取预存的设备ID
return Open(szPID, szMsg); // 调用带设备ID的重载版本
}
COMMON_ERR CDevice::Open(char* szPID, char* szMsg)
{
// 核心打开逻辑(见下文解析)
}
COMMON_ERR CDevice::Open(char* szMsg/*= NULL*/)
{
char* szPID = m_info.id;
return Open(szPID, szMsg);
}
//——————————
COMMON_ERR CDevice::Open(char* szPID, char* szMsg)
{
COMMON_ERR nErrCode = COMMON_OK;
GError* error = NULL;
ArvCamera* camera = m_pGige;
if (strlen(szPID) > 1)
{
if (Invalidate())
camera = arv_camera_new(szPID, &error);
if (camera)
{
m_pGige = camera;
if (strlen(m_info.id) < 1)
GetDeviceInfo();
GetCameraInfo();
}
if (error)
{
nErrCode = error->code;
if (szMsg) memcpy(szMsg, error->message, sizeof(tagErrMsg) – 1);
}
else if(szMsg) sprintf(szMsg, “%s”, “open camera access”);
}
else
{
nErrCode = ERR_PID_INVLAID;
if (szMsg) sprintf(szMsg, “%s”, “camera id /ip is invlaid”);
}
return nErrCode;
}
这一块没什么好说的,通过找到index来找相机,判定是否有效,有效就执行前面说的获取信息,初始化的一些操作 ,例如GetDeviceInfo();GetCam
eraInfo();
二次开发
void CSUCCES1Dlg::OnBnClickedBtnPhoto()
{
// [2] 拍照
lightSourceSwithOnOff(1, 0); // 开灯
__photo();
ShowGigeImage();
ShowNetStatus();
Sleep(100);
lightSourceSwithOnOff(1,1); // 关灯
}
关于PhotoImage
COMMON_ERR CGige::PhotoImage(char* szMsg/*= NULL*/)
{
// 检查相机是否有效,如果无效则返回错误
if (Invalidate()) return ERR_CAMERA_INVALID;
COMMON_ERR nErrCode = COMMON_OK;
// 创建GError对象用于错误处理
GError* error = NULL;
// 获取相机对象指针
ArvCamera* camera = m_pGige;
// 获取图像的位深度,并确保其有效性
int bits = GetBitCount();
m_nBitCount = (bits >= 24) ? bits : 8;
// 获取图像的宽度和高度
int width = arv_camera_get_integer(camera, "Width", NULL);
int height = arv_camera_get_integer(camera, "Height", NULL);
// 选择数据流通道0
arv_camera_gv_select_stream_channel(camera, 0, NULL);
// 设置采集模式为单帧采集
arv_camera_set_acquisition_mode(camera, ARV_ACQUISITION_MODE_SINGLE_FRAME, NULL);
// 获取相机数据有效载荷大小
guint payload = arv_camera_get_payload(camera, NULL);
// 创建数据流对象
ArvStream* stream = arv_camera_create_stream(camera, NULL, NULL, &error);
// 如果流创建成功且有效载荷大于0
if (stream && payload > 0)
{
// 为数据流推送两个缓冲区用于接收图像数据
for (int i = 0; i < 2; i++)
arv_stream_push_buffer(stream, arv_buffer_new(payload, NULL));
// 初始化速率和速度测量
InitRateSpeed();
// 开始采集图像
arv_camera_start_acquisition(camera, &error);
// 如果开始采集时没有错误
if (!error)
{
// 从流中获取一个缓冲区(即一帧图像)
ArvBuffer* buffer = arv_stream_pop_buffer(stream);
// 如果成功获取缓冲区且状态正常
if (buffer && arv_buffer_get_status(buffer) == ARV_BUFFER_STATUS_SUCCESS)
{
// 保存缓冲区中的图像数据
SaveBuffer(buffer);
}
// 释放缓冲区资源
if (buffer) g_clear_object(&buffer);
}
// 停止图像采集
arv_camera_stop_acquisition(camera, NULL);
}
// 检查是否有错误发生
if (error)
{
// 保存错误码
nErrCode = error->code;
// 如果提供了错误信息缓冲区,则复制错误信息
if (szMsg) memcpy(szMsg, error->message, sizeof(tagErrMsg) - 1);
// 清理错误对象
g_clear_error(&error);
}
// 释放流资源
if (stream) g_clear_object(&stream);
// 返回错误码
return nErrCode;
}
代码执行流程总结
初始化与参数检查:
验证相机连接有效性
获取并设置图像位深度
获取图像尺寸参数
相机配置:
选择数据流通道
设置为单帧采集模式
图像采集准备:
创建数据流对象
分配数据缓冲区
初始化性能监控
图像采集:
启动采集
从缓冲区获取图像数据
保存图像数据
停止采集
资源清理与错误处理:
释放缓冲区和流资源
检查并处理错误
返回操作结果
关于ShowGigeImage();(显示图像)
void CSUCCES1Dlg::ShowGigeImage()
{
CDC* pDC = GetDC();
HBITMAP hBitmap = GetBitmap(pDC);
if (!hBitmap)
{
hBitmap = (HBITMAP)LoadImage(NULL, _T(“res/demo.bmp”), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
if (!hBitmap) hBitmap = (HBITMAP)LoadImage(NULL, _T(“demo.bmp”), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
}
if (hBitmap) ShowImage(hBitmap);
if (hBitmap) DeleteObject(hBitmap);
}
HBITMAP CSUCCES1Dlg::GetBitmap(CDC* pDC)
{
// 检查输入参数有效性
if (!pDC) return NULL;
// 准备位图信息结构,失败则返回NULL
if (!MakeBitMapInfo()) return NULL;
HBITMAP hBitmap = NULL;
// 从相机对象获取原始图像数据指针
LPBYTE lpData = m_curGige->GetMatrix();
// 获取图像宽度和高度
int nWidth = m_curGige->GetBmpWidth();
int nHeight = m_curGige->GetBmpHeight();
// 计算按4字节对齐后的行宽度(Windows位图要求每行字节数必须是4的倍数)
int nSaveWidth = 4 * ((nWidth + 3) / 4);
// 如果原始宽度已经是4的倍数,直接创建位图
if (nSaveWidth == nWidth)
{
hBitmap = ::CreateDIBitmap(pDC->GetSafeHdc(),
(BITMAPINFOHEADER*)m_pBitInfo, CBM_INIT, lpData, m_pBitInfo, DIB_RGB_COLORS);
}
else
{
// 否则需要创建临时缓冲区进行行对齐处理
LPBYTE memData = new BYTE[nSaveWidth * nHeight];
memset(memData, 0, nSaveWidth * nHeight);
LPBYTE pSrc = lpData; // 源数据指针
LPBYTE pp = memData; // 目标数据指针
// 逐行复制数据,并进行必要的填充
for (int i = 0; i < nHeight; i++)
{
memcpy(pp, pSrc, nWidth); // 复制有效数据
pp += nSaveWidth; // 目标指针移动到下一行
pSrc += nWidth; // 源指针移动到下一行
}
// 使用对齐后的数据创建位图
hBitmap = ::CreateDIBitmap(pDC->GetSafeHdc(),
(BITMAPINFOHEADER*)m_pBitInfo, CBM_INIT, memData, m_pBitInfo, DIB_RGB_COLORS);
// 释放临时缓冲区
delete[] memData; memData = NULL;
}
return hBitmap;
}
void CSUCCES1Dlg::ShowNetStatus()
{
// 检查相机对象是否有效
if (m_curGige)
{
// 从相机对象获取各项状态参数
int useTick = m_curGige->GetUseTick(); // 获取图像处理耗时(毫秒)
double speed = m_curGige->GetNetSpeed(); // 获取网络传输速度(Mbps)
double frames = m_curGige->GetNetFrameRate(); // 获取帧率(帧/秒)
int width = m_curGige->GetBmpWidth(); // 获取图像宽度(像素)
int height = m_curGige->GetBmpHeight(); // 获取图像高度(像素)
CString pip = GetFromUTF8(m_curGige->GetIP()); // 获取相机IP地址并转换为UTF-8编码
CString strTemp = _T("");
// 格式化状态信息字符串
strTemp.Format(_T("remote:%s recv rate=%6.2fframe/s speed=%9.2fmbps image[ %d * %d ] use:%dms"),
pip.GetBuffer(), frames, speed, width, height, useTick);
// 将格式化后的字符串显示在ID为IDC_STREAM_DEMO的控件上
SetDlgItemText(IDC_STREAM_DEMO, strTemp);
}
}
关于视频流
void CSUCCES1Dlg::OnBnClickedBtnVideo()
{
// 初始化错误码为成功状态
COMMON_ERR nErrCode = COMMON_OK;
// 获取按钮当前显示的文本
CString strTemp = _T("");
GetDlgItemText(IDC_BTN_VIDEO, strTemp);
// 根据按钮文本判断当前应该执行的操作
if (strTemp.CompareNoCase(_T("video")) == 0)
// 如果按钮文本是"video",则启动视频流
nErrCode = __StartVideo();
else
// 否则停止视频流
nErrCode = __StopVideo();
// 更新界面控件状态
SetDlgItemState();
}
和拍照差不多
COMMON_ERR CSUCCES1Dlg::__StartVideo()
{
// 初始化错误码为成功状态
COMMON_ERR nErrCode = COMMON_OK;
// 定义错误消息缓冲区并初始化为0
tagErrMsg szMsg; memset(szMsg, 0, sizeof(tagErrMsg));
// 如果相机对象存在但无效,则尝试打开相机
if (m_curGige && m_curGige->Invalidate()) m_curGige->Open();
// 检查相机是否有效,无效则设置错误码
if (!m_curGige || m_curGige->Invalidate())
nErrCode = ERR_CAMERA_INVALID;
// 如果前面的操作成功,则打开视频流
if (COMMON_SUCCEEDED(nErrCode))
{
nErrCode = m_curGige->OpenStream(szMsg);
}
// 显示错误消息(如果有错误发生)
__ShowMessage(nErrCode, szMsg);
return nErrCode;
}
COMMON_ERR CGige::OpenStream(char* szMsg/*= NULL*/)
{
// 检查相机状态,如果无效则尝试打开
if (Invalidate()) Open();
if (Invalidate()) return ERR_CAMERA_INVALID;
GError* error = NULL;
ArvCamera* camera = m_pGige;
COMMON_ERR nErrCode = COMMON_OK;
// 配置相机流通道和采集模式
arv_camera_gv_select_stream_channel(camera, 0, NULL);
arv_camera_set_acquisition_mode(camera, ARV_ACQUISITION_MODE_CONTINUOUS, NULL);
// 创建数据流对象并设置回调函数
HeTrace("arv_camera_create_stream");
m_stream = arv_camera_create_stream(camera, stream_callback, this, &error);
// 配置数据流缓冲区
if (!error && ARV_IS_STREAM(m_stream))
{
// 清除可能存在的旧错误
if (error) g_error_free(error); error = NULL;
// 获取图像数据有效载荷大小
size_t payload = arv_camera_get_payload(camera, &error);
// 创建并推送10个缓冲区到数据流
if (!error && payload > 0)
{
for (int i = 0; i < 10; i++)
arv_stream_push_buffer(m_stream, arv_buffer_new(payload, NULL));
}
// 初始化速率和速度测量
InitRateSpeed();
HeTrace("arv_camera_start_acquisition");
// 设置采集标志并启动连续采集
m_bKill = false;
if (!error) arv_camera_start_acquisition(camera, &error);
}
// 错误处理
if (error)
{
nErrCode = error->code;
if (szMsg) memcpy(szMsg, error->message, sizeof(tagErrMsg) - 1);
g_clear_error(&error);
// 释放资源
g_clear_object(&m_stream);
g_object_unref(&m_stream);
m_stream = NULL;
HeTrace("arv_camera_create_stream_error");
}
else if(ARV_IS_STREAM(m_stream))
{
HeTrace("arv_camera_start_acquisition_ok");
}
return nErrCode;
}


















暂无评论内容