基于Qt大恒工业相机二次开发demo-C++
目录
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_OBJECTpublic: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; // 黑白图像为8m_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; //采集图像标识//大恒相机APICGXFeatureControlPointer *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 heretry{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 heretry{//发送停采命令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/qq_42816065/85043886
7.双相机代码移植Qt版
可以实现两个相机的同步采集和图片保存,有兴趣的也可以下载查看使用,该项目需要自己重新配置属性。
大恒双相机C++QT工程文件建议使用Release调试-QT文档类资源-CSDN下载大恒双相机C++QT工程文件建议使用Release调试更多下载资源、学习资料请访问CSDN下载频道.https://download.csdn.net/download/qq_42816065/85043927
基于Qt大恒工业相机二次开发demo-C++相关推荐
- 【Qt】基于Qt的CAN分析仪二次开发
CAN分析仪有上位机,能够满足我们大多数情况下的使用,但当我们想扩展CAN的使用,如对消息进行封装,实现特定的执行功能时,就需要根据库文件进行二次开发.下面是使用zlg进行二次开发的一次尝试. 请提前 ...
- NX/UG二次开发—QT—基于QT平台的UG二次开发
1.新建QT工程,选择C++库,工程名称qtugdemo: 2.添加对话框文件: 3.将UG入口函数考入到qtugdemo.cpp中,并添加如下代码: 4.修改*.pro文件,添加UG函数需要的lib ...
- 大恒工业相机C#语言winform平台开发例程
大恒工业相机winform快速开发 例程一.连续采集,返回bitmap格式图像 例程二.软触发采集,返回bitmap格式图像 例程三.硬触发采集,返回bitmap格式图像 例程四.作为TCP客户端接收 ...
- 大华摄像头二次开发-web端实现实时视频监控
最近客户提需要,需要在现有的系统中集成视频监控功能,摄像头是大华的.而大华又没有关于java的sdk,官网只能下载到c++的demo和dll文件.无奈只能自己在网上找了,最后找到了一些解决办法,把实现 ...
- Qt+大恒相机+OpenCV+MinGW界面开发
Qt+大恒相机+OpenCV+MinGW界面开发 遇到的坑有哪些? 大恒相机接口的问题(C与C++选谁,傻傻分不清) OpenCV版本与MinGW编译平台适应性问题(编译通过,但是一运行就异常退出) ...
- 基于QT的安卓手机蓝牙APP开发
摘要:前段时间用QT写了一个串口调试助手,感觉还可以.因为QT是跨平台的,同样一套代码可以在windows上面跑,也可以在linux上面跑,也可以在安卓手机上面跑.而且不需要修改任何东西,编译器会自动 ...
- Python基于周立功盒子的二次开发的封装和调用
Python基于周立功盒子的二次开发的封装和调用 一.介绍 前面我们介绍如何拿到官网给的例程并使用起来,但在使用的过程中,我们发现官网给的例子非常的冗长,可读性不好,于是我进行分解和封装,使得 ...
- 基于百度编辑器Ueditor的二次开发
基于百度编辑器Ueditor的二次开发 官网下载 基本配置 简化后端配置,不请求后端配置项 后端接口规范 修改图片上传 说明及修改 新增按钮及弹窗(自定义附件上传) 按钮文案修改 在业务开发的时候,曾 ...
- 基于屌丝青年网样式二次开发的WordPress主题:LIiu-One主题
源码下载:基于屌丝青年网样式二次开发的WordPress主题:LIiu-One主题-小程序文档类资源-CSDN下载 wordpress主题,基于屌丝青年网样式二次开发LIiu-One主题仿屌丝青年网模 ...
最新文章
- 创建本地数据库时发生错误及其解决方案
- R语言螺旋线型线性不可分数据xgboost分类:使用xgboost模型来解决螺旋数据的分类问题、可视化模型预测的结果、添加超平面区域渲染并与原始数据标签进行对比分析
- Linux海量数据高并发实时同步架构方案杂谈
- 科技创业公司的效率工具箱
- sublime 插件
- ITK:区域最大图像过滤器
- python卸载不了怎么办说目录有错_错误:无法在安装目录中创建或删除文件
- 【echart数组数据】echarts两条或两条以上x轴不同的线合并x轴 含有不连续数据
- 17款开源论坛系统/Forum Software(转载)
- android 4.4.2截屏方法,android4.4.2 使用 uiautoviewer 截屏报错
- 重物码垛搬运机器人_节卡机器人:5G下的智慧物流——柔性生产物流系统
- 一道六年级数学题,求阴影面积,那我只能用Python代码了
- python中函数startswith的用法_Python中用startswith()函数判断字符串开头的教程
- 【codevs1227】方格取数2,费用流
- 小Q系列故事——大笨钟
- 107 nginx rewrite规则和alias
- HAProxy从零开始到掌握
- php mysql update 不成功也不提示_php与MySQL(基本操作)
- 前端开发常用哪些工具软件?
- Web前端开发技术(第3版)储久良 实验12