大恒相机实时采图

2023-05-16

目录

  • 前言
  • 正文
    • 准备工作
    • 设备的初始化
    • 设备信息的获取
    • 主动采图
    • 相机参数配置
      • 创建doc树
      • 获取doc树下的每一个元素并将其信息写入xml文件中
    • 被动采图
  • 总结

前言

本篇博客稍微记录一下我所写的插件。具体内容是有关于大恒相机的,关于这个相机,相信搜索到这个博客的应该都有所了解了,关于这个插件,我所完成的功能是:利用该相机提供的SDK完成主动采图,回调采图,以及显示出该相机的参数列表这三个主要的功能。下面就是正文,我只会贴属于这个插件的代码,其他部分就不贴出来了。所以,应该只能给你编写的代码一些启示,但就目前这些代码,却没办法运行起来这个代码的,你应该根据软件的功能去继承一些虚函数,就可以完成这个插件啦,这个博客只是节省你看SDK文档的时间,挺多东西,你应该可以从这上面得到。注意,如果程序出现没有办法加载这个插件的话,要检查一下这个相机的SDK下的dll文件有没有放在程序的运行路径之下,这个很重要,有可能会导致你的插件无法加载。
我这篇文章是三个功能的集合,如果想要看比较详细的,可以移步到另外三篇文章,这里给出地址:

大恒相机开发实践(1)——实时采图
大恒相机开发实践(2)——触发采图
大恒相机开发实践(3)——参数设置

正文

准备工作

首先,开始写这个插件肯定是从下载这个相机的SDK开始的,下面就给出下载链接。
大恒相机SDK,我们需要从这个软件的安装目录中拿出我们所需要的东西,需要的东西我也打包成一个链接:
大恒相机必备材料。 如果没积分的话,私信或评论噢。

设备的初始化

MDeviceDahengG3UC.cpp
下面这个函数的主要功能就是完成设备的初始化工作,下面这个函数没有什么跟那个SDK挂上钩的地方,接下去的这个函数比较重要。

bool MDeviceDahengG3UC::InitDevice(QString index,QString identifier)
{
    m_cCameraID = index;
    m_cIdentifier = identifier;
    bool ret = false;
#ifdef WIN32_DAHENG_GEV
    if(DeviceLoading(m_cIdentifier))
    {
        m_pConfigureObj = new MConfigureDahengG3UC();
        m_pConfigureObj->InitConfigure(m_cCameraID,this);
        m_pConfigureObj->RegisterConfigureCallback(m_fXmlChange,m_pCallUser);//注册配置文件的回调函数

        QVariant wVal;
        QVariant hVal;
        QVariant pixelForamt;
        QVariant frameRate;

        this->GetParameter("Width",wVal);
        this->GetParameter("Height",hVal);
        this->GetParameter("PixelFormat",pixelForamt);

        if(IsExistParameter("ResultingFrameRate"))
        {
            qDebug()<<"resultingFrameRate";
            this->GetParameter("ResultingFrameRate",frameRate);
        }
        else if(IsExistParameter("ResultingFrameRateAbs"))
        {
            this->GetParameter("ResultingFrameRateAbs",frameRate);
        }

        m_iWidth = wVal.toInt();
        m_iHeight = hVal.toInt();
        m_cPixelFormat = pixelForamt.toString();
        m_fFrameRate = frameRate.toFloat();
        ret = true;
    }
#endif
    return ret;
}

下面这个函数就有比较多值得学习的地方,以下讲的地方都是从SDK中得出的。

  1. 首先,是相机设备的初始化
IGXFactory::GetInstance().Init();//这个是进行实例的初始化
GxIAPICPP::gxdeviceinfo_vector vectorDeviceInfo;
IGXFactory::GetInstance().UpdateDeviceList(1000, vectorDeviceInfo);
//通过这个就可以获得相关的设备信息vectorDeviceInfo
  1. 接下来,就是获得当前设备的所有信息,这里就列举一些信息的获得就好了。这里可以稍微注意一下,强制类型转换在这里的应用。
GxIAPICPP::gxstring SerialNumber;
QString SerialNumber2;
GX_DEVICE_CLASS_LIST gClass2 = vectorDeviceInfo[n].GetDeviceClass();
SerialNumber = vectorDeviceInfo[n].GetSN();
SerialNumber2 = static_cast<QString>(SerialNumber);
  1. 接下来,根据设备序列号打开设备并获得实例
m_objDevicePtr  = IGXFactory::GetInstance().OpenDeviceBySN(strSN,GX_ACCESS_EXCLUSIVE);
  1. 打开流对象
 m_objStreamPtr = m_objDevicePtr->OpenStream(0);
  1. 下面这个就是比较完整的函数了。
