大恒水星相机SDK(实时采集)基于QT与C++

这篇具有很好参考价值的文章主要介绍了大恒水星相机SDK(实时采集)基于QT与C++。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

资料文档下载

1.环境搭建

本次的开发环境是基于vs2019使用QT的框架对大恒相机的SDK进行实时采集的操作。我们从零开始讲,根据上面的资料文档我们来添加一个新的项目,并且将C++的库文件添加进去。

首先,我们新建的时候使用QT的模板。
qt 大恒,qt,c++,相机

记住我们新建的路径,下面添加库文件的时候用得到
qt 大恒,qt,c++,相机

创建之后会让我们选择QT的模板,直接默认就好了,等待项目创建完成。待项目新建完成,根据资料文档根据以下路径/Samples/C++ SDK 找到两个文件夹,分别是inclib这两个文件都是大恒相机的库文件,我们导入就可以了。

qt 大恒,qt,c++,相机

库文件导入后需要在vs中进行设置,打开vs–右键解决方案–属性
qt 大恒,qt,c++,相机

qt 大恒,qt,c++,相机

到这里,其实我们已经基本搭建完了。不过下面还有一项我们可以选择一下,默认是窗口模式,我们选择控制台。因为窗口模式在我们调试的时候window的控制台不会显示从来,打印的信息就看不到了,所以可以设置一下。
qt 大恒,qt,c++,相机

前面的环境我们已经配置完成了,现在先来验证一下。在 .h的头文件里添加#include <GalaxyIncludes.h>,这是相机的SDK基本都在里面,具体是什么意思可以查看资料文件。添加完成后,运行程序如果正常运行且不报错,环境搭建就算是完成了,我们可以进行下一步了。

2.整体流程

这是整体的流程思路。点击vs里面的资源管理器,有一个UI的文件,打开并建立四个按钮控制设备的打开与关闭,采集和停止,再插入一个标签的控件用来显示图像。所以我们的画面一共有五个控件。在左侧的属性控制器——属性——objectName,可以修改控件对象名字。对于UI的画面,这里就已经完成了,后面就是代码的部分。

qt 大恒,qt,c++,相机

3.代码示例

这里是部分代码块的讲解,后是会有完整代码的。可能会有些不足,但大体思路是这样的,可以根据自己的理解去进行调整。

#include <QtWidgets/QMainWindow>
#include "ui_QtWidgetsApplication1.h"
#include <qdebug.h>
#include <qlabel.h>
#include <qthread.h>
#include <qqueue.h>
#include <GalaxyIncludes.h>

#pragma execution_character_set("utf-8")

class QtWidgetsApplication1 : public QMainWindow
{
    Q_OBJECT

public:
    QtWidgetsApplication1(QWidget* parent = Q_NULLPTR);

    Ui::QtWidgetsApplication1Class ui;


    bool m_bisOpen = false;
    bool m_bisSnap = false;                                     //按钮的显示(是否能点击)

    QQueue <QPixmap> ImageQueue;                                            //建立图像缓存队列

    void UpdataUI();                                            //用于更新画面

private slots:
    void open_camera();                                         //打开设备
    void close_camera();                                        //关闭设备
    void start_acquisition();                                   //开始采集
    void close_acquisition();                                   //关闭采集
};

这是QT的一个类,新建项目的时候就会一起新建出来QtWidgetsApplication1是我的项目的名字。根据自己下项目名字的不同,它也不同。这里除了建立一些信号槽和变量外,需要建立一个缓存队列。因为更新画面的时候我们读取图片是在通道里面读取,如果不放入缓存队列里再读取,会造成内存错误,这一点是需要注意的。

class CSampleCaptureEventHandler : public ICaptureEventHandler
{
public:
    CSampleCaptureEventHandler(QtWidgetsApplication1* mainWindow)
        : pMainWindow(mainWindow)
    {
    }
    void DoOnImageCaptured(CImageDataPointer& objImageDataPointer, void* pUserParam);

private:
    QtWidgetsApplication1* pMainWindow;                 //用于更新画面的一个指针
};

这是相机SDK里面的一个回调采集类,我们获取图片的方法有两种。一种是采单帧,另一种是回调采集,这些文档里面是有讲的,具体可以去查看文档。回调采集只是获取的图片,我们还需要将获取到的图片更新到显示窗口,下面就建立了一个指针用来更新画面。到这里头文件已经完成了,下面就是cpp文件的实现。


