这里写自定义目录标题

  • 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\

直接上代码

界面

python opencv读取海康摄像头 opencv调用海康工业相机_opencv


头文件

#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;
    }
}

就到这里,本人也是小白,刚接触编程没多久,班门弄斧大神轻喷!