想用3D扫描后的图片,但是系统自带的导出方法很麻烦,所以考虑通过sdk导出
首先需要设置点云亮度
这里是导出图片的关键代码
case GoDataMessageType.SurfaceIntensity:
{
Debug.WriteLine("SurfaceIntensity ");
GoSurfaceIntensityMsg surfaceMsg = (GoSurfaceIntensityMsg)dataObj;
long width = surfaceMsg.Width;
long length = surfaceMsg.Length;
long bufferSize = width * length;
IntPtr bufferPointeri = surfaceMsg.Data;
//Console.WriteLine("Surface Intensity received:");
//Console.WriteLine(" Buffer width: {0}", width);
//Console.WriteLine(" Buffer length: {0}", length);
byte[] ranges = new byte[bufferSize];
Marshal.Copy(bufferPointeri, ranges, 0, ranges.Length);
Mat mat1 = new Mat((int)length, (int)width, MatType.CV_8UC1, bufferPointeri);
//Mat mat = Cv2.ImDecode(ranges, ImreadModes.Grayscale);
long UID = YitIdHelper.NextId();
string GlueImageDir = LogsUtil.GetLogDir(LogsUtil.GlueImage);
ImageFile = await FileHelper.SaveVisionImage1(mat1, GlueImageDir, $"Glue3Dimage_{gm.TireBarcode}_{UID}.png");
}
break;
using Camera3D.Models.Glue;
using Camera3D.Utils;
using FluentFTP;
using Google.Protobuf.WellKnownTypes;
using JHCamera3D.Helper.Python;
using JHCamera3D.Utils;
//using Intel.RealSense;
using LinkAsiaSmart.MyTask;
using Lmi3d.GoSdk;
using Lmi3d.GoSdk.Messages;
using OpenCvSharp;
using System.Collections;
using System.Drawing.Imaging;
using System.Threading;
using System.Windows.Forms;
using Yitter.IdGenerator;
using static Camera3D.Enum.LMI.ReceiveProfile;
using static Emgu.CV.WeChatQRCode;
using static Slapper.AutoMapper;
namespace Camera3D.Helper.TCP
{
/// <summary>
///
/// </summary>
public class Camera3DGlue
{
public delegate void OnDataType(KObject data);
public static Camera3DGlue? Instance;
public static bool isSaveDataToMySql = true;
public static bool isGoLoad = false;
public static bool isStart = false;
public static bool isCanStatus = false;
private static double TireInsideLength = 0;
private static double EncoderResolution = 0;
GoDataSet dataSet;
static GoSystem system;
static GoSensor sensor;
static GoSurfaceGeneration surfacelength;
public static Camera3DGlue GetInstance()
{
if (Instance == null)
{
Instance = new Camera3DGlue();
}
return Instance;
}
public bool GoLoad()//加载Gocator
{
string ip = SystemParams.Camera3D.LMI3DGlueCameraIP; // "192.168.1.10";
uint SensorID = uint.Parse(SystemParams.Camera3D.LMI3DGlueCameraSensorID); // "192.168.1.10";
KApiLib.Construct();
GoSdkLib.Construct();
system = new GoSystem();
dataSet = new GoDataSet();
try
{
sensor = system.FindSensorById(SensorID);//指定传感器的ID连接
if (sensor.State == GoState.Running)
{
sensor.Stop();
sensor.Disconnect();
};
sensor.Connect();
//double encoder = sensor.Transform.EncoderResolution;
EncoderResolution = sensor.Transform.EncoderResolution;
TireInsideLength = sensor.Setup.GetSurfaceGeneration().FixedLengthLength;
system.EnableData(true);//数据通道使能
system.SetDataHandler(onData);//异步接受数据
isGoLoad = true;
}
catch (Exception ex)
{
return false;
}
return true;
}
public static void Start()
{
try
{
if (sensor == null)
{
return;
}
sensor.Stop();
surfacelength = sensor.Setup.GetSurfaceGeneration();
sensor.Start();
isStart = true;
isCanStatus = true;
}
catch (Exception ex)
{
Log.Logger.Error($" 异常 {ex.Message}");
}
}
public static void Stop()
{
try
{
sensor.Stop();
isCanStatus = false;
}
catch (Exception ex)
{
Log.Logger.Error($"Sensor Stop 异常 {ex.Message}");
}
}
public static GoState GetStatus()
{
GoState state = GoState.Offline;// new GoState();
// state = GoState.Offline;
if (isCanStatus)
{
try
{
state = sensor.State.Value;
}
catch (Exception ex)
{
Log.Logger.Error($" 异常 {ex.Message}");
}
}
return state;
}
public static async void onData(KObject data)
{
int mb = 1024 * 1024;
Process currentProcess = Process.GetCurrentProcess();
long workingSet = currentProcess.WorkingSet64;
Log.Logger.Debug($" 占用内存{workingSet / mb}MB");
Random rdm = new Random(Guid.NewGuid().GetHashCode());
GlueModel gm = new GlueModel();
gm.DateTime = DateUtil.CurrentDate.ToString();
gm.TireBarcode = PLCTag.GetTagValue(TagNameDesc.GlueTireBarcode, TagValueType.String); // Work.PLC.Glue.GetGlueTireBarcode();
string PLYName = $"Glue_{gm.TireBarcode}_{YitIdHelper.NextId()}";
string ImageFile = "";
GlueCompensationModel gcm = new GlueCompensationModel();
float GlueTireInnerCircumference = float.Parse(PLCTag.GetTagValue(TagNameDesc.GlueTireInnerCircumference, TagValueType.Float)); // Work.PLC.TagValue.GetGlueTireInnerCircumference();
Log.Logger.Debug($"接受到 3D 数据 ");
try
{
DataContext context = new DataContext();
GoDataSet dataSet = (GoDataSet)data;
for (UInt32 i = 0; i < dataSet.Count; i++)
{
GoDataMsg dataObj = (GoDataMsg)dataSet.Get(i);
// Debug.WriteLine($"GoDataMsg.MessageType:{dataObj.MessageType}");
Log.Logger.Debug($" GoDataMsg.MessageType : {dataObj.MessageType} ");
switch (dataObj.MessageType)
{
case GoDataMessageType.Stamp:
{
GoStampMsg stampMsg = (GoStampMsg)dataObj;
for (UInt32 j = 0; j < stampMsg.Count; j++)
{
GoStamp stamp = stampMsg.Get(j);
//Debug.WriteLine("Frame Index = {0}", stamp.FrameIndex);
//Debug.WriteLine("Time Stamp = {0}", stamp.Timestamp);
//Debug.WriteLine("Encoder Value = {0}", stamp.Encoder);
// Debug.WriteLine($"{i} -{j} Index = {stamp.FrameIndex} time = {stamp.Timestamp} value = {stamp.Encoder}");
//Debug.WriteLine($" {stampMsg.Count} ");
// LsData.Add(stamp.Encoder.ToString());
}
//
}
break;
case GoDataMessageType.UniformSurface:
{
try
{
GoUniformSurfaceMsg surfaceMsg = (GoUniformSurfaceMsg)dataObj;
long width = surfaceMsg.Width; //被测物体宽度
long length = surfaceMsg.Length; //3D相机走过的长度
long bufferSize = (width * length);
IntPtr bufferPointer = surfaceMsg.Data;
//获取缓存的宽高
long surfaceBufferWidth = surfaceMsg.Width;
long surfaceBufferLength = surfaceMsg.Length;
float[] x = new float[surfaceBufferLength * surfaceBufferWidth];
float[] y = new float[surfaceBufferLength * surfaceBufferWidth];
float[] z = new float[surfaceBufferLength * surfaceBufferWidth];
// byte[] intensity = new byte[surfaceBufferLength * surfaceBufferWidth];
SurfacePoint[] surfaceBuffer = new SurfacePoint[surfaceBufferLength * surfaceBufferWidth];
List<SurfacePoint> ListSurface = new List<SurfacePoint>();
short[] ranges = new short[bufferSize];
Marshal.Copy(bufferPointer, ranges, 0, ranges.Length);
// Marshal.Copy(bufferPointer, intensity, 0, ranges.Length);
//string rangesStr = string.Join(",", ranges);
Log.Logger.Debug($"Surface Width = {width} length = {length} bufferSize = {bufferSize} ");
double xResolution = (double)surfaceMsg.XResolution / 1000000;
double yResolution = (double)surfaceMsg.YResolution / 1000000;
double zResolution = (double)surfaceMsg.ZResolution / 1000000;
// YDotPitch = yResolution;
context.xResolution = (float)surfaceMsg.XResolution / 1000000;
context.yResolution = (float)surfaceMsg.YResolution / 1000000;
context.zResolution = (float)surfaceMsg.ZResolution / 1000000;
context.xOffset = (float)surfaceMsg.XOffset / 1000;
context.yOffset = (float)surfaceMsg.YOffset / 1000;
context.zOffset = (float)surfaceMsg.ZOffset / 1000;
long surfacePointCount = surfaceMsg.Width * surfaceMsg.Length;
for (int j = 0; j < length; j++)
{
for (int k = 0; k < width; k++)
{
y[width * j + k] = (float)(k * context.xResolution + context.xOffset);
x[width * j + k] = (float)(j * context.yResolution + context.yOffset);
short tmp = ranges[width * j + k];
z[width * j + k] = tmp == -32768 ? -32768 : (float)(tmp * context.zResolution + context.zOffset);
// intensity[width * j + k]= context.
//if (tmp == -32768)
//{
// z[width * j + k] = -32768;
//}
//else
//{
// z[width * j + k] = (float)(tmp * context.zResolution + context.zOffset);
//}
surfaceBuffer[width * j + k].x = x[width * j + k];
surfaceBuffer[width * j + k].y = y[width * j + k];
surfaceBuffer[width * j + k].z = z[width * j + k];
}
}
//Mat mat = Cv2.ImDecode(intensity, ImreadModes.Color);
//long UID = YitIdHelper.NextId();
//FileHelper.SaveVisionImage1(mat, $"Glue3Dimage_{UID}.png");
Log.Logger.Debug($"接收到相机点云数量 = {surfacePointCount} ");
ListSurface = surfaceBuffer.Where(a => a.z >= -10000).ToList();
//PointCloudUtil.SavePointCloudToPLY(No, x, y, z);
string PLYFile = await PointCloudUtil.SavePointCloudToPLY(PLYName, ListSurface.ToArray(), LogsUtil.GluePLY);
//PointCloudUtil.SavePointCloudToPLY(No, x, y, z);
DateTime startTime = DateTime.Now;
while (!File.Exists(PLYFile))
{
if (DateTime.Now - startTime > TimeSpan.FromSeconds(10))
{
break;
}
await Task.Delay(200);
}
if (File.Exists(PLYFile))
{
ProcessPLYGlueStrip(PLYFile, gcm);
}
else
{
Log.Logger.Error($" 未找到ply文件 {PLYFile}");
}
x = null;
y = null;
z = null;
ranges = null;
surfaceBuffer = null;
ListSurface.Clear();
ListSurface = null;
bufferPointer = IntPtr.Zero;
}
catch (Exception e)
{
Log.Logger.Error($" GoDataMessageType.Surface 数据处理异常 = {e.Message} {e.StackTrace} ");
}
}
break;
case GoDataMessageType.SurfacePointCloud:
{
GoSurfacePointCloudMsg surfaceMsg = (GoSurfacePointCloudMsg)dataObj;
context.xResolution = (double)surfaceMsg.XResolution / 1000000;
context.yResolution = (double)surfaceMsg.YResolution / 1000000;
context.zResolution = (double)surfaceMsg.ZResolution / 1000000;
context.xOffset = (double)surfaceMsg.XOffset / 1000;
context.yOffset = (double)surfaceMsg.YOffset / 1000;
context.zOffset = (double)surfaceMsg.ZOffset / 1000;
long surfacePointCount = surfaceMsg.Width * surfaceMsg.Length;
Console.WriteLine("Surface Point Cloud received:");
Console.WriteLine(" Buffer width: {0}", surfaceMsg.Width);
Console.WriteLine(" Buffer length: {0}", surfaceMsg.Length);
GoPoints[] points = new GoPoints[surfacePointCount];
SurfacePoint[] surfaceBuffer = new SurfacePoint[surfacePointCount];
int structSize = Marshal.SizeOf(typeof(GoPoints));
IntPtr pointsPtr = surfaceMsg.Data;
for (UInt32 array = 0; array < surfacePointCount; ++array)
{
IntPtr incPtr = new IntPtr(pointsPtr.ToInt64() + array * structSize);
points[array] = (GoPoints)Marshal.PtrToStructure(incPtr, typeof(GoPoints));
}
for (UInt32 arrayIndex = 0; arrayIndex < surfacePointCount; ++arrayIndex)
{
if (points[arrayIndex].x != -32768)
{
surfaceBuffer[arrayIndex].x = context.xOffset + context.xResolution * points[arrayIndex].x;
surfaceBuffer[arrayIndex].y = context.yOffset + context.yResolution * points[arrayIndex].y;
surfaceBuffer[arrayIndex].z = context.zOffset + context.zResolution * points[arrayIndex].z;
}
else
{
surfaceBuffer[arrayIndex].x = -32768;
surfaceBuffer[arrayIndex].y = -32768;
surfaceBuffer[arrayIndex].z = -32768;
}
}
}
break;
case GoDataMessageType.SurfaceIntensity:
{
Debug.WriteLine("SurfaceIntensity ");
GoSurfaceIntensityMsg surfaceMsg = (GoSurfaceIntensityMsg)dataObj;
long width = surfaceMsg.Width;
long length = surfaceMsg.Length;
long bufferSize = width * length;
IntPtr bufferPointeri = surfaceMsg.Data;
//Console.WriteLine("Surface Intensity received:");
//Console.WriteLine(" Buffer width: {0}", width);
//Console.WriteLine(" Buffer length: {0}", length);
byte[] ranges = new byte[bufferSize];
Marshal.Copy(bufferPointeri, ranges, 0, ranges.Length);
Mat mat1 = new Mat((int)length, (int)width, MatType.CV_8UC1, bufferPointeri);
//Mat mat = Cv2.ImDecode(ranges, ImreadModes.Grayscale);
long UID = YitIdHelper.NextId();
string GlueImageDir = LogsUtil.GetLogDir(LogsUtil.GlueImage);
ImageFile = await FileHelper.SaveVisionImage1(mat1, GlueImageDir, $"Glue3Dimage_{gm.TireBarcode}_{UID}.png");
}
break;
}
}
Log.Logger.Debug($"完成3D相机的数据");
Download3DImage(ImageFile);
}
catch (Exception ex)
{
Log.Logger.Error($"Camera3D Error {ex.Message}");
}
GlobalConst.Common.SharedLock = false;
workingSet = currentProcess.WorkingSet64;
Log.Logger.Debug($"接收3D相机数据后 占用内存{workingSet / mb}MB");
}
public float GetLength()
{
return (float)TireInsideLength;
}
public string SetLength(double length)
{
string result = "";
try
{
Stop();
surfacelength = sensor.Setup.GetSurfaceGeneration();
//surfacelength.FixedLengthTriggerExternalInputIndex = length;
surfacelength.FixedLengthLength = length;
Log.Logger.Debug($"设置 3D相机触发轮胎内周长 PLC = [{length}] OK");
Start();
result = "OK";
TireInsideLength = length;
}
catch (Exception ex)
{
result = "ERROR";
Log.Logger.Error($"设置 3D相机触发长度异常 {ex.Message}");
}
return result;
}
public string SetEncoderResolution(double value)
{
string result = "";
if (value <= 0)
{
return result;
}
try
{
Stop();
// sensor.Setup.EncoderSpacing = value;
sensor.Transform.EncoderResolution = value;
Log.Logger.Debug($"设置 3D相机分辨率OK {value}");
Start();
result = "OK";
}
catch (Exception ex)
{
result = "ERROR";
Log.Logger.Error($"设置 3D相机分辨率异常 value={value} msg={ex.Message}");
}
return result;
}
public string GetEncoder()
{
string result = "";
try
{
if (isCanStatus)
{
if (sensor.State.Value == GoState.Running)
{
result = sensor.Encoder().ToString();
}
}
}
catch (Exception ex)
{
Log.Logger.Error($"读取 3D相机编码器数值异常 value = {result} {sensor.State} msg = {ex.Message}");
}
return result;
}
public static string Download3DImage(string ImageFile)
{
string result = "";
Task.Run(async () =>
{
try
{
EncoderResolution = sensor.Transform.EncoderResolution;
TireInsideLength = sensor.Setup.GetSurfaceGeneration().FixedLengthLength;
result = "OK";
string JPGImageFile = await ConvertToJPG(ImageFile);
SignalRClient.GetInstance().SendMsg(GlobalConst.SignalRUser.Glue.Camera3DGlueImage, JPGImageFile);
}
catch (Exception ex)
{
Log.Logger.Error($" 3D相机 图片出现异常 {ex.Message}");
result = "Error";
}
});
return result;
}
public static async Task<string> ConvertToJPG(string ImageFile)
{
DateTime startTime = DateTime.Now;
while (!File.Exists(ImageFile))
{
if (DateTime.Now - startTime > TimeSpan.FromSeconds(10))
{
break;
}
await Task.Delay(200);
}
Log.Logger.Debug($"PNG转JPG文件 [{ImageFile}]");
string extension = Path.GetExtension(ImageFile);
Log.Logger.Debug($"PNG转JPG文件 [{extension}]");
string JpgImageFile = ImageFile.Replace(extension, ".jpg");
//string result = "";
//int x = 0;
await Task.Run(async () =>
{
try
{
using (Image image = Image.FromFile(ImageFile))
{
image.Save(JpgImageFile, ImageFormat.Jpeg);
}
}
catch (Exception ex)
{
Log.Logger.Error($"PNG转JPG异常 {ex.Message}");
// result = "Error";
}
});
return JpgImageFile;
}
public static async Task<string> ProcessPLYGlueStrip(string PLYFile, GlueCompensationModel gcm)
{
string result = "";
string No = "Glue" + DateUtil.CurrentDateID;
string ScriptFile = AppSettingsHelper.Configuration["PythonScript:GlueScriptFile"];
Log.Logger.Debug($" Open3D 测量 脚本 {ScriptFile}");
string PlyResultDir = LogsUtil.GetLogDir(LogsUtil.GlueResultPLY);
string str = RunPythonHelper.ExecPythonTireGlue(ScriptFile, PLYFile, PlyResultDir);
Log.Logger.Debug($" Open3D 计算结果 {str}");
string[] JsonStrResult = str.Split("~~");
try
{
if (JsonStrResult[2].Trim().Length > 1)
{
Log.Logger.Error($" errMsg = {JsonStrResult[2]}");
}
else
{
GluePlyResultModel gprm = JsonConvert.DeserializeObject<GluePlyResultModel>(JsonStrResult[1]);
gprm.Barcode = PLCTag.GetTagValue(TagNameDesc.GlueTireBarcode, TagValueType.String);
gprm.DateTime = DateUtil.CurrentDate.ToString();
gprm = GetCompensationResult(gprm, gcm);
string jsonStr = JsonConvert.SerializeObject(gprm);
SignalRClient.GetInstance().SendMsg(GlobalConst.SignalRUser.Glue.Glue3DResult, jsonStr);
}
}
catch (Exception ex)
{
Log.Logger.Error($"处理 Open3D 计算结果异常 {ex.Message}");
}
return result;
}
}
}