下面是cpp的全部代码,我会分别讲解每一个块的作用于联系

#include "QtWidgetsApplication1.h"

CGXDevicePointer objDeviceptr;
CGXStreamPointer ObjStreamPtr;
CGXFeatureControlPointer ObjFeatureControlPtr;

QImage blackImage;                                                      //用于黑色背景
ICaptureEventHandler* pCaptureEventHandler=nullptr;                     //建立回调采集变量


QtWidgetsApplication1::QtWidgetsApplication1(QWidget* parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);

    connect(ui.open_camear_button, &QPushButton::clicked, this, &QtWidgetsApplication1::open_camera);
    connect(ui.close_camear_button, &QPushButton::clicked, this, &QtWidgetsApplication1::close_camera);
    connect(ui.start_acquisition_button, &QPushButton::clicked, this, &QtWidgetsApplication1::start_acquisition);
    connect(ui.close_acquisition_button, &QPushButton::clicked, this, &QtWidgetsApplication1::close_acquisition);

    QImage blackImage(ui.label_picture->size(), QImage::Format_RGB888);
    blackImage.fill(Qt::black);
    ui.label_picture->setPixmap(QPixmap::fromImage(blackImage));// 设置 label 的 pixmap 为黑色背景图片

    UpdataUI();
}

void QtWidgetsApplication1::open_camera()
{
    IGXFactory::GetInstance().Init();                                               //初始化设备
    GxIAPICPP::gxdeviceinfo_vector vectorDeviceInfo;
    IGXFactory::GetInstance().UpdateDeviceList(1000, vectorDeviceInfo);             //枚举设备

    if (vectorDeviceInfo.size() <= 0)
    {
        qDebug() << "无可用设备!";
        m_bisOpen = false;
    }
    else
    {
        qDebug() << vectorDeviceInfo[0].GetModelName() << endl;
        GxIAPICPP::gxstring strSN = vectorDeviceInfo[0].GetSN();
        objDeviceptr = IGXFactory::GetInstance().OpenDeviceBySN(strSN, GX_ACCESS_EXCLUSIVE);        //通过SN码连接设备
        m_bisOpen = true;
    }
    UpdataUI();
}

void QtWidgetsApplication1::close_camera()
{
    try
    {
        
        if (m_bisSnap)
        {
        	
            ObjFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute();      //发送停止命令
            ObjStreamPtr->StopGrab();										//停止流通道采集 		
            ObjStreamPtr->UnregisterCaptureCallback();
            delete pCaptureEventHandler;
            pCaptureEventHandler = nullptr;						//停采、注销采集回调函数 
            
            ObjStreamPtr->Close();							//关闭流通道 
            objDeviceptr->Close();	
            IGXFactory::GetInstance().Uninit();   			//反初始化设备
        }
    }
    catch (...)
    {

    }
    qDebug() << "成功关闭设备";
    m_bisOpen = false;
    m_bisSnap = false;

    QImage blackImage(ui.label_picture->size(), QImage::Format_RGB888);
    blackImage.fill(Qt::black);
    ui.label_picture->setPixmap(QPixmap::fromImage(blackImage));// 设置 label 的 pixmap 为黑色背景图片

    UpdataUI();
}

void QtWidgetsApplication1::start_acquisition()
{
    if (m_bisOpen && !m_bisSnap)
    {
        
        ObjStreamPtr = objDeviceptr->OpenStream(0);

        ICaptureEventHandler* pCaptureEventHandler = new CSampleCaptureEventHandler(this);
        ObjStreamPtr->RegisterCaptureCallback(pCaptureEventHandler, NULL);                      //注册回调采集函数

        ObjStreamPtr->StartGrab();                                                      //开启流通道采集

        ObjFeatureControlPtr = objDeviceptr->GetRemoteFeatureControl();
        ObjFeatureControlPtr->GetEnumFeature("ExposureAuto")->SetValue("Off");                  //设置曝光模式
        ObjFeatureControlPtr->GetFloatFeature("ExposureTime")->SetValue(9000);                    //设置曝光度

        ObjFeatureControlPtr->GetCommandFeature("AcquisitionStart")->Execute();                     //发送开采命令

        m_bisSnap = true;
        qDebug() << "开始采集";
        UpdataUI();
    }
}

