目录
1.新建工程
2.文件及属性配置
2.1文件拷贝
2.2VS项目属性配置
2.2.1包含目录和库目录添加
2.2.2附加依赖项添加
3.添加基于官方mfc代码改写的CGXBitmap类
3.1添加CGXBitmap类
3.2编写CGXBitmap.h和.cpp文件
4.编写Qt .h和 .cpp文件
5.运行效果
6.下载链接
7.双相机代码移植Qt版
1.新建工程
该项目是通过阅读大恒官方C++项目的代码进行移植的一个Qt简单demo,废话不多说直接上步骤。



至此一个Qt项目创建完毕。
2.文件及属性配置
因为需要使用大恒官方的API,那么就需要使用官方提供的库文件和头文件。可以通过该步骤添加到项目中。(方法不唯一,这里为了移植到其他电脑才这样做的)
2.1文件拷贝



2.2VS项目属性配置
2.2.1包含目录和库目录添加


2.2.2附加依赖项添加



至此整个项目的属性配置和文件就配置完成了。
3.添加基于官方mfc代码改写的CGXBitmap类
CGXBitmap类是我基于大恒官方提供的C++代码中mfc版CGXBitmap类改写的。具体功能有:显示图像、保存图像等功能。具体步骤如下:
3.1添加CGXBitmap类