bool MDeviceDahengG3UC::DeviceLoading(QString identifier)
{
    m_bLoaded = false;
    bool bIsDeviceOpen = false;              ///< 设备是否已打开标识
    bool bIsStreamOpen = false;              ///< 设备流是否已打开标识
#ifdef WIN32_DAHENG_GEV
    int nRet = -1;
    IGXFactory::GetInstance().Init();
    GxIAPICPP::gxdeviceinfo_vector vectorDeviceInfo;
    IGXFactory::GetInstance().UpdateDeviceList(1000, vectorDeviceInfo);
    //判断当前设备连接个数

    if (vectorDeviceInfo.size() <= 0)
    {
        qDebug()<<"No Device!";
        return m_bLoaded;
    }
    else
    {
        for (uint n = 0; n < vectorDeviceInfo.size(); n++)
        {
            //判断枚举到的设备是否为Gige
            bool accessStatus = vectorDeviceInfo[n].GetAccessStatus();

            if(accessStatus)
            {
                GxIAPICPP::gxstring SerialNumber;
                QString SerialNumber2;

                GX_DEVICE_CLASS_LIST gClass2 = vectorDeviceInfo[n].GetDeviceClass();
                SerialNumber = vectorDeviceInfo[n].GetSN();
                SerialNumber2 = static_cast<QString>(SerialNumber);

                if(SerialNumber2.length()>=16)
                    SerialNumber2 = SerialNumber2.left(16);

                if(identifier.contains(SerialNumber2))
                {
                    m_cSerialNumber = SerialNumber2;
                    m_cModelName = static_cast<QString>(vectorDeviceInfo[n].GetModelName());
                    m_cCameraVendor = vectorDeviceInfo[n].GetVendorName();
                    m_cUserDefine = vectorDeviceInfo[n].GetUserID();
                    m_cDeviceVersion = vectorDeviceInfo[n].GetDisplayName();
                    GxIAPICPP::gxstring strSN  = vectorDeviceInfo[n].GetSN();
                    m_objDevicePtr  = IGXFactory::GetInstance().OpenDeviceBySN(strSN,GX_ACCESS_EXCLUSIVE);
                    m_objStreamPtr = m_objDevicePtr->OpenStream(0);
                    m_pCaptureEventHandler = new CSampleCaptureEventHandler();
                    m_bLoaded = true;
                    bIsDeviceOpen = true;
                    break;
                }

            }
        }
    }
    return m_bLoaded;
#endif
}

设备信息的获取

MDeviceDahengG3UCInfo.cpp
下面这个函数主要是获取根据SDK获取对象的相机信息,并且是相对上面那个函数会较全。

  1. 首先也是要进行初始化,并获得设备信息对象。
IGXFactory::GetInstance().Init();
GxIAPICPP::gxdeviceinfo_vector vectorDeviceInfo;
IGXFactory::GetInstance().UpdateDeviceList(1000, vectorDeviceInfo);
  1. 然后就是获取设备信息的那部分了。注意一些强制类型转换。
  2. 下面这个就是比较完整的函数了。
bool MDeviceDahengG3UCInfo::SearchDeviceInfos(QStringList &lInfo)
{
    bool ret = false;
#ifdef WIN32_DAHENG_GEV
    int nRet = -1;
    IGXFactory::GetInstance().Init();
    GxIAPICPP::gxdeviceinfo_vector vectorDeviceInfo;
    IGXFactory::GetInstance().UpdateDeviceList(1000, vectorDeviceInfo);

    if(vectorDeviceInfo.size()>0)
    {
        for (uint32_t i = 0; i < vectorDeviceInfo.size(); i++)
        {
            if(vectorDeviceInfo[i].GetDeviceClass() == GX_DEVICE_CLASS_GEV||vectorDeviceInfo[i].GetDeviceClass()==GX_DEVICE_CLASS_U3V)
            {
                GxIAPICPP::gxstring ModelName = vectorDeviceInfo[i].GetModelName();
                QString ModelName2 = static_cast<QString>(ModelName);
                GxIAPICPP::gxstring CameraVendor = vectorDeviceInfo[i].GetVendorName();
                QString CameraVendor2 = static_cast<QString>(CameraVendor);
                GxIAPICPP::gxstring UserID = vectorDeviceInfo[i].GetUserID();
                QString UserID2 = static_cast<QString>(UserID);
                GxIAPICPP::gxstring DeviceID = vectorDeviceInfo[i].GetDeviceID();
                QString DeviceID2 = static_cast<QString>(DeviceID);
                GxIAPICPP::gxstring DeviceIP = vectorDeviceInfo[i].GetIP();
                QString DeviceIP2 = static_cast<QString>(DeviceIP);
                GxIAPICPP::gxstring DeviceSN = vectorDeviceInfo[i].GetSN();
                QString DeviceSN2 = static_cast<QString>(DeviceSN);
                GxIAPICPP::gxstring DeviceDisplayName = vectorDeviceInfo[i].GetDisplayName();
                QString DeviceDisplayName2 = static_cast<QString>(DeviceDisplayName);
                bool DeviceStatus = vectorDeviceInfo[i].GetAccessStatus();
                QString devInfo;
                devInfo += QString("%1:%2;").arg(XML_TLAYER_TYPE)      //传输协议
                                                    .arg(XML_TLAYER_U3V);
                devInfo += QString("%1:%2;").arg(XML_DRIVER_TYPE)      //驱动类型
                                                    .arg(m_cCameraType);
                devInfo += QString("%1:%2;").arg(XML_DEVICE_MODEL_NAME)//设备型号
                                                    .arg(ModelName2);
                devInfo += QString("%1:%2;").arg(XML_DEVICE_USER_DEFINE)//自定义名称
                                                    .arg(UserID2);
                devInfo += QString("%1:%2;").arg(XML_DEVICE_ID)         //序列号
                                                    .arg(DeviceSN2);
                devInfo += QString("%1:%2;").arg(XML_DEVICE_VENDOR)     //生产厂家
                                                    .arg(CameraVendor2);
                devInfo += QString("%1:%2;").arg(XML_DEVICE_VERSION)    //设备版本
                                                    .arg(DeviceDisplayName2);
                devInfo += QString("%1:%2;").arg(XML_DEVICE_STATUS)     //设备状态
                                                    .arg(DeviceStatus);
                qDebug()<<"=>GetDeviceDaHengU3V:"<<devInfo;
                lInfo << devInfo;

            }
        }
    }

#endif
    return ret;
}