void QtWidgetsApplication1::close_acquisition()
{
    if (m_bisSnap)
    {
      
        // 等待子线程完成
        ObjFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute();              //停止采集
        ObjStreamPtr->StopGrab();
        ObjStreamPtr->UnregisterCaptureCallback();

        delete pCaptureEventHandler;
        pCaptureEventHandler = nullptr;
        ObjStreamPtr->Close();                                                              //关闭通道
        m_bisSnap = false;
        UpdataUI();
    }
}

void QtWidgetsApplication1::UpdataUI()                                                      //更新
{
    ui.open_camear_button->setEnabled(!m_bisOpen);
    ui.close_camear_button->setEnabled(m_bisOpen);
    ui.start_acquisition_button->setEnabled(m_bisOpen && !m_bisSnap);
    ui.close_acquisition_button->setEnabled(m_bisOpen && m_bisSnap);                        //更新按钮UI

    if (!ImageQueue.empty())
    {
        QPixmap newImage = ImageQueue.dequeue();
        QMetaObject::invokeMethod(this, [this, newImage]() {
            ui.label_picture->setScaledContents(true);
            ui.label_picture->setPixmap(newImage);
         });
    }                                                                           //读取队列里的图片并显示

}                               
void CSampleCaptureEventHandler::DoOnImageCaptured(CImageDataPointer& objImageDataPointer, void* pUserParam)
{
        if (objImageDataPointer->GetStatus() == GX_FRAME_STATUS_SUCCESS)
        {
            qint64 m_width = objImageDataPointer->GetWidth();
            qint64 m_height = objImageDataPointer->GetHeight();
            uchar* pbit = (uchar*)objImageDataPointer->GetBuffer();

            QImage newImage(pbit, m_width, m_height, QImage::Format_Indexed8);
            newImage = newImage.scaled(m_width, m_height, Qt::KeepAspectRatio, Qt::SmoothTransformation);

            double d = ObjFeatureControlPtr->GetFloatFeature("CurrentAcquisitionFrameRate")->GetValue();
            qDebug() << "当前帧率:" << d;

            pMainWindow->ImageQueue.enqueue(QPixmap::fromImage(newImage));
            pMainWindow->UpdataUI();
            
        }
}


QtWidgetsApplication1

里面的四个connect分别对应了UI画面里的四个按钮功能,而下面的设置黑色背景图片可以设置也可以不设置。不设置就是在不获取图像的时候因为label没有东西可以显示,它是白色的也就是看不到了。设置完成了,记得更新画面UpdataUI这个程序相当于一个初始化的作用了。

   QImage blackImage(ui.label_picture->size(), QImage::Format_RGB888);
    blackImage.fill(Qt::black);
    ui.label_picture->setPixmap(QPixmap::fromImage(blackImage));// 设置 label 的 pixmap 为黑色背景图片

    UpdataUI();

open_camera(打开设备)

根据上面流程图可以知道进来的第一步就是先初始化设备,然后就是寻找设备了(枚举设备),上面的程序有注释这里就不显示代码了。
枚举设备后,根据找到的设备数量进行判断。m_bisOpen就是设置按钮的状态了,如果成功打开设备UI上面的按钮就不能再按钮了,所以要如果成功打开了就设置为不可用,后面的其他程序也是一个道理。qDebug相当于cout输出一些信息在控制台方便调试,连接设备的方式有四种,这里使用SN码的方式连接,其他方法请查看手册

    if (vectorDeviceInfo.size() <= 0)
    {
        qDebug() << "无可用设备!";
        m_bisOpen = false;
    }
    else
    {
        qDebug() << vectorDeviceInfo[0].GetModelName() << endl;
        GxIAPICPP::gxstring strSN = vectorDeviceInfo[0].GetSN();
        objDeviceptr = IGXFactory::GetInstance().OpenDeviceBySN(strSN, GX_ACCESS_EXCLUSIVE);        //通过SN码连接设备
        m_bisOpen = true;
    }
    UpdataUI();

close_camera(关闭设备)

有开必有关,根据m_bisOpen判断设备是否被打开了。后面就不管相机处于什么状态都给它停止并关闭了,这个程序跟close_acquisition意思是差不多的,后面我就不讲这个程序了。两个程序的区别一个是停止设备,另一个是先停止关闭这个很好理解。

start_acquisition(开始采集)