3.2编写CGXBitmap.h和.cpp文件
在添加的CGXBitmap.h 填写如下内容
// /*CGXBitmap.h*/ / #pragma once #include <QWidget> #include "ui_CGXBitmap.h" #include <QLabel> #include <iostream> #include <GalaxyIncludes.h> using namespace std; #pragma execution_character_set("utf-8") class CGXBitmap : public QWidget { Q_OBJECT public: CGXBitmap(QWidget *parent = Q_NULLPTR); ~CGXBitmap(); private: Ui::CGXBitmap ui; bool m_bIsColor; //是否支持彩色相机 int64_t m_nImageHeight; //原始图像高 int64_t m_nImageWidth; //原始图像宽 BITMAPINFO *m_pBmpInfo; //BITMAPINFO 结构指针,显示图像时使用 char m_chBmpBuf[2048]; //BIMTAPINFO 存储缓冲区,m_pBmpInfo即指向此缓冲区 uchar *m_pImageBuffer; //保存翻转后的图像用于显示 private: CGXBitmap& operator=(const CGXBitmap&); CGXBitmap(const CGXBitmap&); public: QLabel *m_pLabel; QImage *m_pImage; //显示图像 void Show(CImageDataPointer& objCImageDataPointer); //图像处理后并显示图像 void ShowImageProcess(CImageProcessConfigPointer& objCfg, CImageDataPointer& objCImageDataPointer); //存储Bmp图像 void SaveBmp(CImageDataPointer& objCImageDataPointer, const std::string& strFilePath); //存储Raw图像 void SaveRaw(CImageDataPointer& objCImageDataPointer, const std::string& strFilePath); //通过GX_PIXEL_FORMAT_ENTRY获取最优Bit位 GX_VALID_BIT_LIST GetBestValudBit(GX_PIXEL_FORMAT_ENTRY emPixelFormatEntry); LPCWSTR stringToLPCWSTR(std::string orig); void addDevicePtr(CGXDevicePointer& objCGXDevicePointer); private: //判断PixelFormat是否为8位 bool __IsPixelFormat8(GX_PIXEL_FORMAT_ENTRY emPixelFormatEntry); //为彩色相机图像显示准备资源 void __ColorPrepareForShowImg(); //为黑白相机图像显示准备资源 void __MonoPrepareForShowImg(); //判断是否兼容 bool __IsCompatible(BITMAPINFO *pBmpInfo, uint64_t nWidth, uint64_t nHeight); //更新Bitmap的信息 void __UpdateBitmap(CImageDataPointer& objCImageDataPointer); //将m_pBufferRGB中图像显示到界面 void __DrawImg(uchar* pBuffer); //计算宽度所占的字节数 int64_t __GetStride(int64_t nWidth, bool bIsColor); //是否支持彩色 void __IsSupportColor(CGXDevicePointer& objCGXDevicePointer, bool &bIsColorFilter); };
讯享网
在添加的CGXBitmap.cpp填写如下内容:
讯享网#include "CGXBitmap.h" //--------------------------------------------------------------------------------- / \brief 构造函数 \param objCGXDevicePointer 图像设备指针 \param parent 窗体指针 \return 无 */ //---------------------------------------------------------------------------------- CGXBitmap::CGXBitmap(QWidget *parent) : QWidget(parent) , m_bIsColor(false) , m_nImageHeight(0) , m_nImageWidth(0) , m_pImage(NULL) , m_pBmpInfo(NULL) , m_pImageBuffer(NULL) { ui.setupUi(this); //初始化绘图框 m_pLabel = new QLabel(this); m_pLabel->move(0, 0); m_pLabel->resize(751, 551); } void CGXBitmap::addDevicePtr(CGXDevicePointer& objCGXDevicePointer) { if (objCGXDevicePointer.IsNull()) { throw std::runtime_error("Argument is error"); } memset(m_chBmpBuf, 0, sizeof(m_chBmpBuf)); gxstring strValue = ""; //获得图像宽度、高度等 m_nImageWidth = (int64_t)objCGXDevicePointer->GetRemoteFeatureControl()->GetIntFeature("Width")->GetValue(); m_nImageHeight = (int64_t)objCGXDevicePointer->GetRemoteFeatureControl()->GetIntFeature("Height")->GetValue(); //获取是否为彩色相机 __IsSupportColor(objCGXDevicePointer, m_bIsColor); if (m_bIsColor) { __ColorPrepareForShowImg(); } else { __MonoPrepareForShowImg(); } } //--------------------------------------------------------------------------------- / \brief 析构函数 \return 无 */ //---------------------------------------------------------------------------------- CGXBitmap::~CGXBitmap() { } //---------------------------------------------------------------------------------- / \brief 判断PixelFormat是否为8位 \param emPixelFormatEntry 图像数据格式 \return true为8为数据,false为非8位数据 */ //---------------------------------------------------------------------------------- bool CGXBitmap::__IsPixelFormat8(GX_PIXEL_FORMAT_ENTRY emPixelFormatEntry) { bool bIsPixelFormat8 = false; const unsigned PIXEL_FORMATE_BIT = 0x00FF0000; ///<用于与当前的数据格式进行与运算得到当前的数据位数 unsigned uiPixelFormatEntry = (unsigned)emPixelFormatEntry; if ((uiPixelFormatEntry & PIXEL_FORMATE_BIT) == GX_PIXEL_8BIT) { bIsPixelFormat8 = true; } return bIsPixelFormat8; } //---------------------------------------------------------------------------------- / \brief 通过GX_PIXEL_FORMAT_ENTRY获取最优Bit位 \param emPixelFormatEntry 图像数据格式 \return 最优Bit位 */ //---------------------------------------------------------------------------------- GX_VALID_BIT_LIST CGXBitmap::GetBestValudBit(GX_PIXEL_FORMAT_ENTRY emPixelFormatEntry) { GX_VALID_BIT_LIST emValidBits = GX_BIT_0_7; switch (emPixelFormatEntry) { case GX_PIXEL_FORMAT_MONO8: case GX_PIXEL_FORMAT_BAYER_GR8: case GX_PIXEL_FORMAT_BAYER_RG8: case GX_PIXEL_FORMAT_BAYER_GB8: case GX_PIXEL_FORMAT_BAYER_BG8: { emValidBits = GX_BIT_0_7; break; } case GX_PIXEL_FORMAT_MONO10: case GX_PIXEL_FORMAT_BAYER_GR10: case GX_PIXEL_FORMAT_BAYER_RG10: case GX_PIXEL_FORMAT_BAYER_GB10: case GX_PIXEL_FORMAT_BAYER_BG10: { emValidBits = GX_BIT_2_9; break; } case GX_PIXEL_FORMAT_MONO12: case GX_PIXEL_FORMAT_BAYER_GR12: case GX_PIXEL_FORMAT_BAYER_RG12: case GX_PIXEL_FORMAT_BAYER_GB12: case GX_PIXEL_FORMAT_BAYER_BG12: { emValidBits = GX_BIT_4_11; break; } case GX_PIXEL_FORMAT_MONO14: { //暂时没有这样的数据格式待升级 break; } case GX_PIXEL_FORMAT_MONO16: case GX_PIXEL_FORMAT_BAYER_GR16: case GX_PIXEL_FORMAT_BAYER_RG16: case GX_PIXEL_FORMAT_BAYER_GB16: case GX_PIXEL_FORMAT_BAYER_BG16: { //暂时没有这样的数据格式待升级 break; } default: break; } return emValidBits; } //--------------------------------------------------------------------------------- / \brief 为彩色相机图像显示准备资源 \return 无 */ //---------------------------------------------------------------------------------- void CGXBitmap::__ColorPrepareForShowImg() { //-------------------------------------------------------------------- //---------------------------初始化bitmap头--------------------------- m_pBmpInfo = (BITMAPINFO *)m_chBmpBuf; m_pBmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); m_pBmpInfo->bmiHeader.biWidth = (LONG)m_nImageWidth; m_pBmpInfo->bmiHeader.biHeight = (LONG)m_nImageHeight; m_pBmpInfo->bmiHeader.biPlanes = 1; m_pBmpInfo->bmiHeader.biBitCount = 24; m_pBmpInfo->bmiHeader.biCompression = BI_RGB; m_pBmpInfo->bmiHeader.biSizeImage = 0; m_pBmpInfo->bmiHeader.biXPelsPerMeter = 0; m_pBmpInfo->bmiHeader.biYPelsPerMeter = 0; m_pBmpInfo->bmiHeader.biClrUsed = 0; m_pBmpInfo->bmiHeader.biClrImportant = 0; } //--------------------------------------------------------------------------------- / \brief 为黑白相机图像显示准备资源 \return 无 */ //---------------------------------------------------------------------------------- void CGXBitmap::__MonoPrepareForShowImg() { //--------------------------------------------------------------------- //----------------------初始化bitmap头--------------------------------- m_pBmpInfo = (BITMAPINFO *)m_chBmpBuf; m_pBmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); m_pBmpInfo->bmiHeader.biWidth = (LONG)m_nImageWidth; m_pBmpInfo->bmiHeader.biHeight = (LONG)m_nImageHeight; m_pBmpInfo->bmiHeader.biPlanes = 1; m_pBmpInfo->bmiHeader.biBitCount = 8; // 黑白图像为8 m_pBmpInfo->bmiHeader.biCompression = BI_RGB; m_pBmpInfo->bmiHeader.biSizeImage = 0; m_pBmpInfo->bmiHeader.biXPelsPerMeter = 0; m_pBmpInfo->bmiHeader.biYPelsPerMeter = 0; m_pBmpInfo->bmiHeader.biClrUsed = 0; m_pBmpInfo->bmiHeader.biClrImportant = 0; // 黑白图像需要初始化调色板 for (int i = 0; i < 256; i++) { m_pBmpInfo->bmiColors[i].rgbBlue = i; m_pBmpInfo->bmiColors[i].rgbGreen = i; m_pBmpInfo->bmiColors[i].rgbRed = i; m_pBmpInfo->bmiColors[i].rgbReserved = 0; } //为经过翻转后的图像数据分配空间 if (m_pImageBuffer != NULL) { delete m_pImageBuffer; m_pImageBuffer = NULL; } m_pImageBuffer = new BYTE[(size_t)(m_nImageWidth * m_nImageHeight)]; if (m_pImageBuffer == NULL) { throw std::runtime_error("Fail to allocate memory"); } } //---------------------------------------------------------------------------------- / \brief 判断是否兼容 \param pBmpInfo BITMAPINFO指针 \param nWidth 图像宽 \param nHeight 图像高 \return true为一样,false不一样 */ //---------------------------------------------------------------------------------- bool CGXBitmap::__IsCompatible(BITMAPINFO *pBmpInfo, uint64_t nWidth, uint64_t nHeight) { if (pBmpInfo == NULL || pBmpInfo->bmiHeader.biHeight != nHeight || pBmpInfo->bmiHeader.biWidth != nWidth ) { return false; } return true; } //---------------------------------------------------------------------------------- / \brief 检查图像是否改变并更新Buffer并为图像显示准备资源 \param objCImageDataPointer 图像数据对象 \return 无 */ //---------------------------------------------------------------------------------- void CGXBitmap::__UpdateBitmap(CImageDataPointer& objCImageDataPointer) { if (!__IsCompatible(m_pBmpInfo, objCImageDataPointer->GetWidth(), objCImageDataPointer->GetHeight())) { m_nImageWidth = objCImageDataPointer->GetWidth(); m_nImageHeight = objCImageDataPointer->GetHeight(); if (m_bIsColor) { __ColorPrepareForShowImg(); } else { __MonoPrepareForShowImg(); } } } //--------------------------------------------------------------------------------- / \brief 将m_pBufferRGB中图像显示到界面 \param pBuffer 图像数据Buffer指针 \return 无 */ //---------------------------------------------------------------------------------- void CGXBitmap::__DrawImg(uchar* pBuffer) { if (m_pImage != NULL) { delete m_pImage; m_pImage = NULL; } //数据转换 m_pImage = new QImage(pBuffer, m_nImageWidth, m_nImageHeight, QImage::Format_Indexed8); // 不失真缩放 m_pImage->scaled(m_nImageWidth, m_nImageHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation); m_pLabel->setScaledContents(true); m_pLabel->setPixmap(QPixmap::fromImage(*m_pImage)); } //---------------------------------------------------------------------------------- / \brief 计算宽度所占的字节数 \param nWidth 图像宽度 \param bIsColor 是否是彩色相机 \return 图像一行所占的字节数 */ //---------------------------------------------------------------------------------- int64_t CGXBitmap::__GetStride(int64_t nWidth, bool bIsColor) { return bIsColor ? nWidth * 3 : nWidth; } //---------------------------------------------------------------------------------- / \brief 用于显示图像 \param objCImageDataPointer 图像数据对象 \return 无 */ //---------------------------------------------------------------------------------- void CGXBitmap::Show(CImageDataPointer& objCImageDataPointer) { GX_VALID_BIT_LIST emValidBits = GX_BIT_0_7; uchar* pBuffer = NULL; if (objCImageDataPointer.IsNull()) { throw std::runtime_error("NULL pointer dereferenced"); } //检查图像是否改变并更新Buffer __UpdateBitmap(objCImageDataPointer); emValidBits = GetBestValudBit(objCImageDataPointer->GetPixelFormat()); if (m_bIsColor) { pBuffer = (uchar*)objCImageDataPointer->ConvertToRGB24(emValidBits, GX_RAW2RGB_NEIGHBOUR, true); __DrawImg(pBuffer); } else { if (__IsPixelFormat8(objCImageDataPointer->GetPixelFormat())) { pBuffer = (uchar*)objCImageDataPointer->GetBuffer(); } else { pBuffer = (uchar*)objCImageDataPointer->ConvertToRaw8(emValidBits); } __DrawImg(pBuffer); } } //---------------------------------------------------------------------------------- / \brief 用于图像处理后并显示图像 \param objCfg 图像处理调节参数对象 \param objCImageDataPointer 图像数据对象 \return 无 */ //---------------------------------------------------------------------------------- void CGXBitmap::ShowImageProcess(CImageProcessConfigPointer& objCfg, CImageDataPointer& objCImageDataPointer) { if ((objCfg.IsNull()) || (objCImageDataPointer.IsNull())) { throw std::runtime_error("NULL pointer dereferenced"); } //检查图像是否改变并更新Buffer __UpdateBitmap(objCImageDataPointer); BYTE* pBuffer = (BYTE*)objCImageDataPointer->ImageProcess(objCfg); if (m_bIsColor) { __DrawImg(pBuffer); } else { // 黑白相机需要翻转数据后显示 for (int i = 0; i < m_nImageHeight; i++) { memcpy(m_pImageBuffer + i * m_nImageWidth, pBuffer + (m_nImageHeight - i - 1) * m_nImageWidth, (size_t)m_nImageWidth); } __DrawImg(m_pImageBuffer); } } //---------------------------------------------------------------------------------- / \brief 存储Bmp图像 \param objCImageDataPointer 图像数据对象 \param strFilePath 显示图像文件名 \return 无 */ //---------------------------------------------------------------------------------- void CGXBitmap::SaveBmp(CImageDataPointer& objCImageDataPointer, const std::string& strFilePath) { GX_VALID_BIT_LIST emValidBits = GX_BIT_0_7; uchar* pBuffer = NULL; if ((objCImageDataPointer.IsNull()) || (strFilePath == "")) { throw std::runtime_error("Argument is error"); } //检查图像是否改变并更新Buffer __UpdateBitmap(objCImageDataPointer); emValidBits = GetBestValudBit(objCImageDataPointer->GetPixelFormat()); if (m_bIsColor) { pBuffer = (uchar*)objCImageDataPointer->ConvertToRGB24(emValidBits, GX_RAW2RGB_NEIGHBOUR, true); } else { if (__IsPixelFormat8(objCImageDataPointer->GetPixelFormat())) { pBuffer = (uchar*)objCImageDataPointer->GetBuffer(); } else { pBuffer = (uchar*)objCImageDataPointer->ConvertToRaw8(emValidBits); } // 黑白相机需要翻转数据后显示 for (int i = 0; i < m_nImageHeight; i++) { memcpy(m_pImageBuffer + i * m_nImageWidth, pBuffer + (m_nImageHeight - i - 1) * m_nImageWidth, (size_t)m_nImageWidth); } pBuffer = m_pImageBuffer; } DWORD dwImageSize = (DWORD)(__GetStride(m_nImageWidth, m_bIsColor) * m_nImageHeight); BITMAPFILEHEADER stBfh = { 0 }; DWORD dwBytesRead = 0; stBfh.bfType = (WORD)'M' << 8 | 'B'; //定义文件类型 stBfh.bfOffBits = m_bIsColor ? sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) : sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (256 * 4); //定义文件头大小true为彩色,false为黑白 stBfh.bfSize = stBfh.bfOffBits + dwImageSize; //文件大小 DWORD dwBitmapInfoHeader = m_bIsColor ? sizeof(BITMAPINFOHEADER) : sizeof(BITMAPINFOHEADER) + (256 * 4); //定义BitmapInfoHeader大小true为彩色,false为黑白 //创建文件 HANDLE hFile = ::CreateFile(stringToLPCWSTR(strFilePath), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { throw std::runtime_error("Handle is invalid"); } ::WriteFile(hFile, &stBfh, sizeof(BITMAPFILEHEADER), &dwBytesRead, NULL); ::WriteFile(hFile, m_pBmpInfo, dwBitmapInfoHeader, &dwBytesRead, NULL); //黑白和彩色自适应 ::WriteFile(hFile, pBuffer, dwImageSize, &dwBytesRead, NULL); CloseHandle(hFile); } //---------------------------------------------------------------------------------- / \brief 存储Raw图像 \param objCImageDataPointer 图像数据对象 \param strFilePath 显示图像文件名 \return 无 */ //---------------------------------------------------------------------------------- void CGXBitmap::SaveRaw(CImageDataPointer& objCImageDataPointer, const std::string& strFilePath) { if ((objCImageDataPointer.IsNull()) || (strFilePath == "")) { throw std::runtime_error("Argument is error"); } //检查图像是否改变并更新Buffer __UpdateBitmap(objCImageDataPointer); DWORD dwImageSize = (DWORD)objCImageDataPointer->GetPayloadSize(); // 写入文件的长度 DWORD dwBytesRead = 0; // 文件读取的长度 BYTE* pbuffer = (BYTE*)objCImageDataPointer->GetBuffer(); if (!m_bIsColor) { // 黑白相机需要翻转数据后显示 for (int i = 0; i < m_nImageHeight; i++) { memcpy(m_pImageBuffer + i * m_nImageWidth, pbuffer + (m_nImageHeight - i - 1) * m_nImageWidth, (size_t)m_nImageWidth); } pbuffer = m_pImageBuffer; } // 创建文件 HANDLE hFile = ::CreateFile(stringToLPCWSTR(strFilePath), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) // 创建失败则返回 { throw std::runtime_error("Handle is invalid"); } else // 保存Raw图像 { ::WriteFile(hFile, pbuffer, dwImageSize, &dwBytesRead, NULL); CloseHandle(hFile); } } //---------------------------------------------------------------------------------- / \brief 是否支持彩色 \param objCGXDevicePointer [in] 设备句柄 \param bIsColorFilter [out] 是否支持彩色 \return */ //---------------------------------------------------------------------------------- void CGXBitmap::__IsSupportColor(CGXDevicePointer& objCGXDevicePointer, bool &bIsColorFilter) { GX_STATUS emStatus = GX_STATUS_SUCCESS; bool bIsImplemented = false; bool bIsMono = false; gxstring strPixelFormat = ""; strPixelFormat = objCGXDevicePointer->GetRemoteFeatureControl()->GetEnumFeature("PixelFormat")->GetValue(); strPixelFormat.substr(0, 4); if (0 == memcmp(strPixelFormat.c_str(), "Mono", 4)) { bIsMono = true; } else { bIsMono = false; } bIsImplemented = objCGXDevicePointer->GetRemoteFeatureControl()->IsImplemented("PixelColorFilter"); // 若当前为非黑白且支持PixelColorFilter则为彩色 if ((!bIsMono) && (bIsImplemented)) { bIsColorFilter = true; } else { bIsColorFilter = false; } } LPCWSTR CGXBitmap::stringToLPCWSTR(std::string orig) { size_t origsize = orig.length() + 1; const size_t newsize = 100; size_t convertedChars = 0; wchar_t* wcstring = (wchar_t*)malloc(sizeof(wchar_t) * (orig.length() - 1)); mbstowcs_s(&convertedChars, wcstring, origsize, orig.c_str(), _TRUNCATE); return wcstring; }
CGXBitmap.ui不做修改
4.编写Qt .h和 .cpp文件
接下来编写最后的核心文件,具体文件以自己命名为主。

