当前位置: 首页 > news >正文

相机通用类之LMI激光三角相机(3D),软触发硬触发(飞拍),并输出halcon格式对象

//在此之前可以先浏览我编写的通用上位机类,更方便理解
https://blog.csdn.net/m0_51559565/article/details/134403745

最近完成一个关于LMI激光三角(3D相机)采图的demo,记录并说明用法。
先上代码。

using Lmi3d.GoSdk;
using Lmi3d.Zen;
using System;
using System.Collections.Generic;
using HalconDotNet;
using Lmi3d.GoSdk.Messages;
using System.Runtime.InteropServices;
using System.IO;
using WeldingInspection.MyCamer;namespace WeldingInspection
{internal class LMISDK: MyBaseCamera{GoSensor MyLMICamer = null;//创建LMI相机传感器对象GoSystem goSystem = new GoSystem();//创建LMI系统信息List<string> LMICamerName = new List<string>();//获取相机序列号HObject Himage3D=new HObject();public LMISDK(){//KApiLib.Construct();激活API库//GoSdkLib.Construct();}/// <summary>/// 查找相机,并输出序列号/// </summary>/// <returns></returns>public override List<string> FindCamer(){long size = goSystem.SensorCount;for (int i = 0; i < size; i++){GoAddressInfo addressInfo = goSystem.GetSensor(i).Address();LMICamerName.Add(goSystem.GetSensor(i).Id.ToString());}foreach (var item in LMICamerName){Console.WriteLine("当前连接相机有:" + item);}return LMICamerName;}/// <summary>/// 根据序列号开启相机/// </summary>/// <param name="CamerName"></param>/// <returns></returns>public override bool OpenCamer(string CamerName){uint LMIName;if (!uint.TryParse(CamerName,out LMIName)){return false;}if (LMICamerName.Count == 0 && MyLMICamer == null){return false;}//关闭设备CloseCamer();//通过ID找到Gocator SensorMyLMICamer = new GoSystem().FindSensorById(LMIName);MyLMICamer.Connect();//连接成功if (MyLMICamer.IsConnected()){MyLMICamer.EnableData(true);//开启允许相机采集//MyLMICamer.SetDataHandler(onData);//注册回调函数,生成未标定的16位深度图//MyLMICamer.SetDataHandler(onData_GenTL);//注册回调函数获得GenTL图MyLMICamer.SetDataHandler(onData_Calib);//注册回调函数,生成具有标定数据的,16位深度图}else{Console.WriteLine("开启LMI相机失败");MyLMICamer = null;return false;}return true;}/// <summary>/// 关闭相机/// </summary>/// <returns></returns>public override bool CloseCamer(){try{if (MyLMICamer != null){//停止采集MyLMICamer.Stop();return true;}return false;}catch (Exception ex){Console.WriteLine("相机停止采集异常", ex);return false;}}/// <summary>/// 相机重连/// </summary>/// <param name="CamerName"></param>/// <returns></returns>public override bool ReconnectCamer(string CamerName){uint LMIName;if (!uint.TryParse(CamerName, out LMIName)){return false;}if (LMICamerName.Count == 0 && MyLMICamer == null){return false;}//关闭设备CloseCamer();//通过ID找到Gocator SensorMyLMICamer = new GoSystem().FindSensorById(LMIName);MyLMICamer.Connect();//连接成功if (MyLMICamer.IsConnected()){MyLMICamer.EnableData(true);//开启允许相机采集//MyLMICamer.SetDataHandler(onData);//注册回调函数,生成未标定的16位深度图//MyLMICamer.SetDataHandler(onData_GenTL);//注册回调函数获得GenTL图,可以用于表面缺陷检测MyLMICamer.SetDataHandler(onData_Calib);//注册回调函数,生成具有标定数据的,16位深度图}else{Console.WriteLine("开启LMI相机失败");MyLMICamer = null;return false;}return true;}/// <summary>/// 软触发一次/// </summary>/// <returns></returns>public override bool OneGrap(){try{if (MyLMICamer.State == GoState.Running){MyLMICamer.Stop();MyLMICamer.Start();}else{MyLMICamer.Start();}return true;}catch (Exception){return false;}}/// <summary>/// 设置硬触发/// </summary>/// <returns></returns>public override bool EncoderGrap(){MyLMICamer.Setup.TriggerSource = GoTrigger.Encoder;MyLMICamer.Flush();return true;}/// <summary>/// 将配置文件上传到相机中/// </summary>/// <param name="Address">文件所在绝对路径</param>/// <param name="FileName">文件名称</param>/// <returns></returns>public bool UpLoad_Camer_file(string Address,string FileName){try{MyLMICamer.Stop();MyLMICamer.UploadFile(Address, FileName);MyLMICamer.Flush();return true;}catch (Exception){return false;}}/// <summary>/// 输出高度信息以毫米(mm)为单位,带标定结果/// </summary>/// <param name="data"></param>public void onData_Calib(KObject data){//x图HObject GenTL16BitRGBRedImage = new HObject();//y图HObject GenTL16BitRGBGreenImage = new HObject();//z图HObject GenTL16BitRGBBlueImage = new HObject();try{GoDataSet dataSet = (GoDataSet)data;for (uint i = 0; i < dataSet.Count; i++){GoDataMsg dataObj = (GoDataMsg)dataSet.Get(i);switch (dataObj.MessageType){case GoDataMessageType.UniformSurface:{GoUniformSurfaceMsg surfaceMsg = (GoUniformSurfaceMsg)dataObj;//获取缓存的宽高surfaceBufferWidth = surfaceMsg.Width;surfaceBufferLength = surfaceMsg.Length;double xResolution = (double)surfaceMsg.XResolution / 1000000;double yResolution = (double)surfaceMsg.YResolution / 1000000;double zResolution = (double)surfaceMsg.ZResolution / 1000000;Console.WriteLine("3d标定数据:X方向:"+xResolution+"Y方向:"+yResolution);//double xOffset = (double)surfaceMsg.XOffset / 1000;//double yOffset = (double)surfaceMsg.YOffset / 1000;double zOffset = (double)surfaceMsg.ZOffset / 1000;IntPtr bufferPointeri = surfaceMsg.Data;//short[] x = new short[surfaceBufferLength * surfaceBufferWidth];//short[] y = new short[surfaceBufferLength * surfaceBufferWidth];short[] z = new short[surfaceBufferLength * surfaceBufferWidth];//声明存放surface的Buffer//short[] surfaceBuffer = new short[surfaceBufferWidth * surfaceBufferLength];//将传感器给的值拷贝到我们声明的数组中Marshal.Copy(bufferPointeri, z, 0, Convert.ToInt32(surfaceBufferWidth * surfaceBufferLength));//for (short row = 0; row < surfaceBufferLength; row++)//{//    for (short col = 0; col < surfaceMsg.Width; col++)//    {//        x[row * surfaceMsg.Width + col] = col;//        y[row * surfaceMsg.Width + col] = row;//    }//}//将传感器数据存储至生命的内存空间中// Marshal.Copy(bufferPointeri, surfaceBuffer, 0, surfaceBuffer.Length);unsafe{fixed (short* p = z)HOperatorSet.GenImage1(out GenTL16BitRGBBlueImage, "int2", surfaceBufferWidth, surfaceBufferLength, new IntPtr(p));//fixed (short* p = x)//    HOperatorSet.GenImage1(out GenTL16BitRGBRedImage, "int2", surfaceBufferWidth, surfaceBufferLength, new IntPtr(p));//fixed (short* p = y)//    HOperatorSet.GenImage1(out GenTL16BitRGBGreenImage, "int2", surfaceBufferWidth, surfaceBufferLength, new IntPtr(p));}//以下注释部分可生成三通道图像//HOperatorSet.ConvertImageType(GenTL16BitRGBRedImage, out GenTL16BitRGBRedImage, "real");//HOperatorSet.ScaleImage(GenTL16BitRGBRedImage, out GenTL16BitRGBRedImage, xResolution, xOffset);//HOperatorSet.WriteImage(GenTL16BitRGBRedImage, new HTuple("tiff"), new HTuple(0), "E:\\UpperComputer\\LMI\\LMIHalconImage\\x.tiff");//HOperatorSet.ConvertImageType(GenTL16BitRGBGreenImage, out GenTL16BitRGBGreenImage, "real");//HOperatorSet.ScaleImage(GenTL16BitRGBGreenImage, out GenTL16BitRGBGreenImage, yResolution, yOffset);//HOperatorSet.ScaleImage(GenTL16BitRGBGreenImage, out GenTL16BitRGBGreenImage, -1, 0);//HOperatorSet.WriteImage(GenTL16BitRGBGreenImage, new HTuple("tiff"), new HTuple(0), "E:\\UpperComputer\\LMI\\LMIHalconImage\\y.tiff");HOperatorSet.ConvertImageType(GenTL16BitRGBBlueImage, out GenTL16BitRGBBlueImage, "real");HOperatorSet.ScaleImage(GenTL16BitRGBBlueImage, out Himage3D, zResolution, zOffset);//映射标定数据//HOperatorSet.WriteImage(Himage3D, new HTuple("tiff"), new HTuple(0), "E:\\UpperComputer\\LMI\\LMIHalconImage\\z.tiff");//HOperatorSet.Compose3(GenTL16BitRGBRedImage, GenTL16BitRGBGreenImage, GenTL16BitRGBBlueImage,out HObject Halcon3DImage);//HOperatorSet.WriteImage(Halcon3DImage, new HTuple("tiff"), new HTuple(0), "E:\\UpperComputer\\LMI\\LMIHalconImage\\3d.tiff");GetImage(Himage3D);}break;}}//生成3d模型//HOperatorSet.XyzToObjectModel3d(GenTL16BitRGBRedImage, GenTL16BitRGBGreenImage, GenTL16BitRGBBlueImage, out hv_ObjectModel3D);//HOperatorSet.WriteObjectModel3d(hv_ObjectModel3D, "ply", "E:\\UpperComputer\\LMI\\LMIHalconImage\\xyz.ply", new HTuple(), new HTuple());GenTL16BitRGBRedImage.Dispose();GenTL16BitRGBRedImage = null;GenTL16BitRGBGreenImage.Dispose();GenTL16BitRGBGreenImage = null;GenTL16BitRGBBlueImage.Dispose();GenTL16BitRGBBlueImage = null;MyLMICamer.Stop();}catch{GenTL16BitRGBRedImage.Dispose();GenTL16BitRGBRedImage = null;GenTL16BitRGBGreenImage.Dispose();GenTL16BitRGBGreenImage = null;GenTL16BitRGBBlueImage.Dispose();GenTL16BitRGBBlueImage = null;MyLMICamer.Stop();}Console.WriteLine(Environment.NewLine);}/// <summary>/// 设置曝光时间/// </summary>/// <param name="ExposureTime"></param>/// <returns></returns>public override bool SetExposureTime(int ExposureTime){try{if (MyLMICamer.State == GoState.Running){MyLMICamer.Stop();}MyLMICamer.Setup.SetExposure(MyLMICamer.Role, ExposureTime);MyLMICamer.Flush();return true;}catch (Exception){return false;}}#region // 生成不带标定数据的高度信息图/// <summary>/// 输出高度信息以纳米为单位。需要乘以分辨率/// </summary>/// <param name="data"></param>public void onData(KObject data){//高度图HObject GenTL16BitRGBRedImage = new HObject();//亮度图HObject GenTL16BitRGBGreenImage = new HObject();try{if (!Directory.Exists("E:\\UpperComputer")){Directory.CreateDirectory("E:\\UpperComputer");}GoDataSet dataSet = (GoDataSet)data;for (uint i = 0; i < dataSet.Count; i++){GoDataMsg dataObj = (GoDataMsg)dataSet.Get(i);Console.WriteLine(dataObj.MessageType);switch (dataObj.MessageType){case GoDataMessageType.UniformSurface:{GoUniformSurfaceMsg surfaceMsg = (GoUniformSurfaceMsg)dataObj;IntPtr bufferPointeri = surfaceMsg.Data;//声明存放surface的Buffershort[] surfaceBuffer = new short[surfaceMsg.Width * surfaceMsg.Length];//将传感器数据存储至生命的内存空间中Marshal.Copy(bufferPointeri, surfaceBuffer, 0, surfaceBuffer.Length);unsafe{fixed (short* p = surfaceBuffer)HOperatorSet.GenImage1(out GenTL16BitRGBRedImage, "int2", surfaceMsg.Width, surfaceMsg.Length, new IntPtr(p));}HOperatorSet.WriteImage(GenTL16BitRGBRedImage, "tiff", 0, "E:\\UpperComputer\\" + "height" + DateTime.Now.ToString("yyyymmdd-hhmmssfff") + ".tif");}break;case GoDataMessageType.SurfaceIntensity:{GoSurfaceIntensityMsg surfaceIntensityMsg = (GoSurfaceIntensityMsg)dataObj;IntPtr bufferPointeri = surfaceIntensityMsg.Data;//声明存放surface的Bufferbyte[] surfaceBuffer = new byte[surfaceIntensityMsg.Width * surfaceIntensityMsg.Length];//将传感器数据存储至声明的内存空间中Marshal.Copy(bufferPointeri, surfaceBuffer, 0, surfaceBuffer.Length);GenTL16BitRGBGreenImage.Dispose();unsafe{fixed (byte* p = surfaceBuffer){HOperatorSet.GenImage1(out GenTL16BitRGBGreenImage, "byte", surfaceIntensityMsg.Width, surfaceIntensityMsg.Length, new IntPtr(p));}}HOperatorSet.WriteImage(GenTL16BitRGBGreenImage, "tiff", 0, "E:\\UpperComputer\\" + "Intensity" + DateTime.Now.ToString("yyyymmdd-hhmmssfff") + ".tif");}break;}}//GenTL16BitRGBRedImage = null;//GenTL16BitRGBGreenImage = null;GenTL16BitRGBGreenImage.Dispose();GenTL16BitRGBRedImage.Dispose();MyLMICamer.Stop();}catch{//MyLMICamer.Stop();GenTL16BitRGBRedImage.Dispose();//GenTL16BitRGBRedImage = null;GenTL16BitRGBGreenImage.Dispose();//GenTL16BitRGBGreenImage = null;}Console.WriteLine(Environment.NewLine);}#endregion#region // 生成GenTL彩色图格式,并转化为halcon模型/// <summary>/// 输入genTL格式高度图,转化为3d模型。genTL为彩色高度图像/// </summary>/// <param name="ho_Gentl"></param>/// <param name="Save3D"></param>/// <param name="SaveAddress"></param>/// <returns></returns>public HTuple Himage_To_3D(HObject ho_Gentl, bool Save3D, string SaveAddress){HTuple hv_ObjectModel3D = new HTuple();hv_ObjectModel3D.Dispose();Gentl_to_object_model_3d(ho_Gentl, out hv_ObjectModel3D, Save3D, SaveAddress);return hv_ObjectModel3D;}static long frameCount = 0, timeStamp = 0, encoderValue = 0, encoderIndex = 0, digitalStates = 0;static long surfaceBufferWidth = 0, surfaceBufferLength = 0;static long surfaceXResolution = 0, surfaceYResolution = 0, surfaceZResolution = 0;static long surfaceXOffset = 0, surfaceYOffset = 0, surfaceZOffset = 0;static long intensityEnable = 0;/// <summary>/// 回调函数,输出GenTL格式彩色深度图/// </summary>/// <param name="data"></param>public void onData_GenTL(KObject data){//高度图HObject GenTL16BitRGBRedImage = new HObject();//亮度图HObject GenTL16BitRGBGreenImage = new HObject();//Stamp图HObject GenTL16BitRGBBlueImage = new HObject();//GenTLImageHObject GenTLImage = new HObject();try{GoDataSet dataSet = (GoDataSet)data;for (uint i = 0; i < dataSet.Count; i++){GoDataMsg dataObj = (GoDataMsg)dataSet.Get(i);switch (dataObj.MessageType){case GoDataMessageType.Stamp:{GoStampMsg stampMsg = (GoStampMsg)dataObj;for (int j = 0; j < stampMsg.Count; j++){//获取缓存的宽高GoStamp goStamp = stampMsg.Get(j);frameCount = (long)goStamp.FrameIndex;timeStamp = (long)goStamp.Timestamp;encoderValue = goStamp.Encoder;encoderIndex = goStamp.EncoderAtZ;digitalStates = (long)goStamp.Status;}}break;case GoDataMessageType.UniformSurface:{GoUniformSurfaceMsg surfaceMsg = (GoUniformSurfaceMsg)dataObj;//获取缓存的宽高surfaceBufferWidth = surfaceMsg.Width;surfaceBufferLength = surfaceMsg.Length;//获取缓存的分辨率 nmsurfaceXResolution = surfaceMsg.XResolution;surfaceYResolution = surfaceMsg.YResolution;surfaceZResolution = surfaceMsg.ZResolution;#region Offset (um) 转换为 NM *1000surfaceXOffset = surfaceMsg.XOffset * 1000;surfaceYOffset = surfaceMsg.YOffset * 1000;//注意由于halcon体系中用GenTL采集图像默认使用uint2来存储高度数据//而Gocator体系中采集的图像默认使用int2来存储高度数据//所以从Gocator SDK读出的zOffset 适用于Gocator SDK采集的“int2”类型的数据//而我们由于在算法开发过程中使用halcon GenTL采集数据,并且配置了众多处理参数,从而导出的算法代码中的参数//通常都是基于uint2类型数据的,这里我们将Gocator SDK读出的 zOffset做一个转换,使其适配于halcon的uint2体系surfaceZOffset = (long)((surfaceMsg.ZOffset +(short.MinValue * (surfaceMsg.ZResolution * 1e-3))) * 1000);#endregionIntPtr bufferPointeri = surfaceMsg.Data;//声明存放surface的Buffershort[] surfaceBuffer = new short[surfaceBufferWidth * surfaceBufferLength];//将传感器数据存储至生命的内存空间中Marshal.Copy(bufferPointeri, surfaceBuffer, 0, surfaceBuffer.Length);unsafe{fixed (short* p = surfaceBuffer)HOperatorSet.GenImage1(out GenTL16BitRGBRedImage, "int2", surfaceBufferWidth, surfaceBufferLength, new IntPtr(p));}HOperatorSet.ConvertImageType(GenTL16BitRGBRedImage, out GenTL16BitRGBRedImage, "real");HOperatorSet.ScaleImage(GenTL16BitRGBRedImage, out GenTL16BitRGBRedImage, 1, 32768);HOperatorSet.ConvertImageType(GenTL16BitRGBRedImage, out GenTL16BitRGBRedImage, "uint2");}break;case GoDataMessageType.SurfaceIntensity:{GoSurfaceIntensityMsg surfaceIntensityMsg = (GoSurfaceIntensityMsg)dataObj;IntPtr bufferPointeri = surfaceIntensityMsg.Data;//声明存放surface的Bufferbyte[] surfaceBuffer = new byte[surfaceBufferWidth * surfaceBufferLength];//将传感器数据存储至声明的内存空间中Marshal.Copy(bufferPointeri, surfaceBuffer, 0, surfaceBuffer.Length);intensityEnable = 1;GenTL16BitRGBGreenImage.Dispose();unsafe{fixed (byte* p = surfaceBuffer){HOperatorSet.GenImage1(out GenTL16BitRGBGreenImage, "byte", surfaceBufferWidth, surfaceBufferLength, new IntPtr(p));}}#region 将byte图像转换为uint2图像//如果严格按照GenTL协议组织数据的话应该将GenTL16BitRGBGreenImage(Intensity)转换成Uint2类型,转换代码如下//但是由于在运行时软件中显示亮度图时,很多显示器无法很好的支持16bit亮度图的显示,会出现显示细节丢失的情况,从而显示效果很差,//索性这里保留GenTL16BitRGBGreenImage的Byte类型//注意下面的代码为halcon中的流程在VS中实现需要一些中间HObje来保存每一步处理生成的图像,建议在halcon中编写写明的过程,然后导出为C#代码,参考导出代码编写//HOperatorSet.ConvertImageType(GenTL16BitRGBGreenImage, out GenTL16BitRGBGreenImage, "uint2");//HOperatorSet.ScaleImage(GenTL16BitRGBGreenImage, out GenTL16BitRGBGreenImage, 256, 0);#endregion}break;}}//生成BlueImageGenTL16BitRGBBlueImage.Dispose();GenGenTL16BitRGBBlueImage(frameCount, timeStamp, encoderValue, encoderIndex, digitalStates,surfaceBufferWidth, surfaceBufferLength, surfaceXOffset, surfaceXResolution, surfaceYOffset, surfaceYResolution,surfaceZOffset, surfaceZResolution, intensityEnable, out GenTL16BitRGBBlueImage);//将 高度图 亮度图 Stamp图组合成GenTL图像HOperatorSet.Compose3(GenTL16BitRGBRedImage, GenTL16BitRGBGreenImage, GenTL16BitRGBBlueImage, out GenTLImage);HOperatorSet.WriteImage(GenTLImage, new HTuple("tiff"), new HTuple(0), new HTuple("E:\\UpperComputer\\LMI\\LMIHalconImage\\" + frameCount.ToString()));Himage_To_3D(GenTLImage, true, "E:\\UpperComputer\\LMI\\LMIHalconImage\\2");GenTL16BitRGBRedImage = null;GenTL16BitRGBGreenImage = null;GenTL16BitRGBBlueImage = null;GenTLImage = null;MyLMICamer.Stop();Console.WriteLine("采集结束");}catch{GenTL16BitRGBRedImage.Dispose();GenTL16BitRGBRedImage = null;GenTL16BitRGBGreenImage.Dispose();GenTL16BitRGBGreenImage = null;GenTL16BitRGBBlueImage.Dispose();GenTL16BitRGBBlueImage = null;GenTLImage.Dispose();GenTLImage = null;MyLMICamer.Stop();}Console.WriteLine(Environment.NewLine);}public static void Gentl_to_object_model_3d(HObject ho_Gentl, out HTuple hv_ObjectModel3D, bool Save3D, string SaveAddress){// Local iconic variables HObject ho_HeightMap, ho_Intensity, ho_ImageOpening;HObject ho_Regions, ho_ImageReduced, ho_ImageConverted;HObject ho_HeightMapMM, ho_ImageSurface, ho_ImageSurface1;HObject ho_X, ho_Y, ho_MultiChannelImage;// Local control variables HTuple hv_frameCount = null, hv_timestamp = null;HTuple hv_encoderPosition = null, hv_encoderIndex = null;HTuple hv_inputs = null, hv_xOffset = null, hv_xResolution = null;HTuple hv_yOffset = null, hv_yResolution = null, hv_zOffset = null;HTuple hv_zResolution = null, hv_width = null, hv_height = null;HTuple hv_HasIntensity = null, hv_Width = null, hv_Height = null;// Initialize local and output iconic variables HOperatorSet.GenEmptyObj(out ho_HeightMap);HOperatorSet.GenEmptyObj(out ho_Intensity);HOperatorSet.GenEmptyObj(out ho_ImageOpening);HOperatorSet.GenEmptyObj(out ho_Regions);HOperatorSet.GenEmptyObj(out ho_ImageReduced);HOperatorSet.GenEmptyObj(out ho_ImageConverted);HOperatorSet.GenEmptyObj(out ho_HeightMapMM);HOperatorSet.GenEmptyObj(out ho_ImageSurface);HOperatorSet.GenEmptyObj(out ho_ImageSurface1);HOperatorSet.GenEmptyObj(out ho_X);HOperatorSet.GenEmptyObj(out ho_Y);HOperatorSet.GenEmptyObj(out ho_MultiChannelImage);ho_HeightMap.Dispose(); ho_Intensity.Dispose();Go2GenTL_ParseData(ho_Gentl, out ho_HeightMap, out ho_Intensity, out hv_frameCount,out hv_timestamp, out hv_encoderPosition, out hv_encoderIndex, out hv_inputs,out hv_xOffset, out hv_xResolution, out hv_yOffset, out hv_yResolution, out hv_zOffset,out hv_zResolution, out hv_width, out hv_height, out hv_HasIntensity);if (HDevWindowStack.IsOpen()){HOperatorSet.DispObj(ho_HeightMap, HDevWindowStack.GetActive());}ho_ImageOpening.Dispose();HOperatorSet.GrayOpeningShape(ho_HeightMap, out ho_ImageOpening, 7, 7, "octagon");ho_Regions.Dispose();HOperatorSet.Threshold(ho_ImageOpening, out ho_Regions, 1, 65535);ho_ImageReduced.Dispose();HOperatorSet.ReduceDomain(ho_ImageOpening, ho_Regions, out ho_ImageReduced);ho_ImageConverted.Dispose();HOperatorSet.ConvertImageType(ho_ImageReduced, out ho_ImageConverted, "real");ho_HeightMapMM.Dispose();HOperatorSet.ScaleImage(ho_ImageConverted, out ho_HeightMapMM, hv_zResolution,hv_zOffset);HOperatorSet.GetImageSize(ho_Gentl, out hv_Width, out hv_Height);//生成xy坐标的图像映射,乘以分辨率就是xy的相对值ho_ImageSurface.Dispose();HOperatorSet.GenImageSurfaceFirstOrder(out ho_ImageSurface, "real", 1, 0, 0,0, 0, hv_Width, hv_Height);ho_ImageSurface1.Dispose();HOperatorSet.GenImageSurfaceFirstOrder(out ho_ImageSurface1, "real", 0, 1, 0,0, 0, hv_Width, hv_Height);//Create X image with correct scaling (in [m])//scale_image (ImageSurface, X, xResolution * 1e-3, xOffset * 1e-3)//scale_image (ImageSurface1, Y, yResolution * 1e-3, yOffset * 1e-3)ho_X.Dispose();HOperatorSet.GenImageSurfaceFirstOrder(out ho_X, "real", 0, hv_xResolution, hv_xOffset,0, 0, hv_Width, hv_Height);//Create Y image with correct scaling (in [m])ho_Y.Dispose();HOperatorSet.GenImageSurfaceFirstOrder(out ho_Y, "real", -hv_yResolution, 0,-hv_yOffset, 0, 0, hv_Width, hv_Height);//scale_image (Z, Z, zResolution * -1e-6, (StandOff + zOffsetTransform_signed) * 1e-6 - zOffset * 1e-9)ho_MultiChannelImage.Dispose();HOperatorSet.Compose3(ho_X, ho_Y, ho_HeightMapMM, out ho_MultiChannelImage);HOperatorSet.XyzToObjectModel3d(ho_X, ho_Y, ho_HeightMapMM, out hv_ObjectModel3D);if (Save3D){HOperatorSet.WriteObjectModel3d(hv_ObjectModel3D, "ply", SaveAddress,new HTuple(), new HTuple());}}public static void Go2GenTL_ParseData(HObject ho_Image, out HObject ho_HeightMap, out HObject ho_Intensity,out HTuple hv_FrameCount, out HTuple hv_Timestamp, out HTuple hv_EncoderPosition,out HTuple hv_EncoderIndex, out HTuple hv_Inputs, out HTuple hv_xOffset, out HTuple hv_xResolution,out HTuple hv_yOffset, out HTuple hv_yResolution, out HTuple hv_zOffset, out HTuple hv_zResolution,out HTuple hv_Width, out HTuple hv_Length, out HTuple hv_HasIntensity){// Local iconic variables HObject ho_Stamps = null;// Local control variables HTuple hv_channelCount = null, hv_monoImageWidth = new HTuple();HTuple hv_monoImageHeight = new HTuple(), hv_IntensityPosition = new HTuple();// Initialize local and output iconic variables HOperatorSet.GenEmptyObj(out ho_HeightMap);HOperatorSet.GenEmptyObj(out ho_Intensity);HOperatorSet.GenEmptyObj(out ho_Stamps);hv_FrameCount = new HTuple();hv_Timestamp = new HTuple();hv_EncoderPosition = new HTuple();hv_EncoderIndex = new HTuple();hv_Inputs = new HTuple();hv_xOffset = new HTuple();hv_xResolution = new HTuple();hv_yOffset = new HTuple();hv_yResolution = new HTuple();hv_zOffset = new HTuple();hv_zResolution = new HTuple();hv_Width = new HTuple();hv_Length = new HTuple();hv_HasIntensity = new HTuple();HOperatorSet.CountChannels(ho_Image, out hv_channelCount);//if ((int)(new HTuple(hv_channelCount.TupleEqual(1))) != 0){//HOperatorSet.GetImageSize(ho_Image, out hv_monoImageWidth, out hv_monoImageHeight);ho_Stamps.Dispose();HOperatorSet.CropRectangle1(ho_Image, out ho_Stamps, hv_monoImageHeight - 1,0, hv_monoImageHeight - 1, hv_monoImageWidth);//Go2GenTLStamp(ho_Stamps, 1, out hv_FrameCount);Go2GenTLStamp(ho_Stamps, 2, out hv_Timestamp);Go2GenTLStamp(ho_Stamps, 3, out hv_EncoderPosition);Go2GenTLStamp(ho_Stamps, 4, out hv_EncoderIndex);Go2GenTLStamp(ho_Stamps, 5, out hv_Inputs);Go2GenTLStamp(ho_Stamps, 6, out hv_xOffset);Go2GenTLStamp(ho_Stamps, 7, out hv_xResolution);Go2GenTLStamp(ho_Stamps, 8, out hv_yOffset);Go2GenTLStamp(ho_Stamps, 9, out hv_yResolution);Go2GenTLStamp(ho_Stamps, 10, out hv_zOffset);Go2GenTLStamp(ho_Stamps, 11, out hv_zResolution);Go2GenTLStamp(ho_Stamps, 12, out hv_Width);Go2GenTLStamp(ho_Stamps, 13, out hv_Length);Go2GenTLStamp(ho_Stamps, 14, out hv_HasIntensity);//ho_HeightMap.Dispose();HOperatorSet.CropRectangle1(ho_Image, out ho_HeightMap, 0, 0, hv_Length - 1,hv_Width);if ((int)(new HTuple(hv_HasIntensity.TupleEqual(1))) != 0){hv_IntensityPosition = (hv_monoImageHeight - 1) / 2;ho_Intensity.Dispose();HOperatorSet.CropRectangle1(ho_Image, out ho_Intensity, hv_IntensityPosition,0, (hv_IntensityPosition + hv_Length) - 1, hv_Width);}else{ho_Intensity.Dispose();HOperatorSet.GenImageConst(out ho_Intensity, "byte", hv_Width, hv_Length);}//}else if ((int)(new HTuple(hv_channelCount.TupleEqual(3))) != 0){//将三通道图像转换为三个图像ho_HeightMap.Dispose(); ho_Intensity.Dispose(); ho_Stamps.Dispose();HOperatorSet.Decompose3(ho_Image, out ho_HeightMap, out ho_Intensity, out ho_Stamps);//Go2GenTLStamp(ho_Stamps, 1, out hv_FrameCount);Go2GenTLStamp(ho_Stamps, 2, out hv_Timestamp);Go2GenTLStamp(ho_Stamps, 3, out hv_EncoderPosition);Go2GenTLStamp(ho_Stamps, 4, out hv_EncoderIndex);Go2GenTLStamp(ho_Stamps, 5, out hv_Inputs);Go2GenTLStamp(ho_Stamps, 6, out hv_xOffset);Go2GenTLStamp(ho_Stamps, 7, out hv_xResolution);Go2GenTLStamp(ho_Stamps, 8, out hv_yOffset);Go2GenTLStamp(ho_Stamps, 9, out hv_yResolution);Go2GenTLStamp(ho_Stamps, 10, out hv_zOffset);Go2GenTLStamp(ho_Stamps, 11, out hv_zResolution);Go2GenTLStamp(ho_Stamps, 12, out hv_Width);Go2GenTLStamp(ho_Stamps, 13, out hv_Length);Go2GenTLStamp(ho_Stamps, 14, out hv_HasIntensity);}////* Change Offset and resolution back to floating point and described in mmhv_xOffset = hv_xOffset / 1000000.0;hv_yOffset = hv_yOffset / 1000000.0;hv_zOffset = hv_zOffset / 1000000.0;hv_xResolution = hv_xResolution / 1000000.0;hv_yResolution = hv_yResolution / 1000000.0;hv_zResolution = hv_zResolution / 1000000.0;//ho_Stamps.Dispose();return;}public static void Go2GenTLStamp(HObject ho_Stamps, HTuple hv_Index, out HTuple hv_Value){// Local iconic variables // Local control variables HTuple hv_test_value = null, hv_is64bit = new HTuple();HTuple hv_tempvalue0 = null, hv_tempvalue1 = null, hv_tempvalue2 = null;HTuple hv_tempvalue3 = null;// Initialize local and output iconic variables hv_Value = new HTuple();//Check if we are on a 64-bit machinehv_test_value = 0xFFFFFFFF;if ((int)(new HTuple(hv_test_value.TupleGreater(0))) != 0){hv_is64bit = 1;}else{hv_is64bit = 0;}//HOperatorSet.GetGrayval(ho_Stamps, 0, hv_Index * 4, out hv_tempvalue0);HOperatorSet.GetGrayval(ho_Stamps, 0, (hv_Index * 4) + 1, out hv_tempvalue1);HOperatorSet.GetGrayval(ho_Stamps, 0, (hv_Index * 4) + 2, out hv_tempvalue2);HOperatorSet.GetGrayval(ho_Stamps, 0, (hv_Index * 4) + 3, out hv_tempvalue3);////The actual stamp from the Gocator is 64-bit. tempvalue0 is the most significant 16-bit (i.e. the top bit is the sign bit)//The code below assumes we only need the bottom 32-bit information. User need to update this conversion function if they want to//return 64-bit value.//if ((int)(new HTuple(hv_is64bit.TupleEqual(1))) != 0){HOperatorSet.TupleLsh(hv_tempvalue0, 48, out hv_tempvalue0);HOperatorSet.TupleLsh(hv_tempvalue1, 32, out hv_tempvalue1);HOperatorSet.TupleLsh(hv_tempvalue2, 16, out hv_tempvalue2);HOperatorSet.TupleLsh(hv_tempvalue3, 0, out hv_tempvalue3);hv_Value = ((hv_tempvalue0 + hv_tempvalue1) + hv_tempvalue2) + hv_tempvalue3;}else{HOperatorSet.TupleLsh(hv_tempvalue2, 16, out hv_tempvalue2);HOperatorSet.TupleLsh(hv_tempvalue3, 0, out hv_tempvalue3);hv_Value = hv_tempvalue2 + hv_tempvalue3;}return;}/// <summary>/// GenTL16BitRGBBlueImage生成/// </summary>/// <param name="frameCount"></param>/// <param name="timeStamp"></param>/// <param name="encoderValue"></param>/// <param name="encoderIndex"></param>/// <param name="digitalStates"></param>/// <param name="surfaceBufferWidth"></param>/// <param name="surfaceBufferLength"></param>/// <param name="surfaceXOffset"></param>/// <param name="surfaceXResolution"></param>/// <param name="surfaceYOffset"></param>/// <param name="surfaceYResolution"></param>/// <param name="surfaceZOffset"></param>/// <param name="surfaceZResolution"></param>/// <param name="intensityEnable"></param>/// <param name="GenTL16BitRGBBlueImage"></param>private static void GenGenTL16BitRGBBlueImage(long frameCount, long timeStamp, long encoderValue, long encoderIndex, long digitalStates,long surfaceBufferWidth, long surfaceBufferLength,long surfaceXOffset, long surfaceXResolution,long surfaceYOffset, long surfaceYResolution,long surfaceZOffset, long surfaceZResolution,long intensityEnable,out HObject GenTL16BitRGBBlueImage){try{#region 初始BlueImage缓存//BlueImage缓存ushort[] blueChannel = new ushort[surfaceBufferWidth * surfaceBufferLength];//临时变量ushort temp0 = 0, temp1 = 0, temp2 = 0, temp3 = 0;//VersionblueChannel[0] = 0;blueChannel[1] = 0;blueChannel[2] = 0;blueChannel[3] = 0;//Frame CountLong2UShort(frameCount, ref temp0, ref temp1, ref temp2, ref temp3);blueChannel[4] = temp0;blueChannel[5] = temp1;blueChannel[6] = temp2;blueChannel[7] = temp3;//TimeStampLong2UShort(timeStamp, ref temp0, ref temp1, ref temp2, ref temp3);blueChannel[8] = temp0;blueChannel[9] = temp1;blueChannel[10] = temp2;blueChannel[11] = temp3;//Encoder value(ticks)Long2UShort(encoderValue, ref temp0, ref temp1, ref temp2, ref temp3);blueChannel[12] = temp0;blueChannel[13] = temp1;blueChannel[14] = temp2;blueChannel[15] = temp3;//Encoder index (ticks)Long2UShort(encoderIndex, ref temp0, ref temp1, ref temp2, ref temp3);blueChannel[16] = temp0;blueChannel[17] = temp1;blueChannel[18] = temp2;blueChannel[19] = temp3;//Digital input statesLong2UShort(digitalStates, ref temp0, ref temp1, ref temp2, ref temp3);blueChannel[20] = temp0;blueChannel[21] = temp1;blueChannel[22] = temp2;blueChannel[23] = temp3;//X offset (nm)Long2UShort(surfaceXOffset, ref temp0, ref temp1, ref temp2, ref temp3);blueChannel[24] = temp0;blueChannel[25] = temp1;blueChannel[26] = temp2;blueChannel[27] = temp3;//X resolution(nm)Long2UShort(surfaceXResolution, ref temp0, ref temp1, ref temp2, ref temp3);blueChannel[28] = temp0;blueChannel[29] = temp1;blueChannel[30] = temp2;blueChannel[31] = temp3;//Y offset (nm)Long2UShort(surfaceYOffset, ref temp0, ref temp1, ref temp2, ref temp3);blueChannel[32] = temp0;blueChannel[33] = temp1;blueChannel[34] = temp2;blueChannel[35] = temp3;//Y resolution (nm)Long2UShort(surfaceYResolution, ref temp0, ref temp1, ref temp2, ref temp3);blueChannel[36] = temp0;blueChannel[37] = temp1;blueChannel[38] = temp2;blueChannel[39] = temp3;//Z offset (nm)Long2UShort(surfaceZOffset, ref temp0, ref temp1, ref temp2, ref temp3);blueChannel[40] = temp0;blueChannel[41] = temp1;blueChannel[42] = temp2;blueChannel[43] = temp3;//Z resolution (nm)Long2UShort(surfaceZResolution, ref temp0, ref temp1, ref temp2, ref temp3);blueChannel[44] = temp0;blueChannel[45] = temp1;blueChannel[46] = temp2;blueChannel[47] = temp3;//Height map Width (in pixels)Long2UShort(surfaceBufferWidth, ref temp0, ref temp1, ref temp2, ref temp3);blueChannel[48] = temp0;blueChannel[49] = temp1;blueChannel[50] = temp2;blueChannel[51] = temp3;//Height map length (in pixels)Long2UShort(surfaceBufferLength, ref temp0, ref temp1, ref temp2, ref temp3);blueChannel[52] = temp0;blueChannel[53] = temp1;blueChannel[54] = temp2;blueChannel[55] = temp3;//Specify if intensity is enabled or notLong2UShort(intensityEnable, ref temp0, ref temp1, ref temp2, ref temp3);blueChannel[56] = temp0;blueChannel[57] = temp1;blueChannel[58] = temp2;blueChannel[59] = temp3;#endregion#region 创建GenTL16BitRGBBlueImageunsafe{fixed (ushort* p = blueChannel)HOperatorSet.GenImage1(out GenTL16BitRGBBlueImage, "uint2", surfaceBufferWidth, surfaceBufferLength, new IntPtr(p));}#endregion}catch (Exception ex){throw ex;}}/// <summary>/// Long类型ToUint2类型转换器/// </summary>/// <param name="value"></param>/// <param name="valueL0"></param>/// <param name="valueL1"></param>/// <param name="valueL2"></param>/// <param name="valueL3"></param>private static void Long2UShort(long value, ref ushort valueL0, ref ushort valueL1, ref ushort valueL2, ref ushort valueL3){valueL0 = (ushort)(value >> 48);valueL1 = (ushort)(value >> 32);valueL2 = (ushort)(value >> 16);valueL3 = (ushort)(value >> 0);}#endregion}
}

LMI相机的运行逻辑并不难,一个主要是如何配置LMI相机,另一个是如何转换格式图像。代码中提供了3种转换方式,分别有:GenTL格式,带标定数据的halcon类型,不带标定数据的halcon类型。
如何配置LMI相机后面会再开一份博客进行讲解。
其中需要注意的事情又:
第一:LMI的相机SDK与VS的版本(。net版本)有部分冲突,再使用.net4.72和VS2022时发现,最新版LMISDK无法运行,暂时可以使用旧版SDK。
第二:LMI相机加速器,只能使用相机相对应版本的加速器进行加速,相机SDK中并没有内置加速器。

相关文章:

  • Linux命令--重启系统的方法
  • 电源电压范 围宽、功耗小、抗干扰能力强的国产芯片GS069适用于电动工具等产品中,采用SOP8的封装形式封装
  • Redis缓存穿透、击穿、雪崩
  • 阿里云国际站:密钥管理服务
  • 【Vue原理解析】之异步与优化
  • python接口自动化-参数关联
  • Ladybug 全景相机, 360°球形成像,带来全方位的视觉体验
  • [代码实战和详解]VGG16
  • vue 使用 this.$router.push 传参数,接参数的 query或params 两种方法示例
  • 第一行代码第三版-第三章变量和函数
  • CSS特效007:绘制3D文字,类似PS效果
  • css中的hover用法示例(可以在vue中制作鼠标悬停显示摸个按钮的效果)
  • 桂院校园导航 静态项目 二次开发教程 1.3
  • 差分详解(附加模板和例题)
  • 桂院校园导航 | 云上高校导航 云开发项目 二次开发教程 1.3
  • 网络传输文件的问题
  • (三)从jvm层面了解线程的启动和停止
  • [deviceone开发]-do_Webview的基本示例
  • Apache的基本使用
  • CentOS学习笔记 - 12. Nginx搭建Centos7.5远程repo
  • Javascripit类型转换比较那点事儿,双等号(==)
  • javascript 哈希表
  • JavaScript工作原理(五):深入了解WebSockets,HTTP/2和SSE,以及如何选择
  • linux学习笔记
  • MobX
  • overflow: hidden IE7无效
  • Terraform入门 - 3. 变更基础设施
  • Wamp集成环境 添加PHP的新版本
  • 阿里云Kubernetes容器服务上体验Knative
  • 机器学习学习笔记一
  • 近期前端发展计划
  • 猫头鹰的深夜翻译:JDK9 NotNullOrElse方法
  • 前端面试之闭包
  • 前端面试总结(at, md)
  • 使用Swoole加速Laravel(正式环境中)
  • 数组的操作
  • 微信支付JSAPI,实测!终极方案
  • 运行时添加log4j2的appender
  • 在 Chrome DevTools 中调试 JavaScript 入门
  • 3月27日云栖精选夜读 | 从 “城市大脑”实践,瞭望未来城市源起 ...
  • CMake 入门1/5:基于阿里云 ECS搭建体验环境
  • 东超科技获得千万级Pre-A轮融资,投资方为中科创星 ...
  • ​​​​​​​​​​​​​​汽车网络信息安全分析方法论
  • ​Linux Ubuntu环境下使用docker构建spark运行环境(超级详细)
  • !$boo在php中什么意思,php前戏
  • #NOIP 2014# day.1 生活大爆炸版 石头剪刀布
  • #pragam once 和 #ifndef 预编译头
  • (1)(1.8) MSP(MultiWii 串行协议)(4.1 版)
  • (42)STM32——LCD显示屏实验笔记
  • (附源码)ssm智慧社区管理系统 毕业设计 101635
  • (论文阅读40-45)图像描述1
  • (已更新)关于Visual Studio 2019安装时VS installer无法下载文件,进度条为0,显示网络有问题的解决办法
  • (转)ABI是什么
  • (转)EXC_BREAKPOINT僵尸错误
  • (转)fock函数详解