打开设备后,已经完成了流程图上面的三个步骤,这里将完成设置参数开始采集的操作。具体的程序上面的注释已经有了,但这里我讲一个需要注意的小点也是我自己做的时候遇到的问题——曝光度。通过程序去设置的曝光度是会影响画面的帧率的,设置的越高帧率越低,后面可以自行尝试。到这一个程序的最后一步,只是发送了开采命令并没有对图像进行读取与显示的操作,后面的两个程序才是关键的。

DoOnImageCaptured(回调采集类里面的操作)

到这里就正式开始了对图像的处理了,首先建立的三个变量是获取图片的基本信息。

qint64 m_width = objImageDataPointer->GetWidth();
qint64 m_height = objImageDataPointer->GetHeight();
uchar* pbit = (uchar*)objImageDataPointer->GetBuffer();

建立一个QImage将刚刚获取的图像数据放进去,注意QImage::Format_Indexed8根据自己相机能获取到的图像数据进行赋值,具体是写什么去官网查看自己相机的参数,我的相机的原始数据是Mono8的一个灰度图。而且下面的代码调用了scaled()函数对新创建的图像进行缩放操作,使用Qt::KeepAspectRatio保持宽高比的方式进行缩放,并使用Qt::SmoothTransformation参数来指定平滑的缩放。

QImage newImage(pbit, m_width, m_height, QImage::Format_Indexed8);
newImage = newImage.scaled(m_width, m_height, Qt::KeepAspectRatio, Qt::SmoothTransformation);

下面就是一个读取当前相机帧率的操作,可有可无,自己看着办。

double d = ObjFeatureControlPtr->GetFloatFeature("CurrentAcquisitionFrameRate")->GetValue();
qDebug() << "当前帧率:" << d;

这个就重要了,再上面处理好的图像先放到缓存队列enqueue里面,再调用UpdataUI进行画面的更新,这个函数是专门用来进行UI画面的显示与更新的。传上去这里就不管它了,它的任务已经完成了。

pMainWindow->ImageQueue.enqueue(QPixmap::fromImage(newImage));
pMainWindow->UpdataUI();

会不会有疑问,明明没有调用这个程序,为什么它能采集图像呢?它是相机SDK里面的一个虚基类,开启回调采集的时候,相机获取到图片的时候就告诉你,它有一张图片。你拿到之后又告诉相机“我要下一张图片”,相机获取到了图片又跟你说了一遍,一直循环下去。而且控制它开始与停止的就是下面的两个函数,它们位于是start_acquisitionclose_acquistion里面。

ObjFeatureControlPtr->GetCommandFeature("AcquisitionStart")->Execute();                     //发送开采命令
ObjFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute();              //停止采集

UpdataUI(更新画面)

这是最后一个了,累死啦!!!
程序分两个部分,上半部分是更新UI界面的按钮的,下半部分就是更新图片进行实时显示的操作。

    ui.open_camear_button->setEnabled(!m_bisOpen);
    ui.close_camear_button->setEnabled(m_bisOpen);
    ui.start_acquisition_button->setEnabled(m_bisOpen && !m_bisSnap);
    ui.close_acquisition_button->setEnabled(m_bisOpen && m_bisSnap);                        //更新按钮UI

这一部分就是通过读取缓存队列里面的图像,然后进行显示。在缓存队列里面我们是先进先出的原则,这样做无论在什么时候对采集进行停止还是关闭设备,都不会因为没有来得及显示图片而进行内存管理错误,来不及显示的图片就暂时放在了队列里面,保证了程序的安全与稳定。

    if (!ImageQueue.empty())
    {
        QPixmap newImage = ImageQueue.dequeue();
        QMetaObject::invokeMethod(this, [this, newImage]() {
            ui.label_picture->setScaledContents(true);
            ui.label_picture->setPixmap(newImage);
         });
    }                                                                           //读取队列里的图片并显示

4.结果显示

qt 大恒,qt,c++,相机文章来源地址https://www.toymoban.com/news/detail-759448.html