主动采图

下面这个函数是主动采图的两个函数,所谓主动采图,就是通过按钮,用户主动去控制采图的过程,控制定时器定时器的开关,从而得到在一定的时间内可以连续采图,最终得到较好的连续的图像。

  1. 首先,开启流通道采集
if(!m_objStreamPtr.IsNull())
{
     qDebug()<<"MDeviceDahengG3UC::AcquisitionStart m_objStreamPtr";
    //objStreamPtr->SetAcqusitionBufferNumber(10);//必须在调用StartGrab开启流通道的采集之前,设置采集buffer个数,否则设置无效。
    m_objStreamPtr->StartGrab();
}
  1. 给设备发送开始开采命令
m_objFeatureControlPtr = m_objDevicePtr->GetRemoteFeatureControl();
 if(!m_objFeatureControlPtr.IsNull())
{
    m_objFeatureControlPtr->GetCommandFeature("AcquisitionStart")->Execute();
    ret = RETURN_OK;
}
  1. 在这里调用相机参数配置的函数
if(m_pConfigureObj->UpdateConfigureFromDevice())
    m_pConfigureObj->SlotConfigChanged();

if(m_pConfigureObj->UpdateSimplyConfigureFromDevice())
    m_pConfigureObj->SlotSimplyConfigChanged();
  1. 给设备发送关闭开采的命令
m_objFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute();
    m_objStreamPtr->StopGrab();
    //关闭流通道
    m_objStreamPtr->Close();

下面这个是比较打开采图的函数,关闭采图的函数

qint32  MDeviceDahengG3UC::AcquisitionStart()
{
    qint32 ret = RETURN_FAIL;
#ifdef WIN32_DAHENG_GEV

    if(m_bLoaded)
    {
        if(m_bStopWork)
        {
            m_objFeatureControlPtr = m_objDevicePtr->GetRemoteFeatureControl();
            m_objImageProcessPtr = m_objDevicePtr->CreateImageProcessConfig();
            bool m_bIsColorFilter = m_objFeatureControlPtr->IsImplemented("PixelColorFilter");

            //开启流通道采集
            if(!m_objStreamPtr.IsNull())
            {
                qDebug()<<"MDeviceDahengG3UC::AcquisitionStart m_objStreamPtr";
                //objStreamPtr->SetAcqusitionBufferNumber(10);//必须在调用StartGrab开启流通道的采集之前,设置采集buffer个数,否则设置无效。
                m_objStreamPtr->StartGrab();
            }

            //给设备发送开采命令
            if(!m_objFeatureControlPtr.IsNull())
            {
                m_objFeatureControlPtr->GetCommandFeature("AcquisitionStart")->Execute();
                ret = RETURN_OK;
            }

            if(m_pConfigureObj->UpdateConfigureFromDevice())
                m_pConfigureObj->SlotConfigChanged();

            if(m_pConfigureObj->UpdateSimplyConfigureFromDevice())
                m_pConfigureObj->SlotSimplyConfigChanged();

            m_bStopWork =false;
        }
    }
#endif
    return ret;
}

qint32  MDeviceDahengG3UC::AcquisitionStop()
{
    qint32 ret = RETURN_FAIL;
#ifdef WIN32_DAHENG_GEV
    if(m_bLoaded)
    {
        if(!m_bStopWork)
        {
            //停采
            if((!m_objFeatureControlPtr.IsNull())&&(!m_objStreamPtr.IsNull()))
            {
                m_objFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute();
                m_objStreamPtr->StopGrab();
                //关闭流通道
                m_objStreamPtr->Close();
            }

            if(m_pConfigureObj->UpdateConfigureFromDevice())
                m_pConfigureObj->SlotConfigChanged();

            if(m_pConfigureObj->UpdateSimplyConfigureFromDevice())
                m_pConfigureObj->SlotSimplyConfigChanged();
            ret = RETURN_OK;
            m_bStopWork = true;
        }
    }
#endif
    return ret;
}

这两个函数一旦实现,基本就完成主动采图的功能了,接下来就是相机参数的配置。

相机参数配置

ConfigureDahengG3UC.cpp
首先,这里给出的只是很小的一部分代码,只是插件中的一部分,至于节点成树的那部分就没有贴出来了。

创建doc树

  1. 首先判断好一些比较重要的指针传进来别是零了,所以,这里就要完成好检测的那个功能。
if((Q_NULLPTR == m_pNodeMap))

if(m_pDevice->m_objDevicePtr.IsNull())
  1. 通过相机的SDK得到相对应的参数集合featureNameList,featureRemoteNameList,它总共有两个参数集合。
