这里写自定义目录标题
- QT+opencv调用海康工业相机
- 开发环境
- 引用海康开发文件
- 直接上代码
QT+opencv调用海康工业相机
最近在使用Opencv调用海康工业相机的程序,从网上查了好多资料,也走了不少弯路,在这里分享下,希望大家少走弯路!
开发环境
QT5.14.2 +MSVC2017 64bit + opencv4.5
引用海康开发文件
这里就不多少了 网上有好多,可以参考 记得工程文件添加引用路径
opencv
```cpp
INCLUDEPATH += D:/Environment/opencv/build/include\
D:/Environment/opencv/build/include/opencv2
LIBS += D:/Environment/opencv/build/x64/vc15/lib/opencv_world451d.lib
海康
INCLUDEPATH += $$PWD/includes
LIBS += $$PWD/libs/MvCameraControl.lib\
直接上代码
界面
头文件
#include <QMainWindow>
#include <MvCameraControl.h>
#include <opencv2/opencv.hpp>
#include <QTimer>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
public://公共函数
void EnumDevice();//设备枚举
void ConnectDevice();//连接设备
void SetTriggerMode();//设置触发模式
void GrabImage();//开始取流
//RGB转BGR
int RGB2BGR( unsigned char* pRgbData, unsigned int nWidth, unsigned int nHeight );
//图片格式转Mat类型并返回Mat
cv::Mat Convert2Mat(MV_FRAME_OUT_INFO_EX* pstImageInfo, unsigned char * pData);
private slots://按键槽函数
void on_pushButton_seachDevice_clicked();
void on_pushButton_grabImage_clicked();
void on_pushButton_stopGrab_clicked();
private slots:// 自定义槽函数
void GetImage();//获取图像
private://全局对象
MV_CC_DEVICE_INFO_LIST stDeviceList;//实例化设备列表
int nRet;//定义返回接收值
void* handle;//实例化设备句柄
unsigned char * pData;//图像信息
unsigned int g_nPayloadSize;//图像尺寸
mat_to_img MatToImage;//Mat转Image
QTimer * timer;//创建定时器
MV_FRAME_OUT_INFO_EX stImageInfo;
private:
Ui::MainWindow *ui;
};
CPP文件
#include "Mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QMessageBox>
#include <Windows.h>
#ifdef WIN32
#pragma execution_character_set("utf-8")//解决QT VC中文乱码
#endif
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
/*初始化对象↓*/
nRet = MV_OK;
handle = NULL;
g_nPayloadSize = 0;
stImageInfo = {0};
/*↑初始化对象*/
}
MainWindow::~MainWindow()
{
timer->stop();
delete ui;
delete timer;
}
void MainWindow::EnumDevice()//枚举设备
{
memset(&stDeviceList,0,sizeof(MV_CC_DEVICE_INFO_LIST));//开辟空间
nRet = MV_CC_EnumDevices(MV_GIGE_DEVICE,&stDeviceList);//枚举设备并返回信息进行判断
if(nRet != MV_OK)
{
QString text = QString("枚举设备失败!nRet [0x%1]").arg(nRet);
QMessageBox::warning(this,"警告",text);
return;
}
if(stDeviceList.nDeviceNum > 0)
{
for (unsigned int i = 0;i < stDeviceList.nDeviceNum;i++)
{
MV_CC_DEVICE_INFO* pDeviceInfo = stDeviceList.pDeviceInfo[i];
if(pDeviceInfo == NULL)
{
continue;
}
wchar_t* pUserName = NULL;
if(pDeviceInfo->nTLayerType == MV_GIGE_DEVICE)
{
int nIp1 = ((stDeviceList.pDeviceInfo[i]->SpecialInfo.stGigEInfo.nCurrentIp & 0xff000000) >> 24);
int nIp2 = ((stDeviceList.pDeviceInfo[i]->SpecialInfo.stGigEInfo.nCurrentIp & 0x00ff0000) >> 16);
int nIp3 = ((stDeviceList.pDeviceInfo[i]->SpecialInfo.stGigEInfo.nCurrentIp & 0x0000ff00) >> 8);
int nIp4 = (stDeviceList.pDeviceInfo[i]->SpecialInfo.stGigEInfo.nCurrentIp & 0x000000ff);
if(std::strcmp("",(LPCSTR)(pDeviceInfo->SpecialInfo.stGigEInfo.chUserDefinedName)) != 0)
{
DWORD dwLenUserName = MultiByteToWideChar(CP_ACP,0,(LPCSTR)(pDeviceInfo->SpecialInfo.stGigEInfo.chUserDefinedName),-1,NULL,0);
pUserName = new wchar_t[dwLenUserName];
MultiByteToWideChar(CP_ACP,0,(LPCSTR)(pDeviceInfo->SpecialInfo.stGigEInfo.chUserDefinedName),-1,pUserName,dwLenUserName);
}
else
{
DWORD dwLenUserName = MultiByteToWideChar(CP_ACP,0,(LPCSTR)(pDeviceInfo->SpecialInfo.stGigEInfo.chUserDefinedName),-1,NULL,0);
pUserName = new wchar_t[dwLenUserName];
MultiByteToWideChar(CP_ACP,0,(LPCSTR)(pDeviceInfo->SpecialInfo.stGigEInfo.chUserDefinedName),-1,pUserName,dwLenUserName);
}
QString text = QString("[%1]Gige:%2(%3.%4.%5.%6)").arg(i).arg(pUserName).arg(nIp1).arg(nIp2).arg(nIp3).arg(nIp4);
ui->comboBox_DeviceList->addItem(text);
}
else
{
QMessageBox::warning(this,"警告","未知设备");
QString text = QString("未知设备[%1]").arg(i);
ui->comboBox_DeviceList->addItem(text);
}
if(pUserName)
{
delete [] pUserName;
pUserName = NULL;
}
}
}
if(stDeviceList.nDeviceNum == 0)
{
QMessageBox::warning(this,"警告","未发现设备");
return;
}
}
void MainWindow::ConnectDevice()//连接设备并打开
{
//创建设备句柄
unsigned int nIndex = ui->comboBox_DeviceList->currentIndex();
nRet = MV_CC_CreateHandle(&handle,stDeviceList.pDeviceInfo[nIndex]);
if(nRet != MV_OK)
{
QString text = QString("创建设备失败!nRet [%1]").arg(nRet);
QMessageBox::warning(this,"警告",text);
return;
}
//打开设备
nRet = MV_CC_OpenDevice(handle);
if(nRet != MV_OK)
{
QString text = QString("打开设备失败!nRet [%1]").arg(nRet);
QMessageBox::warning(this,"警告",text);
return;
}
// 检测网络最近封装尺寸(仅支持 GigE camera)
if (stDeviceList.pDeviceInfo[nIndex]->nTLayerType == MV_GIGE_DEVICE)
{
int nPacketSize = MV_CC_GetOptimalPacketSize(handle);
if (nPacketSize > 0)
{
nRet = MV_CC_SetIntValue(handle,"GevSCPSPacketSize",nPacketSize);
if(nRet != MV_OK)
{
QString text = QString("设置封装尺寸失败!nRet [%1]").arg(nRet);
QMessageBox::warning(this,"警告",text);
}
}
else
{
QString text = QString("获取封装尺寸失败!nRet [%1]").arg(nPacketSize);
QMessageBox::warning(this,"警告",text);
}
}
}
void MainWindow::SetTriggerMode()//设置触发模式
{
nRet = MV_CC_SetEnumValue(handle, "TriggerMode", 0);
if (MV_OK != nRet)
{
printf("Set Trigger Mode fail! nRet [0x%x]\n", nRet);
QString text = QString("设置触发模式失败!nRet [%1]").arg(nRet);
QMessageBox::warning(this,"警告",text);
return;
}
}
void MainWindow::GrabImage()//开始取流
{
//获取playload尺寸
MVCC_INTVALUE stParam;
memset(&stParam, 0, sizeof(MVCC_INTVALUE));
nRet = MV_CC_GetIntValue(handle, "PayloadSize", &stParam);
if (MV_OK != nRet)
{
QString text = QString("获取playlord失败!nRet [%1]").arg(nRet);
QMessageBox::warning(this,"警告",text);
return;
}
g_nPayloadSize = stParam.nCurValue;
//开始取流
nRet = MV_CC_StartGrabbing(handle);
if(nRet != MV_OK)
{
printf("Start Grabbing fail! nRet [0x%x]\n", nRet);
// QString text = QString("取流失败!nRet [0x%1]").arg(nRet);
// QMessageBox::warning(this,"警告",text);
return;
}
// MV_FRAME_OUT_INFO_EX stImageInfo = {0};
memset(&stImageInfo,0,sizeof (MV_FRAME_OUT_INFO_EX));
pData = (unsigned char*)malloc(sizeof (unsigned char)* (g_nPayloadSize));
if (pData == NULL)
{
QMessageBox::warning(this,"警告","分配内容失败!");
return;
}
// 获取一张图片get one frame from camera with timeout=1000ms
nRet = MV_CC_GetOneFrameTimeout(handle, pData, g_nPayloadSize, &stImageInfo, 1000);
if (nRet == MV_OK)
{
printf("Get One Frame: Width[%d], Height[%d], nFrameNum[%d]\n",
stImageInfo.nWidth, stImageInfo.nHeight, stImageInfo.nFrameNum);
}
else
{
QString text = QString("无图像数据!nRet [%1]").arg(nRet);
QMessageBox::warning(this,"警告",text);
free(pData);
pData = NULL;
return;
}
}
int MainWindow::RGB2BGR(unsigned char *pRgbData, unsigned int nWidth, unsigned int nHeight)//RGB转BGR
{
if ( NULL == pRgbData )
{
return MV_E_PARAMETER;
}
for (unsigned int j = 0; j < nHeight; j++)
{
for (unsigned int i = 0; i < nWidth; i++)
{
unsigned char red = pRgbData[j * (nWidth * 3) + i * 3];
pRgbData[j * (nWidth * 3) + i * 3] = pRgbData[j * (nWidth * 3) + i * 3 + 2];
pRgbData[j * (nWidth * 3) + i * 3 + 2] = red;
}
}
return MV_OK;
}
cv::Mat MainWindow::Convert2Mat(MV_FRAME_OUT_INFO_EX *pstImageInfo, unsigned char *pData)//转Mat格式
{
cv::Mat srcImage;
if ( pstImageInfo->enPixelType == PixelType_Gvsp_Mono8 )
{
srcImage = cv::Mat(pstImageInfo->nHeight, pstImageInfo->nWidth, CV_8UC1, pData);
return srcImage;
}
else if ( pstImageInfo->enPixelType == PixelType_Gvsp_RGB8_Packed )
{
RGB2BGR(pData, pstImageInfo->nWidth, pstImageInfo->nHeight);
srcImage = cv::Mat(pstImageInfo->nHeight, pstImageInfo->nWidth, CV_8UC3, pData);
return srcImage;
}
else
{
QMessageBox::warning(this,"警告","不支持此类型转换");
return srcImage;
}
if ( NULL == srcImage.data )
{
QMessageBox::warning(this,"警告","转换图像为空");
return srcImage;
}
}
void MainWindow::on_pushButton_seachDevice_clicked()//按下查询设备按钮
{
EnumDevice();//调用枚举设备函数
}
void MainWindow::on_pushButton_grabImage_clicked()//按下采样按钮
{
ConnectDevice();
SetTriggerMode();
GrabImage();
//GetImage();
timer = new QTimer;
timer->start(300);
connect(timer,&QTimer::timeout,this,&MainWindow::GetImage);//通过定时器循环调用显示图像
}
void MainWindow::GetImage()//采集一张图片
{
nRet = MV_CC_GetOneFrameTimeout(handle, pData, g_nPayloadSize, &stImageInfo, 1000);
if (nRet == MV_OK)
{
cv::Mat dstImga;
dstImga = Convert2Mat(&stImageInfo, pData);
//cv::imshow("image",dstImga);
cv::cvtColor(dstImga,dstImga,cv::COLOR_BGR2RGB);
QImage Qtemp = QImage((const unsigned char*)(dstImga.data), dstImga.cols, dstImga.rows, dstImga.step, QImage::Format_RGB888);
ui->label_show->setScaledContents(true);
ui->label_show->setPixmap(QPixmap::fromImage(Qtemp));
}
else
{
QString text = QString("无图像数据!nRet [%1]").arg(nRet);
QMessageBox::warning(this,"警告",text);
free(pData);
pData = NULL;
return;
}
}
void MainWindow::on_pushButton_stopGrab_clicked()//按下停止采集按钮
{
timer->stop();
// 关闭取流
nRet = MV_CC_StopGrabbing(handle);
if (MV_OK != nRet)
{
printf("Stop Grabbing fail! nRet [0x%x]\n", nRet);
return;
}
//关闭设备
nRet = MV_CC_CloseDevice(handle);
if (MV_OK != nRet)
{
printf("ClosDevice fail! nRet [0x%x]\n", nRet);
return;
}
// Destroy handle
nRet = MV_CC_DestroyHandle(handle);
if (MV_OK != nRet)
{
printf("Destroy Handle fail! nRet [0x%x]\n", nRet);
return;
}
}
就到这里,本人也是小白,刚接触编程没多久,班门弄斧大神轻喷!