领胜LDS 键盘AOI检测项目
src/Bro.Device.Gocator/GocatorDriver.cs
@@ -1,16 +1,23 @@
using Bro.Common.Base;
using Bro.Common.Helper;
using Bro.Common.Interface;
using Bro.Common.Model;
using HalconDotNet;
using Lmi3d.GoSdk;
using Lmi3d.GoSdk.Messages;
using Lmi3d.Zen;
using Lmi3d.Zen.Io;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using static Bro.Common.Helper.EnumHelper;
namespace Bro.Device.Gocator
{
@@ -30,14 +37,23 @@
        public override void Snapshot()
        {
            GoDataSet dataSet = null;
            if (IIConfig.IsAsyncMode)
            {
                if (!IIConfig.IsHardwareTrigger)
                {
                    _snapFlag = true;
                    if (!_snapHandle.WaitOne(IIConfig.SnapshotTimeout))
                    {
                        LogAsync(DateTime.Now, $"{Name}获取图像超时", "");
                        return;
                    }
                    dataSet = _currentData;
                }
            }
            else
            {
                GoDataSet dataSet = null;
                try
                {
                    dataSet = system.ReceiveData(IIConfig.SnapshotTimeout);
@@ -47,33 +63,23 @@
                    LogAsync(DateTime.Now, $"{Name}获取图像异常", ex.GetExceptionMessage());
                    return;
                }
                HandleGoData(dataSet);
            }
            HandleGoData(dataSet);
        }
        private void HandleGoData(GoDataSet dataSet)
        private void HandleGoData(GoDataSet dataSet, GoImageSet imgSet = null)
        {
            if (dataSet == null)
            {
                return;
            }
            for (UInt32 i = 0; i < dataSet.Count; i++)
            {
                GoDataMsg dataObj = (GoDataMsg)dataSet.Get(i);
                switch (dataObj.MessageType)
                {
                    //case GoDataMessageType.Stamp:
                    //    {
                    //        GoStampMsg stampMsg = (GoStampMsg)dataObj;
                    //        for (UInt32 j = 0; j < stampMsg.Count; j++)
                    //        {
                    //            GoStamp stamp = stampMsg.Get(j);
                    //            Console.WriteLine("Frame Index = {0}", stamp.FrameIndex);
                    //            Console.WriteLine("Time Stamp = {0}", stamp.Timestamp);
                    //            Console.WriteLine("Encoder Value = {0}", stamp.Encoder);
                    //        }
                    //    }
                    //    break;
                    case GoDataMessageType.Surface:
                        {
                            GoSurfaceMsg surfaceMsg = (GoSurfaceMsg)dataObj;
@@ -82,14 +88,68 @@
                            long bufferSize = width * height;
                            IntPtr bufferPointer = surfaceMsg.Data;
                            //Console.WriteLine("Whole Part Height Map received:");
                            //Console.WriteLine(" Buffer width: {0}", width);
                            //Console.WriteLine(" Buffer height: {0}", height);
                            float zoomFactor = (float)((double)surfaceMsg.YResolution / (double)surfaceMsg.XResolution);
                            int zoomHeight = (int)(zoomFactor * height);
                            IntPtr zoomPtr = Marshal.AllocHGlobal(zoomHeight * (int)width * 2);
                            //short[] ranges = new short[bufferSize];
                            //Marshal.Copy(bufferPointer, ranges, 0, ranges.Length);
                            //没有插值,默认0
                            //Parallel.For(0, height, h =>
                            //  {
                            //      CopyMemory((IntPtr)((long)zoomPtr + width * 2 * Math.Floor(h * zoomFactor)), (IntPtr)((long)bufferPointer + width * 2 * h), width * 2);
                            //  });
                            Generate16GrayImageByPointer((int)(width / 1), (int)(height / 1), bufferPointer, "");
                            //使用上一行原有数据
                            Parallel.For(0, zoomHeight, h =>
                            {
                                int originHeightIndex = (int)Math.Floor((double)height * h / (double)zoomHeight);
                                CopyMemory((IntPtr)((long)zoomPtr + width * 2 * h), (IntPtr)((long)bufferPointer + width * 2 * originHeightIndex), width * 2);
                            });
                            if (imgSet != null)
                            {
                                imgSet.HImage = new HImage();
                                imgSet.HImage.GenImage1("uint2", (int)width, zoomHeight, zoomPtr);
                                imgSet.HImage_2 = new HImage();
                                imgSet.HImage_2.GenImage1("uint2", (int)width, zoomHeight, zoomPtr);
                                LaserScanParam para = new LaserScanParam()
                                {
                                    Resolution_X = surfaceMsg.XResolution,
                                    Resolution_Y = surfaceMsg.YResolution,
                                    Resolution_Z = surfaceMsg.ZResolution,
                                    Offset_X = surfaceMsg.XOffset,
                                    Offset_Y = surfaceMsg.YOffset,
                                    Offset_Z = surfaceMsg.ZOffset,
                                    Angle_Z = surfaceMsg.ZAngle,
                                };
                                imgSet.ImageData = JsonConvert.SerializeObject(para);
                                //imgSet.HImage_2 = imgSet.HImage_2.ZoomImageSize((int)width, zoomHeight, "constant");
                            }
                            Generate16GrayImageByPointer((int)width, zoomHeight, zoomPtr, imgSet?.Id).ContinueWith(t =>
                            {
                                Marshal.FreeHGlobal(zoomPtr);
                            });
                            //int zoomHeight = (int)(((double)surfaceMsg.YResolution / (double)surfaceMsg.XResolution) * (double)surfaceMsg.Length);
                            //if (imgSet != null)
                            //{
                            //    imgSet.HImage = new HImage();
                            //    imgSet.HImage.GenImage1("uint2", (int)width, (int)height, bufferPointer);
                            //    imgSet.HImage = imgSet.HImage.ZoomImageSize((int)width, zoomHeight, "constant");
                            //    imgSet.HImage_2 = new HImage();
                            //    imgSet.HImage_2.GenImage1("uint2", (int)width, (int)height, bufferPointer);
                            //    imgSet.HImage_2 = imgSet.HImage_2.ZoomImageSize((int)width, zoomHeight, "constant");
                            //}
                            //Generate16GrayImageByPointer((int)width, (int)height, bufferPointer, imgSet?.Id);
                        }
                        break;
                        //case GoDataMessageType.SurfaceIntensity:
@@ -98,27 +158,93 @@
                        //        long width = surfaceMsg.Width;
                        //        long height = surfaceMsg.Length;
                        //        long bufferSize = width * height;
                        //        IntPtr bufferPointeri = surfaceMsg.Data;
                        //        IntPtr bufferPointer = surfaceMsg.Data;
                        //        //Console.WriteLine("Whole Part Intensity Image received:");
                        //        //Console.WriteLine(" Buffer width: {0}", width);
                        //        //Console.WriteLine(" Buffer height: {0}", height);
                        //        //byte[] ranges = new byte[bufferSize];
                        //        //Marshal.Copy(bufferPointeri, ranges, 0, ranges.Length);
                        //        //GenerateGrayImageByPointer((int)width, (int)height, bufferPointeri, "");
                        //        //int zoomHeight = (surfaceMsg.YResolution * (int)surfaceMsg.Length * 10) / surfaceMsg.XResolution;
                        //        int zoomHeight = (int)(((double)surfaceMsg.YResolution / (double)surfaceMsg.XResolution) * (double)surfaceMsg.Length);
                        //        if (imgSet != null)
                        //        {
                        //            imgSet.HImage = new HImage();
                        //            imgSet.HImage.GenImage1("uint2", (int)width, (int)height, bufferPointer);
                        //            imgSet.HImage = imgSet.HImage.ZoomImageSize((int)width, zoomHeight, "constant");
                        //            imgSet.HImage_2 = new HImage();
                        //            imgSet.HImage_2.GenImage1("uint2", (int)width, (int)height, bufferPointer);
                        //            imgSet.HImage_2 = imgSet.HImage_2.ZoomImageSize((int)width, zoomHeight, "constant");
                        //        }
                        //        Generate16GrayImageByPointer((int)width, (int)height, bufferPointer, imgSet?.Id);
                        //    }
                        //    break;
                }
            }
        }
        public override ImageSet Snapshot(IOperationConfig config)
        public override IImageSet Snapshot(IOperationConfig config)
        {
            ImageSet imgSet = base.Snapshot(config);
            if (!IIConfig.IsAsyncMode)
            {
                if (config is GocatorOperationConfig opConfig)
                {
                    if (opConfig.IsOpenConnection)
                    {
                        system.Start();
                    }
                    else
                    {
                        system.Stop();
                    }
                    if (!opConfig.IsSnapshotAction)
                    {
                        return null;
                    }
                }
            }
            GoImageSet imgSet = new GoImageSet();
            InitialImageSet(imgSet, (config as CameraOprerationConfigBase).ImageSaveOption);
            GoDataSet dataSet = null;
            if (IIConfig.IsAsyncMode)
            {
                if (!IIConfig.IsHardwareTrigger)
                {
                    _snapFlag = true;
                    if (!_snapHandle.WaitOne(IIConfig.SnapshotTimeout))
                    {
                        LogAsync(DateTime.Now, $"{Name}获取图像超时", "");
                        return null;
                    }
                    dataSet = _currentData;
                }
            }
            else
            {
                try
                {
                    dataSet = system.ReceiveData(IIConfig.SnapshotTimeout);
                }
                catch (Exception ex)
                {
                    LogAsync(DateTime.Now, $"{Name}获取图像异常", ex.GetExceptionMessage());
                    return null;
                }
            }
            HandleGoData(dataSet, imgSet);
            if (imgSet.HImage == null)
            {
                LogAsync(DateTime.Now, $"{Name}未能获取HImage图像", "");
            }
            return imgSet;
        }
        float _currentExposure = 0;
        string _currentJob = "";
@@ -193,7 +319,15 @@
            _currentJob = sensor.DefaultJob;
            if (!string.IsNullOrWhiteSpace(IIConfig.DefaultJob) && _currentJob != IIConfig.DefaultJob)
            {
                _currentJob = sensor.DefaultJob = IIConfig.DefaultJob;
                //_currentJob = sensor.DefaultJob = IIConfig.DefaultJob;
                string currentJob = IIConfig.DefaultJob;
                bool isChanged = false;
                sensor.LoadedJob(ref currentJob, ref isChanged);
                if (!isChanged)
                {
                    throw new ProcessException($"{Name}未成功切换至任务{IIConfig.DefaultJob}");
                }
            }
            sensor.Flush();
@@ -240,6 +374,10 @@
            get => InitialConfig as GocatorInitialConfig;
        }
        volatile bool _snapFlag = false;
        readonly ManualResetEvent _snapHandle = new ManualResetEvent(false);
        GoDataSet _currentData = null;
        /// <summary>
        /// 异步模式获取数据
        /// </summary>