GxIAPICPP::gxstring_vector featureNameList;
GxIAPICPP::gxstring_vector featureRemoteNameList;
CGXFeatureControlPointer featureControl = m_pDevice->m_objDevicePtr->GetFeatureControl();

if(!featureControl.IsNull())
    featureControl->GetFeatureNameList(featureNameList);//获取第一个属性参数集合featureNameList
GXFeatureControlPointer featureControl2 = m_pDevice->m_objDevicePtr->GetRemoteFeatureControl();
if(!featureControl2.IsNull())
    featureControl2->GetFeatureNameList(featureRemoteNameList);//获取第二个属性参数集合featureRemoteNameList
  1. 创建xml文件中的头部的一些信息还有创建根节点
QDomDocument *m_doc = new QDomDocument();
QDomProcessingInstruction instruction;
instruction = m_doc->createProcessingInstruction("xml","version=\"1.0\" encoding=\"UTF-8\"");
m_doc->appendChild(instruction);

//create root element
QDomElement root = m_doc->createElement(XML_TAG_CONFIGUR);
m_doc->appendChild(root);

  1. 接下来就是拿出一个一个的参数出来弄成节点,然后往下传
for(size_t i=0;i<featureNameList.size();i++)
{
   GxIAPICPP::gxstring  name = featureNameList.at(i);
   QDomElement param = m_doc->createElement(XML_TAG_PARAMETER);
   if(CreateElement(name,m_pNodeMap,param,featureControl))
   {
       root.appendChild(param);
   }
}

  1. 下面这个函数是比较完整的函数
bool  MConfigureDahengG3UC::CreateDocXml()
{
    bool ret = false;
#ifdef WIN32_DAHENG_GEV

    if((Q_NULLPTR == m_pNodeMap))
    {
        qDebug()<<"MConfigureDahengG3UC::CreateDocXml m_pNodeMap is null";
        return ret;
    }
    if(m_pDevice->m_objDevicePtr.IsNull())
    {
        qDebug()<<"MConfigureDahengG3UC::CreateDocXml m_pDevice->m_objDevicePtr.IsNull";
        return ret ;
    }

    GxIAPICPP::gxstring_vector featureNameList;
    GxIAPICPP::gxstring_vector featureRemoteNameList;
    CGXFeatureControlPointer featureControl = m_pDevice->m_objDevicePtr->GetFeatureControl();

    if(!featureControl.IsNull())
        featureControl->GetFeatureNameList(featureNameList);//获取第一个属性参数集合featureNameList

    CGXFeatureControlPointer featureControl2 = m_pDevice->m_objDevicePtr->GetRemoteFeatureControl();

    if(!featureControl2.IsNull())
        featureControl2->GetFeatureNameList(featureRemoteNameList);//获取第二个属性参数集合featureRemoteNameList

    //开始创建xml文件
    QDomDocument *m_doc = new QDomDocument();
    QDomProcessingInstruction instruction;
    instruction = m_doc->createProcessingInstruction("xml","version=\"1.0\" encoding=\"UTF-8\"");
    m_doc->appendChild(instruction);

    //create root element
    QDomElement root = m_doc->createElement(XML_TAG_CONFIGUR);
    m_doc->appendChild(root);

    //包含一些本地属性,不同类型的设备具备的功能也不一样
    for(size_t i=0;i<featureNameList.size();i++)
    {
        GxIAPICPP::gxstring  name = featureNameList.at(i);
        QDomElement param = m_doc->createElement(XML_TAG_PARAMETER);
        if(CreateElement(name,m_pNodeMap,param,featureControl))
        {
            root.appendChild(param);
        }
    }

    //包含主要设备信息,比如宽高、曝光增益等,一般用户主要使用此属性控制器即可。
    for(size_t i=0;i<featureRemoteNameList.size();i++)
    {
        GxIAPICPP::gxstring  name = featureRemoteNameList.at(i);
        QDomElement param = m_doc->createElement(XML_TAG_PARAMETER);
        if(CreateElement(name,m_pNodeMap,param,featureControl2))
        {
            root.appendChild(param);
        }
    }

    ret = m_pNodeMap->SetDocument(m_doc);
#endif
    return ret;
}

获取doc树下的每一个元素并将其信息写入xml文件中

ConfigureDahengG3UC.cpp
这个函数,主要是接受该节点的属性,然后根据这个节点的类型创建不同类型连接在父节点的后面,并将其信息写入xml文件中

  1. 首先,对传进来的数据类型进行类型转换,这个转换还是蛮难的,至少我是花了挺多的时间研究这个东西。接下来就是获得节点的类型。
GxIAPICPP::gxstring gxName;
QString name = QString::fromStdString(gxName.c_str());
GX_FEATURE_TYPE gxType = featureControl->GetFeatureType(gxName);

接下来,就可以开始判断该数据的数据类型是什么,然后根据这个类型,调用对应的取信息的函数,就可以获取到一些比较必要的信息,将其写入xml文件之中。下面,列举两个:

