配置環境:
Qt5.12.5
OpenCV3.4.9
海康MVS3.1.0
開發工具:QT Creator-4.11.0
1、開發步驟:
1)創建QT項目,在pro文件中添加相機的引用文件
1.1)添加海康的庫:
將海康SDK庫MVS\Development\Includes和MVS\Development\Libraries\win64下復制到自己的工程目錄下
然后把庫添加到.pro文件中
點擊下一步之后就會在.pro文件中出現如下代碼
然后在這后面加上以下代碼,添加依賴項
1 INCLUDEPATH += $$PWD/includes/ 2 INCLUDEPATH += $$PWD/includes/GenICam/ 3 4 DEPENDPATH += $$PWD/includes/ 5 DEPENDPATH += $$PWD/includes/GenICam/
1.2)配置OpenCV
跟上面配置HKSDK步驟相同庫文件目錄為OpenCV的安裝目錄D:/OpenCV/opencv/build/x64/vc14/lib/opencv_world349d.lib
配置完成會在。pro文件中出現如下代碼
需要在后面添加如下代碼
1 INCLUDEPATH += D:\OpenCV\opencv\build\include \ 2 D:\OpenCV\opencv\build\include\opencv \ 3 D:\OpenCV\opencv\build\include\opencv2 4 DEPENDPATH += D:\OpenCV\opencv\build\include \ 5 D:\OpenCV\opencv\build\include\opencv \ 6 D:\OpenCV\opencv\build\include\opencv2
這樣海康SDK和OpenCV庫就配置完成了,可以在項目引入他們的頭文件了。
2、開發步驟:
新建一個類:mycanera.h和mycaner.cpp生成這兩個文件(ps:建文件時將camera打錯了,^_^)
mycanera.h文件參考一下代碼:
#ifndef MYCANERA_H #define MYCANERA_H #include "MvCameraControl.h" #pragma execution_character_set("utf-8") //設置當前文件為UTF-8編碼 #pragma warning( disable : 4819 ) //解決SDK中包含中文問題;忽略C4819錯誤 #include <stdio.h> #include <iostream> #include "opencv2/core/core.hpp" #include "opencv2/opencv.hpp" #include "opencv2/highgui/highgui.hpp" #include <string> #include <QDebug> using namespace std; using namespace cv; class MyCanera { public: MyCanera(); ~MyCanera(); //聲明相關變量及函數等 //枚舉相機設備列表 static int EnumDevices(MV_CC_DEVICE_INFO_LIST* pstDevList); // ch:連接相機 int connectCamera(string id); //設置相機觸發模式 int setTriggerMode(unsigned int TriggerModeNum); //開啟相機采集 int startCamera(); //發送軟觸發 int softTrigger(); //讀取buffer int ReadBuffer(Mat &image); //設置心跳時間 int setHeartBeatTime(unsigned int time); //設置曝光時間 int setExposureTime(float ExposureTimeNum);
//關閉相機 int closeCamera();
private: void* m_hDevHandle; public: unsigned char* m_pBufForSaveImage; // 用於保存圖像的緩存 unsigned int m_nBufSizeForSaveImage; unsigned char* m_pBufForDriver; // 用於從驅動獲取圖像的緩存 unsigned int m_nBufSizeForDriver; MV_CC_DEVICE_INFO_LIST m_stDevList; // ch:設備信息列表結構體變量,用來存儲設備列表 MV_CC_DEVICE_INFO *m_Device = NULL; //設備對象 }; #endif // MYCANERA_H
mycanera.cpp文件參考一下代碼:
#include "mycanera.h" #include <QDebug> MyCanera::MyCanera() { m_hDevHandle = NULL; } MyCanera::~MyCanera() { if (m_hDevHandle) { MV_CC_DestroyHandle(m_hDevHandle); m_hDevHandle = NULL; } } //查詢設備列表 int MyCanera::EnumDevices(MV_CC_DEVICE_INFO_LIST* pstDevList) { int temp= MV_CC_EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE, pstDevList); if (MV_OK != temp) { return -1; } return 0; } //連接相機 //id:自定義相機名稱 int MyCanera::connectCamera(string id) { int temp= EnumDevices(&m_stDevList); if(temp!=0) //設備更新成功接收命令的返回值為0,返回值不為0則為異常 return -1; if(m_stDevList.nDeviceNum==0) //未找到任何相機 return 2; for (unsigned int i = 0; i < m_stDevList.nDeviceNum; i++) { MV_CC_DEVICE_INFO* pDeviceInfo = m_stDevList.pDeviceInfo[i]; if (NULL == pDeviceInfo) { continue; } //qDebug() << (char*)pDeviceInfo->SpecialInfo.stGigEInfo.chUserDefinedName;//自定義相機名稱 //qDebug() << (char*)pDeviceInfo->SpecialInfo.stGigEInfo.chSerialNumber;//相機序列號 if(id == (char*)pDeviceInfo->SpecialInfo.stGigEInfo.chUserDefinedName||id == (char*)pDeviceInfo->SpecialInfo.stGigEInfo.chSerialNumber) { m_Device= m_stDevList.pDeviceInfo[i]; break; }else { continue; } } if(m_Device==NULL) { //未找到指定名稱的相機 qDebug() << "未找到指定名稱的相機"; return 3; } temp = MV_CC_CreateHandle(&m_hDevHandle, m_Device);//創建句柄 if(temp !=0) return -1; temp = MV_CC_OpenDevice(m_hDevHandle);//打開設備 if (temp !=0) { MV_CC_DestroyHandle(m_hDevHandle); m_hDevHandle = NULL; return -1; }else { setTriggerMode(1);//設置觸發模式:1-打開觸發模式 0-關閉觸發模式 return 0; } if (m_Device->nTLayerType == MV_GIGE_DEVICE)//設備類型為網絡接口 { //std::cout<<"Gige Camera"<<std::endl; } } //設置相機是否開啟觸發模式 int MyCanera::setTriggerMode(unsigned int TriggerModeNum) { int nRet = MV_CC_SetTriggerMode(m_hDevHandle,TriggerModeNum); if (MV_OK != nRet) { return -1; } } //啟動相機采集 int MyCanera::startCamera() { int temp=MV_CC_StartGrabbing(m_hDevHandle); if(temp!=0) { qDebug() << "抓圖失敗"; return -1; }else { qDebug() << "抓圖成功"; return 0; } } //發送軟觸發 int MyCanera::softTrigger() { int enumValue = MV_CC_SetEnumValue(m_hDevHandle,"TriggerSource",MV_TRIGGER_SOURCE_SOFTWARE); if(enumValue != 0){ qDebug() << "設置軟觸發失敗"; return -1; }else { qDebug() << "設置軟觸發"; } int comdValue= MV_CC_SetCommandValue(m_hDevHandle, "TriggerSoftware"); if(comdValue!=0) { qDebug() << "軟觸發失敗"; return -1; }else { qDebug() << "軟觸發一次"; return 0; } } //讀取相機中的圖像 int MyCanera::ReadBuffer(Mat &image) { unsigned int nBufSize = 0;//緩存大小 MVCC_INTVALUE stIntvalue; //獲取一幀數據的大小 memset(&stIntvalue, 0, sizeof(MVCC_INTVALUE)); int tempValue = MV_CC_GetIntValue(m_hDevHandle, "PayloadSize", &stIntvalue); if (tempValue != 0) { qDebug() << "GetIntValue失敗"; return -1; }else{qDebug() << "GetIntValue成功";} nBufSize = stIntvalue.nCurValue; m_pBufForDriver = (unsigned char *)malloc(nBufSize); MV_FRAME_OUT_INFO_EX stImageInfo; memset(&stImageInfo,0,sizeof(MV_FRAME_OUT_INFO)); qDebug() << MV_CC_StartGrabbing(m_hDevHandle); int timeout= MV_CC_GetOneFrameTimeout(m_hDevHandle, m_pBufForDriver, nBufSize, &stImageInfo, 1000); if(timeout!=0) { qDebug() << "GetOneFrameTimeout失敗"; return -1; } m_nBufSizeForSaveImage = stImageInfo.nWidth * stImageInfo.nHeight * 3 + 2048; m_pBufForSaveImage = (unsigned char*)malloc(m_nBufSizeForSaveImage); //向系統申請M_nBufSizeForSaveImage內存空間 bool isMono;//判斷是否為黑白圖像 switch (stImageInfo.enPixelType) //像素格式 { case PixelType_Gvsp_Mono8: case PixelType_Gvsp_Mono10: case PixelType_Gvsp_Mono10_Packed: case PixelType_Gvsp_Mono12: case PixelType_Gvsp_Mono12_Packed: isMono=true; break; default: isMono=false; break; } if(isMono) { image=Mat(stImageInfo.nHeight,stImageInfo.nWidth,CV_8UC1,m_pBufForDriver); } else { //轉換圖像格式為BGR8 MV_CC_PIXEL_CONVERT_PARAM stConvertParam = {0}; memset(&stConvertParam, 0, sizeof(MV_CC_PIXEL_CONVERT_PARAM)); stConvertParam.nWidth = stImageInfo.nWidth; //ch:圖像寬 | en:image width stConvertParam.nHeight = stImageInfo.nHeight; //ch:圖像高 | en:image height stConvertParam.pSrcData = m_pBufForDriver; //ch:輸入數據緩存 | en:input data buffer stConvertParam.nSrcDataLen = stImageInfo.nFrameLen; //ch:輸入數據大小 | en:input data size stConvertParam.enSrcPixelType = stImageInfo.enPixelType; //ch:輸入像素格式 | en:input pixel format //stConvertParam.enDstPixelType = PixelType_Gvsp_BGR8_Packed; //ch:輸出像素格式 | en:output pixel format 適用於OPENCV的圖像格式 stConvertParam.enDstPixelType = PixelType_Gvsp_RGB8_Packed; //ch:輸出像素格式 | en:output pixel format stConvertParam.pDstBuffer = m_pBufForSaveImage; //ch:輸出數據緩存 | en:output data buffer stConvertParam.nDstBufferSize = m_nBufSizeForSaveImage; //ch:輸出緩存大小 | en:output buffer size MV_CC_ConvertPixelType(m_hDevHandle, &stConvertParam); image=Mat(stImageInfo.nHeight,stImageInfo.nWidth,CV_8UC3,m_pBufForSaveImage); } return 0; } //設置心跳時間 int MyCanera::setHeartBeatTime(unsigned int time) { //心跳時間最小為500ms if(time<500) time=500; int temp=MV_CC_SetIntValue(m_hDevHandle, "GevHeartbeatTimeout", time); if(temp!=0) { return -1; } else { return 0; } } //設置曝光時間 int MyCanera::setExposureTime(float ExposureTimeNum) { int temp= MV_CC_SetFloatValue(m_hDevHandle, "ExposureTime",ExposureTimeNum ); if(temp!=0) return -1; return 0; } //關閉相機 int MyCanera::closeCamera() { int nRet = MV_OK; if (NULL == m_hDevHandle) { qDebug() << "沒有句柄,不用關閉"; return -1; } MV_CC_CloseDevice(m_hDevHandle); nRet = MV_CC_DestroyHandle(m_hDevHandle); m_hDevHandle = NULL; return nRet; }
mainwindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include "mycanera.h" QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); MyCanera *m_pcMycamera; MV_CC_DEVICE_INFO_LIST m_stDevList;//設備列表 string cameraName; //相機名稱 Mat imageMat; //使用OpenCV接受采集圖像 QImage cvMat2QImage(const cv::Mat& mat); QImage image; private slots: void on_pushButton_link_clicked(); void on_pushButton_close_clicked(); void on_pushButton_caiji_clicked(); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H
minwindow.cpp
#include "mainwindow.h" #include "ui_mainwindow.h" #include "mycanera.h" #include <QDebug> #include <QImage> #include <QImageReader> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); m_pcMycamera = new MyCanera; int neRt = m_pcMycamera->EnumDevices(&m_stDevList); qDebug() << neRt; qDebug() << m_stDevList.pDeviceInfo[0]->nTLayerType; //獲取相機的IP地址 if(1 == m_stDevList.pDeviceInfo[0]->nTLayerType){ int nIp1,nIp2,nIp3,nIp4; nIp1 = ((m_stDevList.pDeviceInfo[0]->SpecialInfo.stGigEInfo.nCurrentIp & 0xff000000) >> 24); nIp2 = ((m_stDevList.pDeviceInfo[0]->SpecialInfo.stGigEInfo.nCurrentIp & 0x00ff0000) >> 16); nIp3 = ((m_stDevList.pDeviceInfo[0]->SpecialInfo.stGigEInfo.nCurrentIp & 0x0000ff00) >> 8); nIp4 = (m_stDevList.pDeviceInfo[0]->SpecialInfo.stGigEInfo.nCurrentIp & 0x000000ff); QString nIp = QString("%1.%2.%3.%4").arg(nIp1).arg(nIp2).arg(nIp3).arg(nIp4); qDebug() << nIp; } } MainWindow::~MainWindow() { delete ui; } //連接相機 void MainWindow::on_pushButton_link_clicked() { cameraName = (char *)m_stDevList.pDeviceInfo[0]->SpecialInfo.stGigEInfo.chUserDefinedName; qDebug() << QString::fromStdString(cameraName); int linkCamera = m_pcMycamera->connectCamera(cameraName); qDebug() << linkCamera; if(linkCamera == 0){ qDebug() << "連接相機成功"; }else { qDebug() << "連接相機失敗"; } //開啟抓圖 int satrtCamera = m_pcMycamera->startCamera(); if(satrtCamera != 0){ qDebug() << "啟動相機采集失敗"; }else { qDebug() << "正在啟動相機采集信息"; } } //關閉設備 void MainWindow::on_pushButton_close_clicked() { //關閉設備,釋放資源 int close = m_pcMycamera->closeCamera(); if(close != 0){ qDebug() << "相機關閉失敗"; } } //采集單張圖像按鈕 void MainWindow::on_pushButton_caiji_clicked() { //設置相機軟觸發 int softTrigger = m_pcMycamera->softTrigger();//發送軟觸發 if(softTrigger != 0){ qDebug() << "失敗"; }else { qDebug() << "成功觸發一次"; } //讀取相機中的圖像 int readInt = m_pcMycamera->ReadBuffer(imageMat); if(readInt != 0){ qDebug() << "讀取圖像失敗"; } image = cvMat2QImage(imageMat); ui->label_image->setPixmap(QPixmap::fromImage(image)); } //Mat轉QImage函數 QImage MainWindow::cvMat2QImage(const cv::Mat& mat) { // 8-bits unsigned, NO. OF CHANNELS = 1 if(mat.type() == CV_8UC1) { QImage qimage(mat.cols, mat.rows, QImage::Format_Indexed8); // Set the color table (used to translate colour indexes to qRgb values) qimage.setColorCount(256); for(int i = 0; i < 256; i++) { qimage.setColor(i, qRgb(i, i, i)); } // Copy input Mat uchar *pSrc = mat.data; for(int row = 0; row < mat.rows; row ++) { uchar *pDest = qimage.scanLine(row); memcpy(pDest, pSrc, mat.cols); pSrc += mat.step; } return qimage; } // 8-bits unsigned, NO. OF CHANNELS = 3 else if(mat.type() == CV_8UC3) { // Copy input Mat const uchar *pSrc = (const uchar*)mat.data; // Create QImage with same dimensions as input Mat QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888); return image.rgbSwapped(); } else if(mat.type() == CV_8UC4) { // Copy input Mat const uchar *pSrc = (const uchar*)mat.data; // Create QImage with same dimensions as input Mat QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32); return image.copy(); } else { return QImage(); } }
運行結果:(ps:停止采集沒有用)