- 如何在LabView中使用MVDAlgotihrmSDK进行视觉开发
- LabVIEW开发者请看过来,教你怎么在LabVIEW中 使用VM 4.2 应用
- 悉灵杯”课题研究-LabVIEW集成及示例代码开发
- 工业相机labview例程显示方案
- LabVIEW基于算法平台C#版本SDK进行二次开发
Labview简介:
LabVIEW(Laboratory Virtual instrument Engineering Workbench)是一种图形化的编程语言的开发环境,它广泛地被工业界、学术界和研究实验室所接受,视为一个标准的数据采集和仪器控制软件。LabVIEW [3] 集成了与满足 GPIB、VXI、RS-232和 RS-485 协议的硬件及数据采集卡通讯的全部功能。它还内置了便于应用TCP/IP、ActiveX等软件标准的库函数。这是一个功能强大且灵活的软件。利用它可以方便地建立自己的虚拟仪器,其图形化的界面使得编程及使用过程都生动有趣。
图形化的程序语言,又称为 “G” 语言。使用这种语言编程时,基本上不写程序代码,取而代之的是流程图或框图。它尽可能利用了技术人员、科学家、工程师所熟悉的术语、图标和概念,因此,LabVIEW是一个面向最终用户的工具。它可以增强你构建自己的科学和工程系统的能力,提供了实现仪器编程和数据采集系统的便捷途径。使用它进行原理研究、设计、测试并实现仪器系统时,可以大大提高工作效率。。
Mv3d_Rgbd_Sdk简介:
RGB-D立体相机SDK是用于RGB-D立体相机的一个独立组件,支持图像采集、配置参数、获取设备信息等功能。
运行环境:
硬件配置: | CPU:Intel Atom(TM) E3845及以上 |
内存:4G及以上 | |
操作系统: | Windows7/10 32/64位版本 |
RGB-D相机SDK接口调用流程图
运行环境:
Labview 2015 32位
VS2015 debug 32位
SDK_Mv3dRgbd_V1.0.0_Win_220621_836278
在labview中使用共享库调用C++动态链接库时,部分函数的结构体参数中含有联合体(union),转换程序无法识别,需要编写扩展接口将结构体和函数重新封装,以便labview识别。
结构体MV3D_RGBD_DEVICE_INFO中成员变量SpecialInfo表示网口设备信息或USB设备信息,两个变量共享一段内存,将其拆分为MV3D_RGBD_GigEDEVICE_INFO和MV3D_RGBD_U3DEVICE_INFO两个结构体。
typedef struct _MV3D_RGBD_U3DEVICE_INFO_
{
char chManufacturerName[32]; // 设备厂商
char chModelName[32]; // 设备型号
char chDeviceVersion[32]; // 设备版本
char chManufacturerSpecificInfo[48]; // 设备厂商特殊信息
char chSerialNumber[16]; // 设备序列号
char chUserDefinedName[16]; // 设备用户自定义名称
int32_t enDeviceType; // 设备类型:网口、USB
uint32_t nVendorId; // 供应商ID号
uint32_t nProductId; // 产品ID号
int32_t enUsbProtocol; // 支持的USB协议
char chDeviceGUID[64]; // 设备GUID号
uint8_t nReserved[16]; // 保留字节
} MV3D_RGBD_U3DEVICE_INFO;
typedef struct _MV3D_RGBD_GigEDEVICE_INFO_
{
char chManufacturerName[32]; // 设备厂商
char chModelName[32]; // 设备型号
char chDeviceVersion[32]; // 设备版本
char chManufacturerSpecificInfo[48]; // 设备厂商特殊信息
char chSerialNumber[16]; // 设备序列号
char chUserDefinedName[16]; // 设备用户自定义名称
int32_t enDeviceType; // 设备类型:网口、USB
unsigned char chMacAddress[8]; // Mac地址
int32_t enIPCfgMode; // 当前IP类型
char chCurrentIp[16]; // 设备当前IP
char chCurrentSubNetMask[16]; // 设备当前子网掩码
char chDefultGateWay[16]; // 设备默认网关
char chNetExport[16]; // 网口IP地址
uint8_t nReserved[16]; // 保留字节
} MV3D_RGBD_GigEDEVICE_INFO;
typedef struct _MV3D_RGBD_U3DEVICE_INFO_
{
char chManufacturerName[32]; // 设备厂商
char chModelName[32]; // 设备型号
char chDeviceVersion[32]; // 设备版本
char chManufacturerSpecificInfo[48]; // 设备厂商特殊信息
char chSerialNumber[16]; // 设备序列号
char chUserDefinedName[16]; // 设备用户自定义名称
int32_t enDeviceType; // 设备类型:网口、USB
uint32_t nVendorId; // 供应商ID号
uint32_t nProductId; // 产品ID号
int32_t enUsbProtocol; // 支持的USB协议
char chDeviceGUID[64]; // 设备GUID号
uint8_t nReserved[16]; // 保留字节
} MV3D_RGBD_U3DEVICE_INFO;
相关的函数:
MV3D_RGBD_GetDeviceList
MV3D_RGBD_GetGigEDeviceList
MV3D_RGBD_GetU3DeviceList
MV3D_RGBD_OpenDevice
MV3D_RGBD_OpenGigEDevice
MV3D_RGBD_OpenU3Device
MV3D_RGBD_GetDeviceInfo
MV3D_RGBD_GetGigEDeviceInfo
MV3D_RGBD_GetU3DeviceInfo
在悉灵相机中,每一帧会读出四张图片,一张YUV422格式的图片,一张16位深度图,两张8位灰度图,便于显示,编写MV3D_RGBD_YUV422ToRGB实现YUV422至RGB的转换。
转换公式:
函数体:
MV3D_RGBD_STATUS __stdcall MV3D_RGBD_YUV422ToRGB(MV3D_RGBD_IMAGE_DATA *pYuvImgge, MV3D_RGBD_IMAGE_DATA* pRgbImage) {
//2.整数形式(减少计算量)未量化 R,G,B~[0, 255] U,V~[0, 255]
//R = Y + ((360 * (V - 128)) >> 8);
//G = Y - (((88 * (U - 128) + 184 * (V - 128))) >> 8);
//B = Y + ((455 * (U - 128)) >> 8);
pRgbImage->enImageType = Mv3dRgbdImageType::ImageType_RGB8_Planar;
pRgbImage->nDataLen = pYuvImgge->nHeight*pYuvImgge->nWidth * 3;
pRgbImage->nFrameNum = pYuvImgge->nFrameNum;
pRgbImage->nHeight = pYuvImgge->nHeight;
pRgbImage->nTimeStamp = pYuvImgge->nTimeStamp;
pRgbImage->nWidth = pYuvImgge->nWidth;
static uint8_t buffer[1280 * 720 * 9];
for (size_t i = 0; i < pRgbImage->nWidth*pRgbImage->nHeight; i += 2)
{
uint16_t Y1 = (uint16_t)pYuvImgge->pData[i * 2];
uint16_t U1 = (uint16_t)(pYuvImgge->pData[i * 2 + 1]);
uint16_t Y2 = (uint16_t)pYuvImgge->pData[i * 2 + 2];
uint16_t V2 = (uint16_t)(pYuvImgge->pData[i * 2 + 3]);
/***********************RGB值计算*************************/
buffer[i * 3 + 0] = (uint8_t)(Y1 + ((360 * (V2 - 128)) >> 8)); //R通道
buffer[i * 3 + 1] = (uint8_t)(Y1 - (((88 * (U1 - 128) + 184 * (V2 - 128))) >> 8)); //G通道
buffer[i * 3 + 2] = (uint8_t)(Y1 + ((455 * (U1 - 128)) >> 8)); //B通道
buffer[i * 3 + 3] = (uint8_t)(Y2 + ((360 * (V2 - 128)) >> 8)); //R通道
buffer[i * 3 + 4] = (uint8_t)(Y2 - (((88 * (U1 - 128) + 184 * (V2 - 128))) >> 8)); //G通道
buffer[i * 3 + 5] = (uint8_t)(Y2 + ((455 * (U1 - 128)) >> 8)); //B通道
}
pRgbImage->pData = buffer;
return 0;
}
基于SDK生成扩展VI
(1)打开labview,找到工具->导入->共享库
(2)在弹出的窗口中选择为共享库创建VI,然后点击下一步
(3)在弹出的面板中选择共享库文件路径
选择文件后点击确定
(4)继续选择待导出函数的头文件
(5)选择文件后点击确定
(5)点击下一步
(6)识别函数失败,原因为“未在指定头文件中或某个引用的头文件中找到以下头文件:stdint.h“
(7)返回上一步,继续添加附加的标准库文件,如stdint.h string.h等
(8)函数正确识别,点击下一步
(9)设置导出路径,并点击下一步
(10)点击下一步
(11)点击下一步
(12)点击下一步
(13)等待导出结束
(14)勾选打开报告,并点击完成
(15)在导出过程中,有三个函数未正确识别,原因为函数的参数中含有嵌套结构体或联合体,labview无法正确识别,将三个函数重新封装后打包生成动态链接库
(16)导入第二节编写的扩展库Mv3dSdkEx,步骤与导入Mv3dSdk相同。选择好dll路径和头文件路径后点击下一步
(17)添加stdint.h等头文件,防止导入出错。点击下一步
(18)点击下一步
(19)选择导入路径后点击下一步
(20)点击下一步
(21)点击下一步
(22)点击下一步
(23)已正确导入,默认不勾选查看报告
(24)正确导入后,可在函数选板的用户库中选择使用
(25)至此,导入完成。
4、调整导入的VI
成功导入dll后,部分VI输入输出不正确,需要重新设置输入输出。如MV3D_RGBD_GetGigEDeviceList等,将函数中的结构体参数按字节生成簇,并且在连接多个设备时,只能识别一个,需要根据输出指针和设备个数重新解析。
重新设置输入输出后MV3D_RGBD_GetGigEDeviceList对应的VI如下。
同理,其他相似或错误的VI也需要按照此流程进行处理
根据第一章的开发流程开发示例程序,该示例程序可实现RGB、深度图、点云的采集与显示。下面介绍各部分功能实现与注意事项
(1)初始化
(2)获取相机列表,并打开相机,开始图像采集
(3)初始化场景和光源,用于显示点云
(4)采集图像,输出包含图像数量和每一张图像信息,使用悉灵相机将会得到一张深度图、一张YUV422图片、两张辅助的灰度图
(5)解析深度图并显示
其中使用指针解析数据时,使用了labview自带的MoveBlock函数,将指定数据解析为数组,MoveBlock配置如下:
(6)将深度图转换为点云进行显示,转换后的pData为点云数据的首地址,其中每个点由XYZ三个浮点数构成,每个点的信息占用12个字节,通过解析pData得到float数组,数组内元素的排列方式为“x1,y1,z1,x2,y2,z2...”,将数组拆分即可得到XYZ分量,用于显示。
(7)YUV422转RGB后显示
(8)将RGB渲染到每个有效点上进行显示,由于深度图转换到点云后存在无效点,需要将无效点进行剔除。
(9)停止采集并关闭相机
(10)释放
完整程序框图
深度图和RGB图
点云显示