if(gxType==GX_FEATURE_INT)
        {
            bool gxIsWriteable = featureControl->IsWritable(gxName);
            bool bIsReadable = featureControl->IsReadable(gxName);//查询是否可读
            if(gxIsWriteable)
                enable = true;
            CIntFeaturePointer objIntPtr = featureControl->GetIntFeature(gxName);

            int64_t valueInt;
            int64_t valueMinInt;
            int64_t valueMaxInt;

            if(bIsReadable)
            {
                valueInt = objIntPtr->GetValue();
                valueMinInt = objIntPtr->GetMin();
                valueMaxInt = objIntPtr->GetMax();
                element.setAttribute(XML_KEY_MIN,QString::number(valueMinInt,10));
                element.setAttribute(XML_KEY_MAX,QString::number(valueMaxInt,10));
                element.setAttribute(XML_KEY_VALUE,QString::number(valueInt,10));
            }

            element.setAttribute(XML_KEY_ENABLE,enable);
            element.setAttribute(XML_KEY_TYPE,XML_TYPE_NUMBER);
            element.setAttribute(XML_KEY_DECIMALS,0);
            element.setAttribute(XML_KEY_UNIT,"");
            eType = IFT_IInteger;
            ret = true;
        }

        else if(gxType == GX_FEATURE_FLOAT)
        {
            bool gxIsWriteable = featureControl->IsWritable(gxName);//查询是否可写
            bool bIsReadable = featureControl->IsReadable(gxName);//查询是否可读

            if(gxIsWriteable)
                enable = true;

            CFloatFeaturePointer objFloatPtr = featureControl->GetFloatFeature(gxName);
            double valueFloat;
            double valueMinFloat;
            double valueMaxFloat;

            if(bIsReadable)
            {
                valueFloat = objFloatPtr->GetValue();
                valueMinFloat = objFloatPtr->GetMin();
                valueMaxFloat = objFloatPtr->GetMax();
                element.setAttribute(XML_KEY_MIN,valueMinFloat);
                element.setAttribute(XML_KEY_MAX,valueMaxFloat);
                element.setAttribute(XML_KEY_VALUE,valueFloat);
            }

            element.setAttribute(XML_KEY_ENABLE,enable);
            element.setAttribute(XML_KEY_TYPE,XML_TYPE_NUMBER);
            element.setAttribute(XML_KEY_DECIMALS,3);
            element.setAttribute(XML_KEY_UNIT,"");
            eType = IFT_IFloat;
            ret = true;
        }

下面是较为完整的函数,

