大恒相机实时采图

    科技2022-09-05  199

    目录

    前言正文准备工作设备的初始化设备信息的获取主动采图相机参数配置创建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中得出的。

    首先,是相机设备的初始化 IGXFactory::GetInstance().Init();//这个是进行实例的初始化 GxIAPICPP::gxdeviceinfo_vector vectorDeviceInfo; IGXFactory::GetInstance().UpdateDeviceList(1000, vectorDeviceInfo); //通过这个就可以获得相关的设备信息vectorDeviceInfo 接下来,就是获得当前设备的所有信息,这里就列举一些信息的获得就好了。这里可以稍微注意一下,强制类型转换在这里的应用。 GxIAPICPP::gxstring SerialNumber; QString SerialNumber2; GX_DEVICE_CLASS_LIST gClass2 = vectorDeviceInfo[n].GetDeviceClass(); SerialNumber = vectorDeviceInfo[n].GetSN(); SerialNumber2 = static_cast<QString>(SerialNumber); 接下来,根据设备序列号打开设备并获得实例 m_objDevicePtr = IGXFactory::GetInstance().OpenDeviceBySN(strSN,GX_ACCESS_EXCLUSIVE); 打开流对象 m_objStreamPtr = m_objDevicePtr->OpenStream(0); 下面这个就是比较完整的函数了。 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获取对象的相机信息,并且是相对上面那个函数会较全。

    首先也是要进行初始化,并获得设备信息对象。 IGXFactory::GetInstance().Init(); GxIAPICPP::gxdeviceinfo_vector vectorDeviceInfo; IGXFactory::GetInstance().UpdateDeviceList(1000, vectorDeviceInfo); 然后就是获取设备信息的那部分了。注意一些强制类型转换。下面这个就是比较完整的函数了。 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; }

    主动采图

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

    首先,开启流通道采集 if(!m_objStreamPtr.IsNull()) { qDebug()<<"MDeviceDahengG3UC::AcquisitionStart m_objStreamPtr"; //objStreamPtr->SetAcqusitionBufferNumber(10);//必须在调用StartGrab开启流通道的采集之前,设置采集buffer个数,否则设置无效。 m_objStreamPtr->StartGrab(); } 给设备发送开始开采命令 m_objFeatureControlPtr = m_objDevicePtr->GetRemoteFeatureControl(); 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_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树

    首先判断好一些比较重要的指针传进来别是零了,所以,这里就要完成好检测的那个功能。 if((Q_NULLPTR == m_pNodeMap)) if(m_pDevice->m_objDevicePtr.IsNull()) 通过相机的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 创建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); } } 下面这个函数是比较完整的函数 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文件中

    首先,对传进来的数据类型进行类型转换,这个转换还是蛮难的,至少我是花了挺多的时间研究这个东西。接下来就是获得节点的类型。 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; }

    被动采图

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

    首先,初始化一个固定的图像的大小,确保这个图像的大小与你要显示的图像的框的大小是一致的,不然,就容易出现,一个框出现三个图像的状况。不信你可以试试看。 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,用户可以自行设定 } 然后对该单帧进行处理,得到一个处理好的帧,往回传,注意并把信息赋值给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; } 下面是比较完整的函数 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给的接口信息是最完整的,能较好的让我们利用好这些接口去做一些事情,后面遇到的相机的都让我们感觉很麻烦,如果有空,我也会做些记录,如果有错,麻烦各位在评论区指出哈!!感谢!

    Processed: 0.009, SQL: 10