@@ -247,6 +385,127 @@
        private void onData(KObject data)
        {
            GoDataSet dataSet = (GoDataSet)data;
            if (IIConfig.IsHardwareTrigger)
            {
                GoImageSet imgSet = new GoImageSet();
                InitialImageSet(imgSet, IConfig.ImageSaveOption);
                HandleGoData(dataSet, imgSet);
                if (imgSet.HImage != null)
                {
                    OnHImageOutput?.BeginInvoke(this, imgSet.HImage, imgSet.Id, null, null);
                }
                else
                {
                    LogAsync(DateTime.Now, $"{Name}获取HImage失败", "");
                }
            }
            else
            {
                if (_snapFlag)
                {
                    _snapFlag = false;
                    _currentData = dataSet.Clone<GoDataSet>();
                    _snapHandle.Set();
                }
            }
        }
        #region 重写图片保存操作
        public override async void SaveOriginImage(Bitmap map, Bitmap showImage, string imgSetId)
        {
            Task.Run(() =>
             {
                 OnImageUpdated?.Invoke(this, showImage, imgSetId);
             });
            GoImageSet set = _imageSetList.FirstOrDefault(u => u.Id == imgSetId) as GoImageSet;
            if (set == null)
                return;
            set.Image = map;
            await Task.Run(() =>
            {
                lock (set.SaveLock)
                {
                    if (set.ImageSaveOption.IsSaveOriginImage && !set.IsOriginSaved)
                    {
                        string imgDir = CheckImageDirectory(set.ImageSaveOption.ImageSaveSubDirectory, "Origin");
                        try
                        {
                            //SaveImageByNameAndType(map, set.Id, set.ImageSaveOption.ImageFormat, imgDir);
                            string filePath = Path.Combine(imgDir, $"{set.Id}.tif");
                            set.HImage_2.WriteImage("tiff", 0, filePath);
                        }
                        catch (Exception ex)
                        {
                            LogAsync(DateTime.Now, $"{set.Id}原图保存失败", ex.GetExceptionMessage());
                        }
                    }
                    set.IsOriginSaved = true;
                    ClearImageSet(set);
                }
            });
        }
        /// <summary>
        /// 保存特定类型图片,例如NG图片
        /// </summary>
        /// <param name="prefix">图片类型说明 例如“NG”</param>
        /// <param name="imgSetId">图片ID</param>
        public override async void SaveSelectedImage(string prefix, string imgSetId)
        {
            await Task.Run(() =>
            {
                GoImageSet set = _imageSetList.FirstOrDefault(u => u.Id == imgSetId) as GoImageSet;
                if (set == null)
                    return;
                lock (set.SaveLock)
                {
                    if (set.ImageSaveOption.AddtionalSaveType.Contains(prefix) && !set.IsAddtionalSaved)
                    {
                        string imgDir = CheckImageDirectory(set.ImageSaveOption.ImageSaveSubDirectory, prefix);
                        while (set.Image == null)
                        {
                            Thread.Sleep(50);
                        }
                        try
                        {
                            string filePath = Path.Combine(imgDir, $"{set.Id}.tif");
                            set.HImage_2.WriteImage("tiff", 0, filePath);
                        }
                        catch (Exception ex)
                        {
                            LogAsync(DateTime.Now, $"{set.Id}{prefix}图片保存失败", ex.GetExceptionMessage());
                        }
                    }
                    set.IsAddtionalSaved = true;
                    ClearImageSet(set);
                }
            });
        }
        #endregion
    }
    public class GoImageSet : ImageSet
    {
        public HImage HImage_2 { get; set; }
        public override void Dispose()
        {
            base.Dispose();
            HImage_2?.Dispose();
            HImage_2 = null;
        }
    }
}