bool MConfigureDahengG3UC::CreateElement(GxIAPICPP::gxstring gxName,MNodeMap *nodeMap,QDomElement &element,CGXFeatureControlPointer featureControl)
{
    bool ret = false;
#ifdef WIN32_DAHENG_GEV
    qint32 iVisibility = 0;
    QString name = QString::fromStdString(gxName.c_str());

    QString displayName= name;
    bool enable = false;
    bool hide = false;
    GX_XML_InterfaceType eType;
    GX_FEATURE_TYPE gxType = featureControl->GetFeatureType(gxName);

    Mc::VisibilityEnums visb = (Mc::VisibilityEnums)iVisibility;
    QString visbStr =  MEnumToString<Mc::VisibilityEnums>(visb);
    element.setAttribute(XML_KEY_NAME,name);
    element.setAttribute(XML_KEY_DISPLAYNAME,displayName);
    element.setAttribute(XML_KEY_STEP,1);
    element.setAttribute(XML_KEY_HIDE,hide);
    element.setAttribute(XML_KEY_VISIBILITY,visbStr);

    try
    {
        if(gxType==GX_FEATURE_INT)
        {
            bool gxIsWriteable = featureControl->IsWritable(gxName);
            bool bIsReadable = featureControl->IsReadable(gxName);//查询是否可读
            if(gxIsWriteable)
                enable = true;
            CIntFeaturePointer objIntPtr = featureControl->GetIntFeature(gxName);

            int64_t valueInt;
            int64_t valueMinInt;
            int64_t valueMaxInt;

            if(bIsReadable)
            {
                valueInt = objIntPtr->GetValue();
                valueMinInt = objIntPtr->GetMin();
                valueMaxInt = objIntPtr->GetMax();
                element.setAttribute(XML_KEY_MIN,QString::number(valueMinInt,10));
                element.setAttribute(XML_KEY_MAX,QString::number(valueMaxInt,10));
                element.setAttribute(XML_KEY_VALUE,QString::number(valueInt,10));
            }

            element.setAttribute(XML_KEY_ENABLE,enable);
            element.setAttribute(XML_KEY_TYPE,XML_TYPE_NUMBER);
            element.setAttribute(XML_KEY_DECIMALS,0);
            element.setAttribute(XML_KEY_UNIT,"");
            eType = IFT_IInteger;
            ret = true;
        }

        else if(gxType == GX_FEATURE_FLOAT)
        {
            bool gxIsWriteable = featureControl->IsWritable(gxName);//查询是否可写
            bool bIsReadable = featureControl->IsReadable(gxName);//查询是否可读

            if(gxIsWriteable)
                enable = true;

            CFloatFeaturePointer objFloatPtr = featureControl->GetFloatFeature(gxName);
            double valueFloat;
            double valueMinFloat;
            double valueMaxFloat;

            if(bIsReadable)
            {
                valueFloat = objFloatPtr->GetValue();
                valueMinFloat = objFloatPtr->GetMin();
                valueMaxFloat = objFloatPtr->GetMax();
                element.setAttribute(XML_KEY_MIN,valueMinFloat);
                element.setAttribute(XML_KEY_MAX,valueMaxFloat);
                element.setAttribute(XML_KEY_VALUE,valueFloat);
            }

            element.setAttribute(XML_KEY_ENABLE,enable);
            element.setAttribute(XML_KEY_TYPE,XML_TYPE_NUMBER);
            element.setAttribute(XML_KEY_DECIMALS,3);
            element.setAttribute(XML_KEY_UNIT,"");
            eType = IFT_IFloat;
            ret = true;
        }
        else if(gxType == GX_FEATURE_ENUM)
        {
            bool gxIsWriteable = featureControl->IsWritable(gxName);//查询是否可写
            bool bIsReadable = featureControl->IsReadable(gxName);//查询是否可读

            if(gxIsWriteable)
                enable = true;

            QString valueQEnum;
            GxIAPICPP::gxstring_vector valueList;

            if(bIsReadable)
            {
                CEnumFeaturePointer objEnumPtr = featureControl->GetEnumFeature(gxName);
                valueList = objEnumPtr->GetEnumEntryList();
                GxIAPICPP::gxstring  valueEnum = objEnumPtr->GetValue();
                valueQEnum = QString::fromStdString(valueEnum.c_str());
                QStringList list;

                for(size_t i=0;i<valueList.size();i++)
                {
                    GxIAPICPP::gxstring gxValue = valueList[i];
                    QString gxQValue = QString::fromStdString(gxValue.c_str());
                    list<<gxQValue;
                }

                element.setAttribute(XML_KEY_ENUMENTRYS,list.join(";"));
                element.setAttribute(XML_KEY_VALUE,valueQEnum);
            }

            element.setAttribute(XML_KEY_ENABLE,enable);
            element.setAttribute(XML_KEY_TYPE,XML_TYPE_COMBO);
            eType = IFT_IEnumeration;
            ret = true;
        }
        else if(gxType == GX_FEATURE_BOOL)
        {
            bool gxIsWriteable = featureControl->IsWritable(gxName);//查询是否可写
            bool bIsReadable = featureControl->IsReadable(gxName);//查询是否可读

            if(gxIsWriteable)
                enable = true;

            CBoolFeaturePointer objBoolPtr = featureControl->GetBoolFeature(gxName);
            bool valueBool;

            if(bIsReadable)
            {
                valueBool = objBoolPtr->GetValue();
                element.setAttribute(XML_KEY_VALUE,QVariant(valueBool).toString());
            }

            element.setAttribute(XML_KEY_ENABLE,enable);
            element.setAttribute(XML_KEY_TYPE,XML_TYPE_BOOLEAN);
            eType = IFT_IBoolean;
            ret = true;
        }
        else if(gxType == GX_FEATURE_STRING)
        {
            bool gxIsWriteable = featureControl->IsWritable(gxName);//查询是否可写
            bool bIsReadable = featureControl->IsReadable(gxName);//查询是否可读

            if(gxIsWriteable)
                enable = true;

            CStringFeaturePointer objStringPtr = featureControl->GetStringFeature(gxName);
            GxIAPICPP::gxstring valueStr;

            if(bIsReadable)
            {
                valueStr = objStringPtr->GetValue();//获取当前值
                element.setAttribute(XML_KEY_VALUE,QString::fromStdString(valueStr.c_str()));
            }

            element.setAttribute(XML_KEY_ENABLE,enable);
            element.setAttribute(XML_KEY_TYPE,XML_TYPE_STRING);
            eType = IFT_IString;
            ret = true;
        }
        else if(gxType == GX_FEATURE_COMMAND)
        {
            CCommandFeaturePointer objCommandPtr = featureControl->GetCommandFeature(gxName);
            bool gxIsWriteable = featureControl->IsWritable(gxName);

            if(gxIsWriteable)
                enable = true;

            element.setAttribute(XML_KEY_ENABLE,enable);
            element.setAttribute(XML_KEY_CHECKABLE,"1");
            element.setAttribute(XML_KEY_TYPE,XML_TYPE_COMMAND);
            element.setAttribute(XML_KEY_VALUE,"true");
            eType = IFT_ICommand;
            ret = true;
        }
        else if(gxType == GX_FEATURE_BUFFER)
        {
            CRegisterFeaturePointer objRegisterPtr = featureControl->GetRegisterFeature(gxName);
            bool gxIsWriteable = featureControl->IsWritable(gxName);

            if(gxIsWriteable)
                enable = true;

            element.setAttribute(XML_KEY_ENABLE,enable);
            element.setAttribute(XML_KEY_TYPE,"Register");
        }

    }
    catch(...)
    {
        qDebug()<< "-->Error CreateElement: "<<name;
        ret = false;
    }

    if(ret)
    {
        MNode *temp;
        nodeMap->CreateNode(&temp,Mc::NodeEnums(eType));

        if(temp)
        {
            temp->SetElement(element,false);
            nodeMap->Insert(name,temp);
        }
    }

#endif
    return ret;
}

被动采图

这里所谓的被动采图,其实就是软触发抓图,就是按下一个按钮,便执行一次抓图操作。这里就贴出一个比较重要的触发抓图函数。

  1. 首先,初始化一个固定的图像的大小,确保这个图像的大小与你要显示的图像的框的大小是一致的,不然,就容易出现,一个框出现三个图像的状况。不信你可以试试看。