到了这里,关于大恒水星相机SDK(实时采集)基于QT与C++的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 使用 Python SDK 调试大恒相机记录

    使用长广溪机器人作画需要用到摄像头拍摄人像照片,经过推荐,使用大恒相机,型号为MER-503-36U3C,该相机为USB彩色相机。 更新了 大恒相机多线程采集图像 在官网下载驱动软件Galaxy_Windows_CN_32bits-64bits_1.23.2305.9161.zip并安装。 安装完成后,在安装路径下可以看到如图所示两个

    2024年02月05日
    浏览(60)
  • 大恒相机使用Python SDK调试记录

    使用长广溪机器人作画需要用到摄像头拍摄人像照片,经过推荐,使用大恒相机,型号为MER-503-36U3C,该相机为USB彩色相机。 更新了 大恒相机多线程采集图像 在官网下载驱动软件Galaxy_Windows_CN_32bits-64bits_1.23.2305.9161.zip并安装。 安装完成后,在安装路径下可以看到如图所示两个

    2024年02月09日
    浏览(30)
  • 海康工业相机SDK连接demo,Qt界面显示

    在机器视觉开发过程中,经常使用工业相机采集图像,以下采用海康机器人提供的SDK开发demo,使用语言C++,界面显示使用的Qt。SDK来自MVS 3.1版本中附属的Development文件夹。完整的项目链接地址为: 海康工业相机SDK的Demo源代码C++版本 附录海康工业相机的命名方式: 海康工业相

    2024年02月13日
    浏览(43)
  • (三)Qt+OpenCV调用海康工业相机SDK抓拍示例

    提示:这里是该系列文章的所有文章的目录 第一章: (一)Qt+OpenCV调用海康工业相机SDK示例开发 第二章: (二)Qt多线程实现海康工业相机图像实时采集 第三章: (三)Qt+OpenCV调用海康工业相机SDK抓拍示例 在这系列文章中,讲述了Qt下结合OpenCV与海康工业相机的使用,对

    2024年04月08日
    浏览(73)
  • (一)Qt+OpenCV调用海康工业相机SDK示例开发

    提示:这里是该系列文章的所有文章的目录 第一章: (一)Qt+OpenCV调用海康工业相机SDK示例开发 第二章: (二)Qt多线程实现海康工业相机图像实时采集 近期在Qt环境下进行海康工业相机的使用开发,发现海康提供的示例没有Qt的demo,而其中有基于MFC框架的示例,所以在这

    2024年02月03日
    浏览(56)
  • Qt 实现的万能采集库( 屏幕/相机/扬声器/麦克风采集)

    【写在前面】          之前应公司需要,给公司写过一整套直播的库( 推拉流,编解码),类似于 libobs 。         结果后来因为没有相关项目,便停止开发维护了。         不过里面很多有用的组件,然后也挺好用的,遂开源出来一部分。         因此,本篇就简单讲

    2024年04月27日
    浏览(24)
  • (一)Qt下实现多个海康工业相机内触发采集回调取流显示

    提示:这里是该系列文章的所有文章的目录 第一章:(一)Qt下实现多个海康工业相机内触发采集回调取流显示 第二章:(二)Qt下多线程实现多个海康工业相机内触发采集回调取流显示 在我之前所记录的关于海康工业相机的系列文章中 ,讲述的是使用外触发采集模式中的

    2024年02月16日
    浏览(41)
  • (二)Qt下多线程实现多个海康工业相机内触发采集回调取流显示

    提示:这里是该系列文章的所有文章的目录 第一章:(一)Qt下实现多个海康工业相机内触发采集回调取流显示 第二章:(二)Qt下多线程实现多个海康工业相机内触发采集回调取流显示 在本系列的上一篇文章中,我们讲述了实现海康工业相机的连接,采用内触发采集模式,

    2024年02月16日
    浏览(34)
  • 水星U3相机在Halcon里面不能使用GenICamTL库采集解决方案

    在halcon里面使用采集助手,U3相机不能使用GenICamTL库实时采集。 (首先确保已经安装好水星相机驱动,如果没有安装,GenICamTL库会找不到)  查看电脑的系统环境变量,打开对应电脑位数的值。   只留下大恒水星相机的值,其他的删除,即可以在halcon里面直接使用GenICamTL库采

    2024年02月12日
    浏览(29)
  • FPGA驱动FT601实现USB3.0相机HDMI视频采集 提供工程源码和QT上位机源码

    目前USB3.0的实现方案很多,但就简单好用的角度而言,FT601应该是最佳方案,因为它电路设计简单,操作时序简单,软件驱动简单,官方甚至提供了包括FPGA驱动在内的丰富的驱动源码和测试软件; 本设计用FPGA驱动FT601芯片实现USB3.0数据通信,使用同步245模式通信,提供vivad

    2024年02月09日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包