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

资料文档下载

1.环境搭建

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

首先,我们新建的时候使用QT的模板。
在这里插入图片描述

记住我们新建的路径,下面添加库文件的时候用得到
在这里插入图片描述

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

在这里插入图片描述

库文件导入后需要在vs中进行设置,打开vs–右键解决方案–属性
在这里插入图片描述

在这里插入图片描述

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

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

2.整体流程

初始化设备
枚举设备
打开设备
设置参数
开始采集
采集图像/图像处理
停止采集
关闭相机

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

在这里插入图片描述

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.结果显示

在这里插入图片描述

  • 14
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 12
    评论
使用OpenCV和大恒C SDK可以轻松地采集大恒水星相机的图像。首先,需要下载和安装相应的SDK,并确保与相机的连接正常。接下来,可以使用OpenCV提供的函数来打开相机,并设置相应的参数,如分辨率和帧率。然后,可以通过循环不断地从相机中读取图像帧,并使用OpenCV进行图像处理和分析。 可以使用OpenCV中的cv::VideoCapture类来打开相机连接,并设置相应的参数。例如: ``` cv::VideoCapture capture; capture.open(0); // 打开相机连接 if (!capture.isOpened()) { // 相机连接失败 return -1; } capture.set(cv::CAP_PROP_FRAME_WIDTH, 1280); // 设置图像宽度 capture.set(cv::CAP_PROP_FRAME_HEIGHT, 720); // 设置图像高度 capture.set(cv::CAP_PROP_FPS, 30); // 设置帧率 ``` 然后,可以在循环中读取相机图像,并使用OpenCV函数进行处理。例如,可以使用cv::imshow函数显示图像,使用cv::imwrite保存图像,使用cv::cvtColor将图像转换为不同的颜色空间等等。 ``` cv::Mat frame; while (capture.read(frame)) { cv::imshow("Camera", frame); // 显示图像 // 进行其他的图像处理操作 int key = cv::waitKey(1); if (key == 27) { // 按下Esc键退出循环 break; } } ``` 最后,记得在程序结束时,释放相机连接和关闭窗口: ``` capture.release(); // 释放相机连接 cv::destroyAllWindows(); // 关闭窗口 ``` 以上就是使用OpenCV和大恒C SDK采集大恒水星相机图像的基本步骤。可以根据实际需求,结合OpenCV提供的丰富功能,进行图像处理、计算机视觉和图像分析等任务。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

畵颜卿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值