if((img->width() !=m_iWidth) ||
        (img->height() !=m_iHeight) ||
        (img->format() !=format) )
{
    qDebug()<<"--> HiDahengG3V:CaptureImageEx reset image memory! ";
    *img = QImage(m_iWidth,m_iHeight,format);

    if(format == QImage::Format_Indexed8)
        img->setColorTable(m_vColorTabel);
}
  1. 接下来,根据相机获取单帧
CImageDataPointer objImageDataPtr;
if(!m_objStreamPtr.IsNull())
{
    objImageDataPtr = m_objStreamPtr->GetImage(500);//超时时间使用500ms,用户可以自行设定
}
  1. 然后对该单帧进行处理,得到一个处理好的帧,往回传,注意并把信息赋值给info。
if (objImageDataPtr->GetStatus() == GX_FRAME_STATUS_SUCCESS)
{
     //采图成功而且是完整帧,可以进行图像处理
     void *pbit = objImageDataPtr->GetBuffer();
     int size = qMin((int)objImageDataPtr->GetPayloadSize(),img->byteCount());//这个操作是为了防止复制操作会导致数据溢出
     memcpy(img->bits(),pbit,size);

     info->nWidth  = (qint32)objImageDataPtr->GetWidth();
     info->nHeight = (qint32)objImageDataPtr->GetHeight();
     info->nFramerLen = (qint32)objImageDataPtr->GetPayloadSize();
     //QMetaEnum metaEnum = QMetaEnum::fromType<GXIAPICPP_API::GX_PIXEL_FORMAT_ENTRY>();
     //info->cFormat = metaEnum.valueToKey(objImageDataPtr->GetPixelFormat();
     quint64 nformat = objImageDataPtr->GetPixelFormat();
     info->cFormat = GetPixelFormat(nformat);
     info->fFrameRate = m_fFrameRate;
     ret = RETURN_OK;
 }
  1. 下面是比较完整的函数
qint32 MDeviceDahengG3UC::CaptureImageEx(QImage *img, MFrameInfo *info)
{
    qint32 ret = RETURN_FAIL;
#ifdef WIN32_DAHENG_GEV

    if(m_bLoaded)
    {
        QImage::Format format = QImage::Format_Indexed8;

        if(m_cPixelFormat.compare("RGB888")==0)
            format = QImage::Format_RGB888;

        if((img->width() !=m_iWidth) ||
                (img->height() !=m_iHeight) ||
                (img->format() !=format) )
        {
            qDebug()<<"--> HiDahengG3V:CaptureImageEx reset image memory! ";
            *img = QImage(m_iWidth,m_iHeight,format);

            if(format == QImage::Format_Indexed8)
                img->setColorTable(m_vColorTabel);
        }

        //采单帧
        CImageDataPointer objImageDataPtr;

        if(!m_objStreamPtr.IsNull())
        {
            objImageDataPtr = m_objStreamPtr->GetImage(500);//超时时间使用500ms,用户可以自行设定
        }

        if (objImageDataPtr->GetStatus() == GX_FRAME_STATUS_SUCCESS)
        {
            //采图成功而且是完整帧,可以进行图像处理
            void *pbit = objImageDataPtr->GetBuffer();
            int size = qMin((int)objImageDataPtr->GetPayloadSize(),img->byteCount());//这个操作是为了防止复制操作会导致数据溢出
            memcpy(img->bits(),pbit,size);

            info->nWidth  = (qint32)objImageDataPtr->GetWidth();
            info->nHeight = (qint32)objImageDataPtr->GetHeight();
            info->nFramerLen = (qint32)objImageDataPtr->GetPayloadSize();
            //QMetaEnum metaEnum = QMetaEnum::fromType<GXIAPICPP_API::GX_PIXEL_FORMAT_ENTRY>();
            //info->cFormat = metaEnum.valueToKey(objImageDataPtr->GetPixelFormat();
            quint64 nformat = objImageDataPtr->GetPixelFormat();
            info->cFormat = GetPixelFormat(nformat);
            info->fFrameRate = m_fFrameRate;
            ret = RETURN_OK;
        }
    }
#endif
    return ret;
}

//下面的这个函数就放在对应.h文件的末尾就可以了。然后,在头文件的前面进行前置声明。
class CSampleCaptureEventHandler : public ICaptureEventHandler
{
public:
    void DoOnImageCaptured(CImageDataPointer& objImageDataPointer, void* pUserParam)
    {
        MDeviceDahengG3UC* pDev = static_cast<MDeviceDahengG3UC*>(pUserParam);
        pDev->triggerEvent(objImageDataPointer);
    }
};

总结

现在完成了几个插件之后,才觉得原来这个插件是最好写的,因为这个SDK给的接口信息是最完整的,能较好的让我们利用好这些接口去做一些事情,后面遇到的相机的都让我们感觉很麻烦,如果有空,我也会做些记录,如果有错,麻烦各位在评论区指出哈!!感谢!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

