前言:
近期企业需要用大恒相机的sdk开发项目,我采用VS2017+QT5.10.1+MSVC。
一、环境配置
VS2017和qt的安装不多介绍,主要介绍大恒sdk的配置。
1.https://www.daheng-image.com/list-58-1.html 官网下载大恒相机的SDK包,选择自己对应的相机
2.解压到自己的文件夹
文件目录如下:
3.c++文件的配置主要有头文件、库文件。
头文件在项目中的配置:
右击项目-属性-VC++目录-包含目录
路径为刚才解压的文件夹下路径
库目录路径:
右击项目-属性-VC++目录-库目录
路径为解压文件下路径
附加库依赖
右击项目-属性-链接器-输入
注意事项:有第三方库,将dll文件加入项目文件下即可。这样库文件配置完成开始编写代码部分。我用了opencv。
二、图像采集
1.打开设备
注意事项,必须先进行设备初始化 IGXFactory::GetInstance().Init();
//打开设备
void DH_MER::Open_Device()
{
try
{
do
{
//初始化
IGXFactory::GetInstance().Init();
//枚举设备
gxdeviceinfo_vector vectorDeviceInfo;
IGXFactory::GetInstance().UpdateDeviceList(1000, vectorDeviceInfo);
if (0 == vectorDeviceInfo.size())
{
cout << "无可用设备!" << endl;
break;
}
cout << vectorDeviceInfo.size() << endl;
//打开第一台设备以及设备下面第一个流
ObjDevicePtr = IGXFactory::GetInstance().OpenDeviceBySN(
vectorDeviceInfo[0].GetSN(),
GX_ACCESS_EXCLUSIVE);
ObjStreamPtr = ObjDevicePtr->OpenStream(0);
提高网络相机的采集性能,设置方法参考以下代码(目前只有千兆网系列相机支持设置最优包长)
//GX_DEVICE_CLASS_LIST objDeviceClass =ObjDevicePtr->GetDeviceInfo().GetDeviceClass();
//if (GX_DEVICE_CLASS_GEV == objDeviceClass)
//{
// //判断设备是否支持流通道数据包功能
// if (true == ObjFeatureControlPtr->IsImplemented("GevSCPSPacketSize"))
// {
// //获取当前网络环境的最优包长值
// int nPacketSize = ObjStreamPtr->GetOptimalPacketSize();
// //将最优包长值设置为当前设备的流通道包长值
// ObjFeatureControlPtr->GetIntFeature("GevSCPSPacketSize")->SetValue(nPacketSize);
// }
//}
//注册设备掉线事件【目前只有千兆网系列相机支持此事件通知】
pDeviceOfflineEventHandler = new CSampleDeviceOfflineEventHandler();
hDeviceOffline = ObjDevicePtr->RegisterDeviceOfflineCallback(pDeviceOfflineEventHandler, NULL);
//获取远端设备属性控制器
ObjFeatureControlPtr = ObjDevicePtr->GetRemoteFeatureControl();
#ifdef _DEBUG
//设置心跳超时时间 5min
ObjFeatureControlPtr->GetIntFeature("GevHeartbeatTimeout")->SetValue(5000);
#endif
txt_factoryName = ObjFeatureControlPtr->GetStringFeature("DeviceVendorName")->GetValue();
txt_basicMode = ObjFeatureControlPtr->GetStringFeature("DeviceModelName")->GetValue();
cout << "成功打开第一个设备" << endl;
} while (0);
}
catch (CGalaxyException& e)
{
cout << "错误码: " << e.GetErrorCode() << endl;
cout << "错误描述信息: " << e.what() << endl;
}
catch (std::exception& e)
{
cout << "错误描述信息: " << e.what() << endl;
}
}
2.采集图像
//采集图像
void DH_MER::Pick_Picture()
{
//注册回调采集
pCaptureEventHandler = new CSampleCaptureEventHandler();
ObjStreamPtr->RegisterCaptureCallback(pCaptureEventHandler, this);
//发送开采命令
ObjStreamPtr->StartGrab();
ObjFeatureControlPtr->GetCommandFeature("AcquisitionStart")->Execute();
}
3.停止采集
//停止采集
void DH_MER::Stop_Picking()
{
//发送停采命令
ObjFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute();
ObjStreamPtr->StopGrab();
}
4.采集图像事件处理
这里才是对采集的图像进行处理的地方
void CSampleCaptureEventHandler::DoOnImageCaptured(CImageDataPointer& objImageDataPointer, void* pUserParam)
{
DH_MER* camUiPtr = (DH_MER*)pUserParam;
cout << "收到一帧图像!" << endl;
//cout << "ImageInfo: " << objImageDataPointer->GetPayloadSize() << endl;
camUiPtr->txt_width = QString::number(objImageDataPointer->GetWidth());
camUiPtr->txt_height = QString::number(objImageDataPointer->GetHeight());
camUiPtr->captureImgMat.create(objImageDataPointer->GetHeight(), objImageDataPointer->GetWidth(), CV_8UC3);
void* pRGB24Buffer = NULL;
//假设原始数据是BayerRG8图像
pRGB24Buffer = objImageDataPointer->ConvertToRGB24(GX_BIT_0_7, GX_RAW2RGB_NEIGHBOUR, true);
memcpy(camUiPtr->captureImgMat.data, pRGB24Buffer, (objImageDataPointer->GetHeight()) * (objImageDataPointer->GetWidth()) * 3);
//flip(img, img, 0);
cout << "帧数:" << objImageDataPointer->GetFrameID() << endl;
}
5.相机线程调用实时采集
void WorkThread::run()
{
unsigned char ret;
if (1 == ThreadId)
{
cancl->Open_Device();//打开设备
cancl->Pick_Picture();//开始采集
//if (CAM_RETURNVAL_NO_DEVICES == ret)//未找到摄像头设备
//{
// return;
//}
}
while (1)
{
if (workcount)//关闭线程
{
cancl->Close_Device();
workcount = false;
break;
}
readFarme();
QThread::usleep(33);
}
}
6.相机采集的图像进行算法处理
因算法不便公开,只写图片传出部分。
只需要用lable展示QPixmap即可ui->label_9->setPixmap(fitpixmap);
//获取的到mat数据转换为image(mat为CV_8UC1)
QImage image(cancl->captureImgMat.cols, cancl->captureImgMat.rows, QImage::Format_Indexed8);
image.setColorCount(256);
for (int i = 0; i < 256; i++)
{
image.setColor(i, qRgb(i, i, i));
}
uchar *pSrc = cancl->captureImgMat.data;
for (int row = 0; row < cancl->captureImgMat.rows; row++)
{
uchar *pDest = image.scanLine(row);
memcpy(pDest, pSrc, cancl->captureImgMat.cols);
pSrc += cancl->captureImgMat.step;
}
//获取摄像图像
QPixmap pixmap = QPixmap::fromImage(image);
emit UpdateImage(pixmap);//触发信号更新UI
三、相机类代码
可以根据需求添加设备组和当前设备对象进行处理
CameraClass.h
#pragma once
#include <opencv2/opencv.hpp>
#include"GalaxyIncludes.h"
#include<QObject>
using namespace cv;
using namespace std;
class CameraClass :public QObject
{
Q_OBJECT
public:
CameraClass();
~CameraClass();
//声明事件回调对象指针
IDeviceOfflineEventHandler* pDeviceOfflineEventHandler = NULL;//掉线事件回调对象
GX_DEVICE_OFFLINE_CALLBACK_HANDLE hDeviceOffline = NULL;//注册设备掉线
IFeatureEventHandler* pFeatureEventHandler = NULL;//<远端设备事件回调对象
ICaptureEventHandler* pCaptureEventHandler = NULL;//<采集回调对象
CGXDevicePointer ObjDevicePtr;//设备指针
CGXStreamPointer ObjStreamPtr;//流指针
CGXFeatureControlPointer ObjFeatureControlPtr;//(远端)设备属性控制器指针
Mat captureImgMat;//相机拍摄的图片
QString choose_triggerMode;//选择触发模式
QString txt_triggerSource;//触发源
int txt_exposeTime;//曝光时间
double txt_gain;//增益
QString txt_width;//图像宽
QString txt_height;//图像高
QString txt_factoryName;//厂商
QString txt_basicMode;
public:
void Open_Device();//open the device
void Close_Device();//close the device
void Pick_Picture();//start picking the picture
void Stop_Picking();//stop picking the picture
};
class CSampleCaptureEventHandler : public ICaptureEventHandler
{
public:
void DoOnImageCaptured(CImageDataPointer& objImageDataPointer, void* pUserParam);
};
//用户继承掉线事件处理类
class CSampleDeviceOfflineEventHandler : public IDeviceOfflineEventHandler
{
public:
void DoOnDeviceOfflineEvent(void* pUserParam)
{
cout << "收到设备掉线事件!" << endl;
}
};
CameraClass.cpp
#include "CameraClass.h"
CameraClass::CameraClass()
{
}
CameraClass::~CameraClass()
{
}
//打开设备
void CameraClass::Open_Device()
{
try
{
do
{
//初始化
IGXFactory::GetInstance().Init();
//枚举设备
gxdeviceinfo_vector vectorDeviceInfo;
IGXFactory::GetInstance().UpdateDeviceList(1000, vectorDeviceInfo);
if (0 == vectorDeviceInfo.size())
{
cout << "无可用设备!" << endl;
break;
}
cout << vectorDeviceInfo.size() << endl;
//打开第一台设备以及设备下面第一个流
ObjDevicePtr = IGXFactory::GetInstance().OpenDeviceBySN(
vectorDeviceInfo[0].GetSN(),
GX_ACCESS_EXCLUSIVE);
ObjStreamPtr = ObjDevicePtr->OpenStream(0);
提高网络相机的采集性能,设置方法参考以下代码(目前只有千兆网系列相机支持设置最优包长)
//GX_DEVICE_CLASS_LIST objDeviceClass =ObjDevicePtr->GetDeviceInfo().GetDeviceClass();
//if (GX_DEVICE_CLASS_GEV == objDeviceClass)
//{
// //判断设备是否支持流通道数据包功能
// if (true == ObjFeatureControlPtr->IsImplemented("GevSCPSPacketSize"))
// {
// //获取当前网络环境的最优包长值
// int nPacketSize = ObjStreamPtr->GetOptimalPacketSize();
// //将最优包长值设置为当前设备的流通道包长值
// ObjFeatureControlPtr->GetIntFeature("GevSCPSPacketSize")->SetValue(nPacketSize);
// }
//}
//注册设备掉线事件【目前只有千兆网系列相机支持此事件通知】
pDeviceOfflineEventHandler = new CSampleDeviceOfflineEventHandler();
hDeviceOffline = ObjDevicePtr->RegisterDeviceOfflineCallback(pDeviceOfflineEventHandler, NULL);
//获取远端设备属性控制器
ObjFeatureControlPtr = ObjDevicePtr->GetRemoteFeatureControl();
#ifdef _DEBUG
//设置心跳超时时间 5min
ObjFeatureControlPtr->GetIntFeature("GevHeartbeatTimeout")->SetValue(5000);
#endif
txt_factoryName = ObjFeatureControlPtr->GetStringFeature("DeviceVendorName")->GetValue();
txt_basicMode = ObjFeatureControlPtr->GetStringFeature("DeviceModelName")->GetValue();
cout << "成功打开第一个设备" << endl;
} while (0);
}
catch (CGalaxyException& e)
{
cout << "错误码: " << e.GetErrorCode() << endl;
cout << "错误描述信息: " << e.what() << endl;
}
catch (std::exception& e)
{
cout << "错误描述信息: " << e.what() << endl;
}
}
//关闭设备
void CameraClass::Close_Device()
{
try
{
Stop_Picking();
//注销采集回调
ObjStreamPtr->UnregisterCaptureCallback();
注销远端设备事件
//ObjFeatureControlPtr->UnregisterFeatureCallback(hFeatureEvent);
//注销设备掉线事件
ObjDevicePtr->UnregisterDeviceOfflineCallback(hDeviceOffline);
//释放资源
ObjStreamPtr->Close();
ObjDevicePtr->Close();
//反初始化库
IGXFactory::GetInstance().Uninit();
//销毁事件回调指针
if (NULL != pCaptureEventHandler)
{
delete pCaptureEventHandler;
pCaptureEventHandler = NULL;
}
if (NULL != pDeviceOfflineEventHandler)
{
delete pDeviceOfflineEventHandler;
pDeviceOfflineEventHandler = NULL;
}
if (NULL != pFeatureEventHandler)
{
delete pFeatureEventHandler;
pFeatureEventHandler = NULL;
}
cout << "关闭设备" << endl;
}
catch (const std::exception&)
{
}
}
//采集图像
void CameraClass::Pick_Picture()
{
//注册回调采集
pCaptureEventHandler = new CSampleCaptureEventHandler();
ObjStreamPtr->RegisterCaptureCallback(pCaptureEventHandler, this);
//发送开采命令
ObjStreamPtr->StartGrab();
ObjFeatureControlPtr->GetCommandFeature("AcquisitionStart")->Execute();
}
//停止采集
void CameraClass::Stop_Picking()
{
//发送停采命令
ObjFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute();
ObjStreamPtr->StopGrab();
}
void CSampleCaptureEventHandler::DoOnImageCaptured(CImageDataPointer& objImageDataPointer, void* pUserParam)
{
CameraClass* camUiPtr = (CameraClass*)pUserParam;
cout << "收到一帧图像!" << endl;
//cout << "ImageInfo: " << objImageDataPointer->GetPayloadSize() << endl;
camUiPtr->txt_width = QString::number(objImageDataPointer->GetWidth());
camUiPtr->txt_height = QString::number(objImageDataPointer->GetHeight());
camUiPtr->captureImgMat.create(objImageDataPointer->GetHeight(), objImageDataPointer->GetWidth(), CV_8UC3);
void* pRGB24Buffer = NULL;
//假设原始数据是BayerRG8图像
pRGB24Buffer = objImageDataPointer->ConvertToRGB24(GX_BIT_0_7, GX_RAW2RGB_NEIGHBOUR, true);
memcpy(camUiPtr->captureImgMat.data, pRGB24Buffer, (objImageDataPointer->GetHeight()) * (objImageDataPointer->GetWidth()) * 3);
//flip(img, img, 0);
cout << "帧数:" << objImageDataPointer->GetFrameID() << endl;
}
四、效果展示
实际效果不错,可以看文档更改相机设置。
喜欢点个关注吧