编写daheng_SingleCam_for_qt.h(我的界面是用代码生成的,没有使用拖曳的方式生成,目的是为了提供更好的代码观感)
#pragma once #include <QtWidgets/QMainWindow> #include "ui_daheng_SingleCam_for_qt.h" #include <GalaxyIncludes.h> #include <iostream> #include "CGXBitmap.h" #include <QPushButton> #include <QLabel> #include <QCloseEvent> using namespace std; #pragma execution_character_set("utf-8") class daheng_SingleCam_for_qt : public QMainWindow { Q_OBJECT //用户继承采集事件处理类 class CSampleCaptureEventHandler : public ICaptureEventHandler { public: //--------------------------------------------------------------------------------- / \brief 采集回调函数 \param objImageDataPointer 图像处理参数 \param pFrame 用户参数 \return 无 */ //---------------------------------------------------------------------------------- void DoOnImageCaptured(CImageDataPointer&objImageDataPointer, void* pUserParam) { try { daheng_SingleCam_for_qt* pSingleCamDlg = (daheng_SingleCam_for_qt*)pUserParam; //显示图像 pSingleCamDlg->m_pBitmap->Show(objImageDataPointer); //判断是否需要保存图像 //if (pSingleCamDlg->m_pBitmap->m_bSaveImage == true) //{ // pSingleCamDlg->m_pBitmap->SavePicture(objImageDataPointer); // pSingleCamDlg->m_pBitmap->m_bSaveImage = false; //} } catch (CGalaxyException) { } catch (std::exception) { } } }; public: daheng_SingleCam_for_qt(QWidget *parent = Q_NULLPTR); CGXBitmap *m_pBitmap; //图像操作类 private: Ui::daheng_SingleCam_for_qtClass ui; //Qt控件 QPushButton *m_pBtnOpenDevice; //打开设备按钮 QPushButton *m_pBtnCloseDevice; //关闭设备按钮 QPushButton *m_pBtnStartSnap; //开始采集按钮 QPushButton *m_pBtnStopSnap; //停止采集按钮 QLabel *m_pLabel; //状态栏显示文字 //用于界面更新的标识 bool m_bIsOpen; //打开设备标识 bool m_bIsSnap; //采集图像标识 //大恒相机API CGXFeatureControlPointer *m_pFeatureEventHandler; //远端设备事件回调对象 CSampleCaptureEventHandler *m_pCaptureEventHandler; //采集回调对象 CGXDevicePointer m_ObjDevicePtr; //设备句柄 CGXStreamPointer m_ObjStreamPtr; //设备流 CGXFeatureControlPointer m_ObjFeatureControlPtr; //属性控制器 CGXFeatureControlPointer m_ObjStreamFeatureControlPtr; //流层控制器 //槽函数 void on_Btn_OpenDevice_clicked(); void on_Btn_CloseDevice_clicked(); void on_Btn_StartSnap_clicked(); void on_Btn_StopSnap_clicked(); //关闭窗口事件重写 void closeEvent(QCloseEvent *event); //更新界面 void UpdateUI(); };
daheng_SingleCam_for_qt.cpp
讯享网#include "daheng_SingleCam_for_qt.h" daheng_SingleCam_for_qt::daheng_SingleCam_for_qt(QWidget *parent) : QMainWindow(parent) , m_bIsOpen(false) , m_bIsSnap(false) { ui.setupUi(this); //控件初始化 m_pBtnOpenDevice = new QPushButton(this); m_pBtnOpenDevice->setText("打开设备"); m_pBtnOpenDevice->move(0, 0); m_pBtnCloseDevice = new QPushButton(this); m_pBtnCloseDevice->setText("关闭设备"); m_pBtnCloseDevice->move(0, 50); m_pBtnStartSnap = new QPushButton(this); m_pBtnStartSnap->setText("开始采集"); m_pBtnStartSnap->move(0, 100); m_pBtnStopSnap = new QPushButton(this); m_pBtnStopSnap->setText("停止采集"); m_pBtnStopSnap->move(0, 150); m_pBitmap = new CGXBitmap(this); m_pBitmap->move(100, 0); m_pBitmap->resize(800, 607); m_pLabel = new QLabel(this); m_pLabel->setText("欢迎使用大恒相机[for Qt]"); statusBar()->addWidget(m_pLabel);//将label控件添加到状态栏 //连接信号和槽函数 connect(m_pBtnOpenDevice, &QPushButton::clicked, this, &daheng_SingleCam_for_qt::on_Btn_OpenDevice_clicked); connect(m_pBtnCloseDevice, &QPushButton::clicked, this, &daheng_SingleCam_for_qt::on_Btn_CloseDevice_clicked); connect(m_pBtnStartSnap, &QPushButton::clicked, this, &daheng_SingleCam_for_qt::on_Btn_StartSnap_clicked); connect(m_pBtnStopSnap, &QPushButton::clicked, this, &daheng_SingleCam_for_qt::on_Btn_StopSnap_clicked); //大恒API库调用 try { //初始化设备 IGXFactory::GetInstance().Init(); m_pCaptureEventHandler = new CSampleCaptureEventHandler(); //更新界面 UpdateUI(); } catch (CGalaxyException& e) { if (m_pCaptureEventHandler != NULL) { delete m_pCaptureEventHandler; m_pCaptureEventHandler = NULL; } m_pLabel->setText(QString::fromStdString(e.what())); return; } catch (std::exception& e) { if (m_pCaptureEventHandler != NULL) { delete m_pCaptureEventHandler; m_pCaptureEventHandler = NULL; } m_pLabel->setText(QString::fromStdString(e.what())); return; } } //--------------------------------------------------------------------------------- / \brief 更新界面 \return 无 */ //---------------------------------------------------------------------------------- void daheng_SingleCam_for_qt::UpdateUI() { m_pBtnOpenDevice->setEnabled(!m_bIsOpen); m_pBtnCloseDevice->setEnabled(m_bIsOpen); m_pBtnStartSnap->setEnabled(m_bIsOpen && !m_bIsSnap); m_pBtnStopSnap->setEnabled(m_bIsOpen && m_bIsSnap); } void daheng_SingleCam_for_qt::on_Btn_OpenDevice_clicked() { bool bIsDeviceOpen = false; //设备是否打开标识 bool bIsStreamOpen = false; //设备流是否打开标识 try { //枚举设备 GxIAPICPP::gxdeviceinfo_vector vectorDeviceInfo; IGXFactory::GetInstance().UpdateDeviceList(1000, vectorDeviceInfo); if (vectorDeviceInfo.size() == 0) { m_bIsOpen = false; bIsDeviceOpen = false; m_pLabel->setText("无可用设备!"); return; } //打开第一个设备以及设备下面第一个流 m_ObjDevicePtr = IGXFactory::GetInstance().OpenDeviceBySN(vectorDeviceInfo[0].GetSN(), GX_ACCESS_EXCLUSIVE);//打开方式:独占 m_bIsOpen = true; bIsDeviceOpen = true; //获取远端设备属性控制器 m_ObjFeatureControlPtr = m_ObjDevicePtr->GetRemoteFeatureControl(); //为画图对象分配设备指针 m_pBitmap->addDevicePtr(m_ObjDevicePtr); //判断设备流是否大于零,如果大于零则打开流 int nStreamCount = m_ObjDevicePtr->GetStreamCount(); if (nStreamCount) { m_ObjStreamPtr = m_ObjDevicePtr->OpenStream(0); //获取流层属性控制器 m_ObjStreamFeatureControlPtr = m_ObjStreamPtr->GetFeatureControl(); bIsStreamOpen = true; } else { throw exception("未发现设备流!"); } //提高网络相机的采集性能,设置方法如下(目前只有千兆网系列相机支持设置最优包长) GX_DEVICE_CLASS_LIST ObjDeviceClass = m_ObjDevicePtr->GetDeviceInfo().GetDeviceClass(); if (ObjDeviceClass == GX_DEVICE_CLASS_GEV) { //判断设备是否支持流通道数据包功能 if (m_ObjStreamFeatureControlPtr->IsImplemented("GevSCPSPacketSize")) { //获取当前网络环境的最优包长值 int nPacketSize = m_ObjStreamPtr->GetOptimalPacketSize(); //将最优包长值设置为当前设备的流通道包长值 m_ObjFeatureControlPtr->GetIntFeature( "GevSCPSPacketSize")->SetValue(nPacketSize); } } //更新界面 UpdateUI(); m_pLabel->setText(QString("打开设备成功!")); } catch (CGalaxyException& e) { //判断设备流是否已打开 if (bIsStreamOpen) { m_ObjStreamPtr->Close(); } //判断设备是否已打开 if (bIsDeviceOpen) { m_ObjDevicePtr->Close(); } m_pLabel->setText(QString::fromStdString(e.what())); return; } catch (exception& e) { //判断设备流是否已打开 if (bIsStreamOpen) { m_ObjStreamPtr->Close(); } //判断设备是否已打开 if (bIsDeviceOpen) { m_ObjDevicePtr->Close(); } m_pLabel->setText(QString::fromStdString(e.what())); return; } } void daheng_SingleCam_for_qt::on_Btn_CloseDevice_clicked() { try { //判断是否已停止采集 if (m_bIsSnap) { //发送停采命令 m_ObjFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute(); //关闭流层采集 m_ObjStreamPtr->StopGrab(); //注销采集回调 m_ObjStreamPtr->UnregisterCaptureCallback(); } } catch (CGalaxyException) { //do noting } try { //关闭流对象 m_ObjStreamPtr->Close(); } catch (CGalaxyException) { //do noting } try { //关闭设备 m_ObjDevicePtr->Close(); m_pLabel->setText(QString("关闭设备成功!")); } catch (CGalaxyException) { //do noting } m_bIsOpen = false; m_bIsSnap = false; //更新界面 UpdateUI(); } void daheng_SingleCam_for_qt::on_Btn_StartSnap_clicked() { // TODO: Add your control notification handler code here try { try { //设置Buffer处理模式 m_ObjStreamFeatureControlPtr->GetEnumFeature("StreamBufferHandlingMode")->SetValue("OldestFirst"); } catch (...) { } //注册回调函数 m_ObjStreamPtr->RegisterCaptureCallback(m_pCaptureEventHandler, this); //开启流层通道 m_ObjStreamPtr->StartGrab(); //发送开采命令 m_ObjFeatureControlPtr->GetCommandFeature("AcquisitionStart")->Execute(); m_bIsSnap = true; //更新界面 UpdateUI(); m_pLabel->setText(QString("开始采集!")); } catch (CGalaxyException& e) { m_pLabel->setText(QString::fromStdString(e.what())); return; } catch (std::exception& e) { m_pLabel->setText(QString::fromStdString(e.what())); return; } } void daheng_SingleCam_for_qt::on_Btn_StopSnap_clicked() { // TODO: Add your control notification handler code here try { //发送停采命令 m_ObjFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute(); //关闭流层通道 m_ObjStreamPtr->StopGrab(); //注销采集回调 m_ObjStreamPtr->UnregisterCaptureCallback(); m_bIsSnap = false; //更新界面 UpdateUI(); m_pLabel->setText(QString("停止采集!")); } catch (CGalaxyException& e) { m_pLabel->setText(QString::fromStdString(e.what())); return; } catch (std::exception& e) { m_pLabel->setText(QString::fromStdString(e.what())); return; } } void daheng_SingleCam_for_qt::closeEvent(QCloseEvent *event) { try { //判断是否停止采集 if (m_bIsSnap) { //发送停采命令 m_ObjFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute(); //关闭流层通道 m_ObjStreamPtr->StopGrab(); //注销采集回调 m_ObjStreamPtr->UnregisterCaptureCallback(); m_bIsSnap = false; } } catch (CGalaxyException& e) { } catch (exception& e) { } try { //判断是否关闭设备 if (m_bIsOpen) { //关闭流对象 m_ObjStreamPtr->Close(); //关闭设备 m_ObjDevicePtr->Close(); m_bIsOpen = false; } } catch (CGalaxyException& e) { } catch (exception& e) { } try { //释放设备资源 IGXFactory::GetInstance().Uninit(); } catch (CGalaxyException& e) { } catch (exception& e) { } if (m_pCaptureEventHandler != NULL) { delete m_pCaptureEventHandler; m_pCaptureEventHandler = NULL; } event->accept(); }
5.运行效果

因为目前我只有一个黑白相机,没办法测试彩色相机是否可行。
6.下载链接
基于Qt大恒工业相机二次开发demo-C++-QT文档类资源-CSDN下载基于Qt大恒工业相机二次开发demo-C++,重写的CGXBitmap类,移植性强更多下载资源、学习资料请访问CSDN下载频道.
https://download.csdn.net/download/_/
7.双相机代码移植Qt版

可以实现两个相机的同步采集和图片保存,有兴趣的也可以下载查看使用,该项目需要自己重新配置属性。
大恒双相机C++QT工程文件建议使用Release调试-QT文档类资源-CSDN下载大恒双相机C++QT工程文件建议使用Release调试更多下载资源、学习资料请访问CSDN下载频道.
https://download.csdn.net/download/_/

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/13658.html