GrabBag/SDK/Galaxy/test/GalaxyCamera.cpp
2025-12-10 00:01:32 +08:00

683 lines
19 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "GalaxyCamera.h"
#include <cstring>
#include <algorithm>
#ifdef _WIN32
#include <windows.h>
#endif
// 静态成员初始化
bool GalaxyCamera::s_sdkInitialized = false;
int GalaxyCamera::s_instanceCount = 0;
std::mutex GalaxyCamera::s_sdkMutex;
GalaxyCamera::GalaxyCamera()
: m_pCaptureEventHandler(nullptr)
, m_bIsOpen(false)
, m_bIsStreaming(false)
, m_bHasNewFrame(false) {
std::lock_guard<std::mutex> lock(s_sdkMutex);
s_instanceCount++;
}
GalaxyCamera::~GalaxyCamera() {
try {
StopStreaming();
Close();
}
catch (...) {
// 忽略清理异常
}
std::lock_guard<std::mutex> lock(s_sdkMutex);
s_instanceCount--;
// 注意不在析构函数中反初始化SDK
// SDK应该在程序退出时统一清理或者由最后一个实际使用的相机来清理
// 因为DetectAvailableBrands会频繁创建/销毁临时实例
}
// 检查大恒SDK DLL是否可用
static bool IsGalaxySDKAvailable() {
#ifdef _WIN32
// 尝试加载大恒SDK主DLL
// 使用 LOAD_LIBRARY_AS_DATAFILE 避免触发DLL的依赖加载
HMODULE hModule = LoadLibraryExA("GxIAPI.dll", nullptr, LOAD_LIBRARY_AS_DATAFILE);
if (hModule == nullptr) {
// DLL不在PATH中或不存在
return false;
}
FreeLibrary(hModule);
// 进一步检查尝试真正加载DLL会检查依赖
hModule = LoadLibraryA("GxIAPI.dll");
if (hModule == nullptr) {
// DLL存在但依赖项缺失如缺少MSVCP140D.dll
return false;
}
FreeLibrary(hModule);
return true;
#else
return true; // 非Windows平台假设可用
#endif
}
bool GalaxyCamera::Init(const std::string& sdkPath) {
(void)sdkPath;
std::lock_guard<std::mutex> lock(s_sdkMutex);
// 如果SDK已经初始化直接返回成功
if (s_sdkInitialized) {
return true;
}
// 首先检查SDK DLL是否可用
if (!IsGalaxySDKAvailable()) {
return false;
}
try {
// 尝试获取工厂实例并初始化
IGXFactory& factory = IGXFactory::GetInstance();
factory.Init();
s_sdkInitialized = true;
return true;
}
catch (CGalaxyException& e) {
(void)e;
s_sdkInitialized = false;
return false;
}
catch (std::exception& e) {
(void)e;
s_sdkInitialized = false;
return false;
}
catch (...) {
// 捕获所有其他异常
s_sdkInitialized = false;
return false;
}
}
std::vector<DeviceInfo> GalaxyCamera::Discover() {
std::vector<DeviceInfo> devices;
m_vectorDeviceInfo.clear();
if (!s_sdkInitialized) {
return devices;
}
try {
// 枚举设备超时1000ms
IGXFactory::GetInstance().UpdateDeviceList(1000, m_vectorDeviceInfo);
for (uint32_t i = 0; i < m_vectorDeviceInfo.size(); i++) {
DeviceInfo appDevInfo;
// 获取设备序列号作为ID
appDevInfo.id = m_vectorDeviceInfo[i].GetSN().c_str();
// 获取设备显示名称
appDevInfo.name = m_vectorDeviceInfo[i].GetDisplayName().c_str();
// 标记品牌
appDevInfo.brand = "Galaxy";
devices.push_back(appDevInfo);
}
}
catch (CGalaxyException& e) {
(void)e;
}
catch (std::exception& e) {
(void)e;
}
return devices;
}
bool GalaxyCamera::Open(const std::string& deviceID) {
if (m_bIsOpen) {
Close();
}
if (!s_sdkInitialized) {
return false;
}
bool bIsDeviceOpen = false;
bool bIsStreamOpen = false;
try {
// 通过序列号打开设备
m_objDevicePtr = IGXFactory::GetInstance().OpenDeviceBySN(
deviceID.c_str(), GX_ACCESS_EXCLUSIVE);
bIsDeviceOpen = true;
// 获取远程属性控制器
m_objFeatureControlPtr = m_objDevicePtr->GetRemoteFeatureControl();
// 设置采集模式为连续采集
m_objFeatureControlPtr->GetEnumFeature("AcquisitionMode")->SetValue("Continuous");
// 设置触发模式为关(软件触发时先关闭,后续按需开启)
m_objFeatureControlPtr->GetEnumFeature("TriggerMode")->SetValue("Off");
// 获取设备流个数
int nStreamCount = m_objDevicePtr->GetStreamCount();
if (nStreamCount > 0) {
m_objStreamPtr = m_objDevicePtr->OpenStream(0);
m_objStreamFeatureControlPtr = m_objStreamPtr->GetFeatureControl();
bIsStreamOpen = true;
}
else {
throw std::exception("未发现设备流!");
}
// 对于GigE相机设置最优包长
GX_DEVICE_CLASS_LIST objDeviceClass = m_objDevicePtr->GetDeviceInfo().GetDeviceClass();
if (GX_DEVICE_CLASS_GEV == objDeviceClass) {
if (m_objFeatureControlPtr->IsImplemented("GevSCPSPacketSize")) {
int nPacketSize = m_objStreamPtr->GetOptimalPacketSize();
m_objFeatureControlPtr->GetIntFeature("GevSCPSPacketSize")->SetValue(nPacketSize);
}
}
// 创建采集回调处理器
m_pCaptureEventHandler = new CaptureEventHandler(this);
m_bIsOpen = true;
return true;
}
catch (CGalaxyException& e) {
(void)e;
if (bIsStreamOpen && !m_objStreamPtr.IsNull()) {
m_objStreamPtr->Close();
}
if (bIsDeviceOpen && !m_objDevicePtr.IsNull()) {
m_objDevicePtr->Close();
}
m_bIsOpen = false;
return false;
}
catch (std::exception& e) {
(void)e;
if (bIsStreamOpen && !m_objStreamPtr.IsNull()) {
m_objStreamPtr->Close();
}
if (bIsDeviceOpen && !m_objDevicePtr.IsNull()) {
m_objDevicePtr->Close();
}
m_bIsOpen = false;
return false;
}
}
void GalaxyCamera::Close() {
if (!m_bIsOpen) {
return;
}
try {
// 停止采集
StopStreaming();
// 关闭流对象
if (!m_objStreamPtr.IsNull()) {
m_objStreamPtr->Close();
}
// 关闭设备
if (!m_objDevicePtr.IsNull()) {
m_objDevicePtr->Close();
}
}
catch (CGalaxyException&) {
// 忽略关闭异常
}
catch (std::exception&) {
// 忽略关闭异常
}
// 释放回调处理器
if (m_pCaptureEventHandler != nullptr) {
delete m_pCaptureEventHandler;
m_pCaptureEventHandler = nullptr;
}
m_bIsOpen = false;
}
bool GalaxyCamera::SetROI(int x, int y, int w, int h) {
if (!m_bIsOpen || m_objFeatureControlPtr.IsNull()) {
return false;
}
try {
// 获取最大宽高
int64_t widthMax = m_objFeatureControlPtr->GetIntFeature("WidthMax")->GetValue();
int64_t heightMax = m_objFeatureControlPtr->GetIntFeature("HeightMax")->GetValue();
// 基本验证
if (w <= 0 || h <= 0 || x < 0 || y < 0 ||
(x + w) > widthMax || (y + h) > heightMax) {
return false;
}
// 大恒相机ROI通常需要是4的倍数
w = (w / 4) * 4;
h = (h / 4) * 4;
x = (x / 4) * 4;
y = (y / 4) * 4;
if (w <= 0) w = 4;
if (h <= 0) h = 4;
// 设置ROI
m_objFeatureControlPtr->GetIntFeature("Width")->SetValue(w);
m_objFeatureControlPtr->GetIntFeature("Height")->SetValue(h);
m_objFeatureControlPtr->GetIntFeature("OffsetX")->SetValue(x);
m_objFeatureControlPtr->GetIntFeature("OffsetY")->SetValue(y);
return true;
}
catch (CGalaxyException& e) {
(void)e;
return false;
}
catch (std::exception& e) {
(void)e;
return false;
}
}
bool GalaxyCamera::StartStreaming(FrameCallback callback) {
if (!m_bIsOpen || m_bIsStreaming) {
return false;
}
try {
// 保存回调函数
m_frameCallback = callback;
// 设置Buffer处理模式
try {
m_objStreamFeatureControlPtr->GetEnumFeature("StreamBufferHandlingMode")->SetValue("OldestFirst");
}
catch (...) {
// 部分相机可能不支持此特性,忽略
}
// 注册采集回调
m_objStreamPtr->RegisterCaptureCallback(m_pCaptureEventHandler, this);
// 开启流层采集
m_objStreamPtr->StartGrab();
// 发送开采命令
m_objFeatureControlPtr->GetCommandFeature("AcquisitionStart")->Execute();
m_bIsStreaming = true;
return true;
}
catch (CGalaxyException& e) {
(void)e;
// 清理
try {
m_objStreamPtr->StopGrab();
m_objStreamPtr->UnregisterCaptureCallback();
}
catch (...) {}
m_bIsStreaming = false;
return false;
}
catch (std::exception& e) {
(void)e;
try {
m_objStreamPtr->StopGrab();
m_objStreamPtr->UnregisterCaptureCallback();
}
catch (...) {}
m_bIsStreaming = false;
return false;
}
}
void GalaxyCamera::StopStreaming() {
if (!m_bIsOpen || !m_bIsStreaming) {
return;
}
try {
// 发送停采命令
m_objFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute();
// 关闭流层采集
m_objStreamPtr->StopGrab();
// 注销回调函数
m_objStreamPtr->UnregisterCaptureCallback();
}
catch (CGalaxyException&) {
// 忽略异常
}
catch (std::exception&) {
// 忽略异常
}
m_bIsStreaming = false;
m_bHasNewFrame = false;
}
bool GalaxyCamera::IsStreaming() const {
return m_bIsStreaming;
}
bool GalaxyCamera::GrabCurrentFrame(ImageBuffer& out) {
if (!m_bIsStreaming) {
return false;
}
std::lock_guard<std::mutex> lock(m_frameMutex);
if (!m_latestFramePtr || m_latestFramePtr->data.empty()) {
return false;
}
// 复制最新帧数据
out = *m_latestFramePtr;
m_bHasNewFrame = false;
return true;
}
bool GalaxyCamera::Capture(ImageBuffer& out) {
if (!m_bIsOpen) {
return false;
}
// 如果正在流模式使用GrabCurrentFrame
if (m_bIsStreaming) {
return GrabCurrentFrame(out);
}
try {
// 单帧采集模式
// 开启流层采集
m_objStreamPtr->StartGrab();
// 发送开采命令
m_objFeatureControlPtr->GetCommandFeature("AcquisitionStart")->Execute();
// 获取一帧图像超时5000ms
CImageDataPointer objImageDataPointer = m_objStreamPtr->GetImage(5000);
if (objImageDataPointer.IsNull()) {
m_objFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute();
m_objStreamPtr->StopGrab();
return false;
}
// 检查图像状态
if (objImageDataPointer->GetStatus() != GX_FRAME_STATUS_SUCCESS) {
m_objFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute();
m_objStreamPtr->StopGrab();
return false;
}
// 转换图像数据
out.width = static_cast<int>(objImageDataPointer->GetWidth());
out.height = static_cast<int>(objImageDataPointer->GetHeight());
out.pixelFormat = convertPixelFormat(objImageDataPointer->GetPixelFormat());
// 计算数据大小
size_t dataSize = objImageDataPointer->GetPayloadSize();
out.data.resize(dataSize);
// 复制图像数据
void* pBuffer = objImageDataPointer->GetBuffer();
if (pBuffer) {
std::memcpy(out.data.data(), pBuffer, dataSize);
}
// 停止采集
m_objFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute();
m_objStreamPtr->StopGrab();
return true;
}
catch (CGalaxyException& e) {
(void)e;
try {
m_objFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute();
m_objStreamPtr->StopGrab();
}
catch (...) {}
return false;
}
catch (std::exception& e) {
(void)e;
try {
m_objFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute();
m_objStreamPtr->StopGrab();
}
catch (...) {}
return false;
}
}
bool GalaxyCamera::GetIntValue(const std::string& name, int& value) {
if (!m_bIsOpen || m_objFeatureControlPtr.IsNull()) {
return false;
}
try {
// 映射参数名称
std::string gxName = name;
if (name == "Width" || name == "Height" ||
name == "OffsetX" || name == "OffsetY") {
// 直接使用
}
value = static_cast<int>(m_objFeatureControlPtr->GetIntFeature(gxName.c_str())->GetValue());
return true;
}
catch (CGalaxyException&) {
return false;
}
catch (std::exception&) {
return false;
}
}
bool GalaxyCamera::SetIntValue(const std::string& name, int value) {
if (!m_bIsOpen || m_objFeatureControlPtr.IsNull()) {
return false;
}
try {
m_objFeatureControlPtr->GetIntFeature(name.c_str())->SetValue(value);
return true;
}
catch (CGalaxyException&) {
return false;
}
catch (std::exception&) {
return false;
}
}
bool GalaxyCamera::GetFloatValue(const std::string& name, float& value) {
if (!m_bIsOpen || m_objFeatureControlPtr.IsNull()) {
return false;
}
try {
// 映射参数名称到大恒SDK参数名
std::string gxName = name;
if (name == "ExposureTime") {
gxName = "ExposureTime";
}
else if (name == "Gain") {
gxName = "Gain";
}
value = static_cast<float>(m_objFeatureControlPtr->GetFloatFeature(gxName.c_str())->GetValue());
return true;
}
catch (CGalaxyException&) {
return false;
}
catch (std::exception&) {
return false;
}
}
bool GalaxyCamera::SetFloatValue(const std::string& name, float value) {
if (!m_bIsOpen || m_objFeatureControlPtr.IsNull()) {
return false;
}
try {
// 映射参数名称
std::string gxName = name;
if (name == "ExposureTime") {
gxName = "ExposureTime";
}
else if (name == "Gain") {
gxName = "Gain";
}
m_objFeatureControlPtr->GetFloatFeature(gxName.c_str())->SetValue(value);
return true;
}
catch (CGalaxyException&) {
return false;
}
catch (std::exception&) {
return false;
}
}
bool GalaxyCamera::IsConnected() {
return m_bIsOpen && !m_objDevicePtr.IsNull();
}
void GalaxyCamera::Cleanup() {
Close();
}
void GalaxyCamera::UninitSDK() {
std::lock_guard<std::mutex> lock(s_sdkMutex);
if (s_sdkInitialized) {
try {
IGXFactory::GetInstance().Uninit();
s_sdkInitialized = false;
}
catch (...) {
// 忽略清理异常
}
}
}
// 采集回调处理
void GalaxyCamera::CaptureEventHandler::DoOnImageCaptured(
CImageDataPointer& objImageDataPointer, void* pUserParam) {
try {
GalaxyCamera* pCamera = static_cast<GalaxyCamera*>(pUserParam);
if (pCamera) {
pCamera->processFrame(objImageDataPointer);
}
}
catch (CGalaxyException&) {
// 忽略异常
}
catch (std::exception&) {
// 忽略异常
}
}
void GalaxyCamera::processFrame(CImageDataPointer& objImageDataPointer) {
if (objImageDataPointer.IsNull()) {
return;
}
// 检查图像状态
if (objImageDataPointer->GetStatus() != GX_FRAME_STATUS_SUCCESS) {
return;
}
try {
// 创建新的图像缓冲区
auto newFrame = std::make_shared<ImageBuffer>();
newFrame->width = static_cast<int>(objImageDataPointer->GetWidth());
newFrame->height = static_cast<int>(objImageDataPointer->GetHeight());
newFrame->pixelFormat = convertPixelFormat(objImageDataPointer->GetPixelFormat());
// 获取图像数据大小
size_t dataSize = objImageDataPointer->GetPayloadSize();
newFrame->data.resize(dataSize);
// 复制图像数据
void* pBuffer = objImageDataPointer->GetBuffer();
if (pBuffer) {
std::memcpy(newFrame->data.data(), pBuffer, dataSize);
}
// 更新最新帧
{
std::lock_guard<std::mutex> lock(m_frameMutex);
m_latestFramePtr = newFrame;
m_bHasNewFrame = true;
}
// 调用用户回调
if (m_frameCallback) {
m_frameCallback(newFrame);
}
}
catch (std::exception&) {
// 忽略异常
}
}
PixelFormat GalaxyCamera::convertPixelFormat(GX_PIXEL_FORMAT_ENTRY gxFormat) {
switch (gxFormat) {
case GX_PIXEL_FORMAT_MONO8:
return PixelFormat::Mono8;
case GX_PIXEL_FORMAT_MONO10:
return PixelFormat::Mono10;
case GX_PIXEL_FORMAT_MONO12:
return PixelFormat::Mono12;
case GX_PIXEL_FORMAT_MONO16:
return PixelFormat::Mono16;
case GX_PIXEL_FORMAT_BAYER_RG8:
return PixelFormat::BayerRG8;
case GX_PIXEL_FORMAT_BAYER_GB8:
return PixelFormat::BayerGB8;
case GX_PIXEL_FORMAT_BAYER_GR8:
return PixelFormat::BayerGR8;
case GX_PIXEL_FORMAT_BAYER_BG8:
return PixelFormat::BayerBG8;
default:
// 对于未知格式默认返回Mono8
return PixelFormat::Mono8;
}
}