大恒相机实时采图 的相关文章

  • iOS UITableViewCell高度自适应

    UITableViewCell高度自适应 iOS8之后 我们只需要设置这两句代码之后 xff0c 即可放心的往cell的控件里面加上内容 xff0c cell会根据内部所有控件的高度动态的计算自己的高度从而显示出来 tableView es
  • 记一次vncServer的离线安装经历

    记一次vncServer的离线安装经历 背景 xff1a 需要在一台服务器上面装Oracle xff0c 但是服务器并不能接触到 xff0c 所以只能在客户端进行远程ssh操作 首先根据我以往装Oracle的经验 xff0c 先把安装包这些
  • debian 修改桌面背景

    64 桌面背景 push 图片到对应目录替换 xff1a adb push 图片 usr share desktop base active theme wallpaper contents images 64 当前语言查看 cat etc
  • 【计算机图形学基础教程】MFC基本绘图函数2

    MFC基本绘图函数 绘图工具类 CGdiObject类 xff1a GDI绘图工具的基类CBitmap类 xff1a 封装了GDI画刷 xff0c 可以选作设备上下文的当前画刷 xff0c 用于填充图形的内部CFont类 xff1a 封装了
  • thrift安装及示例

    1 简介 Apache Thrift软件框架 xff08 用于可扩展的跨语言服务开发 xff09 将软件堆栈与代码生成引擎结合在一起 xff0c 它有自己的跨机器的通信框架 xff0c 并提供一套库 它是一个代码生成器 xff0c 按照它的
  • you-get库二开,带UI界面的下载器

    you get库二开 带UI界面的下载器 span class token comment coding utf 8 span span class token comment Form implementation generated f
  • 工厂方法模式【Python篇】

    前言 在 设计模式 一书中工厂模式提到了 xff1a 工厂方法模式 xff08 Factory Method xff09 抽象工厂模式 xff08 Abstract Factory xff09 但是在实际过程中还有一种工厂模式经常被使用 x
  • docker安装gitlab 教程详解

    文章目录 前言一 环境处理二 docker部署gitlab三 调整gitlab配置1 配置克隆项目时所需2 root所需 参考 前言 环境 xff1a 1 xff1a Linux dnsserver moa kdzl cn 3 10 0 6
  • 问题解决:consider to specify kernel configuration cache directory through OPENCV_OCL4DNN_CONFIG_PATH par

    在使用Openpose代码运行的时候 xff0c 提示 xff1a consider to specify kernel configuration cache directory through OPENCV OCL4DNN CONFIG
  • zabbix监控平台搭建,及监控华为S5735S系列交换机和2288hv5服务器

    提要 无监控不运维 xff01 告别 救火员 的运维 二次搭建zabbix了 xff0c 这次打算以zabbix 集团基础硬件为主 43 prometheus k8s 43 微服务集群为主 43 grafana dashbroad展示 xf
  • Selenium 常用API大全(一篇就够)

    Selenium Crawl API xff08 一篇就够 xff09 万字长文整理不易 xff0c 希望对各位有所帮助 xff0c 欢迎大家一键三连 xff0c 点赞收藏加关注 同时也欢迎大家交流分享 xff0c 共同学习互相进步 xff
  • CV和NLP的区别

    本质 xff08 根 xff09 上没有区别 xff0c 都是信息信号处理 xff0c 都是高维信号的分解和组合 xff0c 但是信号的结构特征有区别 xff0c 所以需要不同的策略来挖掘数据信息 xff0c 即使用不同的分解和组合策略 x
  • 【Linux学习笔记】Linux环境搭建Maven私服

    Linux环境搭建Maven私服 一 概要说明二 搭建Nexus3 X xff08 3 18 xff09 2 1 下载Nexus2 2 解压Nexus2 3 启动Nexus2 3 1 创建一个nis用户来启动nexus2 3 2 修改nex
  • Win10喇叭图标出现红叉提示"未安装任何音频输出设备"

    如果你按网上搜的各种方法都试了还是没有声音 xff0c 那么就 1 关机 xff1b 2 拔掉所有的线 xff0c 包括电源线 xff1b 3 长按开机键 15s 重复三次 4 插上电源 xff0c 开机 xff08 此方法适用于我的笔记本
  • C语言提供的线程/进程间同步(锁)机制

    目录 一 C语言提供的线程间同步机制 1 互斥体 xff08 Mutex xff09 2 读写锁 xff08 read write locks xff09 3 条件变量 xff08 conditional variables xff09 4
  • vue 3.0 使用axios

    一 安装axios xff0c vue axios 使用yarn span class token operator span yarn add axios yarn add vue span class token operator sp
  • 深度学习CV(基础理论知识)

    Python 解释性语言 1 tuple元组 xff1a 定义一个只有一个元素的tuple xff0c 必须加逗号 2 幂 xff1b 整除 3 机器学习常用库 numpy xff08 科学计算 xff0c 数据分析 xff09 panda
  • sublime 写C++程序

    sublime 配置 下载 安装sublime安装编译器配置g 43 43 环境变量配置sublime写一个hello world 程序其它的编译build命令 sublime 配置 下载 安装sublime https www subli
  • mysql开启ssl以及如何创建证书

    MYSQL版本8 0 32 xff0c 默认是开启ssl的 xff0c 同时也是自带证书的在 var lib mysql 下 jdbc连接Mysql数据库需要使用SSL时 xff0c 可以按一下步骤进行设置 xff1a 前置条件 xff08
  • Python基础知识:基本语句

    1 if 语句 1 xff09 基本用法 xff1a if 要判断的条件 条件成立的时候 xff0c 要做的事情 else 条件不成立的时候 xff0c 要做的事情 if和else语句以及各自的缩进部分都是一个完整的代码块 示例 xff1a

随机推荐