eyemDecode_Partial.cs 9.0 KB
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace CodeLibrary
{
    unsafe partial  class  EyemDecode
    {
        
        //结构体
        [StructLayout(LayoutKind.Sequential)]
        public struct EyemHSVModel
        {
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
            public double[] dpRangeL, dpRangeU;        // 提取下限,提取上限[H S V]
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
            public double[] dpRangeLExt, dpRangeUExt;  // 额外提取下限,额外提取上限(针对处于跨模型颜色,比如红色)[H S V]
        }// 用于HSV颜色模型分割(H(0-180)、S(0-255)、V(0-255))


        //接口
        [DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
        private static extern int eyemTrackFeature(EyemImage tpImage, EyemImage tpMask, EyemRect tpRoi, IntPtr tpRois, int ipRoiNum, EyemHSVModel tpHSVModel, [MarshalAs(UnmanagedType.LPArray)] int[] ipResults, out EyemImage tpDstImg);


        ///////////////////使用///////////////////


        public static int[] ReelCheck(string deviceName, Bitmap bitmap)
        {
            EyemImage image = eyemCvtToEyemImage(bitmap);
            //绿色分割模型
            EyemHSVModel tpHsvModel = new EyemHSVModel();
            tpHsvModel.dpRangeL = new double[] { 55, 10, 35 }; tpHsvModel.dpRangeU = new double[] { 100, 255, 255 };
            tpHsvModel.dpRangeLExt = new double[] { 0, 0, 0 }; tpHsvModel.dpRangeUExt = new double[] { 0, 0, 0 };

            //裁剪区域
            EyemRect tpRoi = new EyemRect();
            tpRoi.iXs = 0; tpRoi.iYs = 0;
            tpRoi.iWidth = image.iWidth;
            tpRoi.iHeight = image.iHeight;

            //添加需要监控的位置信息
            List<EyemRect> tpRois = new List<EyemRect>();
            EyemRect roi1 = new EyemRect();
            roi1.iXs = 533; roi1.iYs = 187; roi1.iWidth = 345; roi1.iHeight = 310;
            EyemRect roi2 = new EyemRect();
            roi2.iXs = 900; roi2.iYs = 137; roi2.iWidth = 240; roi2.iHeight = 197;

            tpRois.Add(roi1); tpRois.Add(roi2);

            //转指针
            IntPtr hGlobal = eyemStructArray2IntPtr(tpRois.ToArray());

            //加载mask
            EyemImage mask;
            eyemImageRead("mask.png", -1, out mask);

            //检测
            int[] ipResults = new int[tpRois.Count];
            eyemTrackFeature(image, mask, tpRoi, hGlobal, ipResults.Length, tpHsvModel, ipResults, out EyemImage tpDstImg);

            for (int i = 0; i < ipResults.Length; i++)
            {
                if (ipResults[i] == 1)
                {
                    Console.WriteLine("检测到{0}位置有料盘", i);
                }
            }
            string date = deviceName.Trim().Replace('_', '-') + "-" + DateTime.Now.ToString("yyyyMMdd-HHmmss") + DateTime.Now.Millisecond; 
            string imageName = date + ".bmp";
            Bitmap dstBitmap = eyemCvtToBitmap(tpDstImg);
            if (dstBitmap != null)
            {
                dstBitmap.Save("D:\\ResOut\\" + imageName);
            }
            //释放资源
            Marshal.FreeHGlobal(hGlobal);
            //每运行检测一次释放一次
            eyemImageFree(ref tpDstImg);
            eyemImageFree(ref image);
            //mask可以在程序启动与关闭时加载/释放
            eyemImageFree(ref mask);
            return ipResults;
                
        }
        public static EyemImage eyemCvtToEyemImage(Bitmap bitmap)
        {
            EyemImage tpImage = new EyemImage();
            //锁定数据区
            BitmapData bd = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                ImageLockMode.ReadOnly, bitmap.PixelFormat);

            switch (bitmap.PixelFormat)
            {
                case PixelFormat.Format8bppIndexed:
                    tpImage.iChannels = 1;
                    break;
                case PixelFormat.Format24bppRgb:
                    tpImage.iChannels = 3;
                    break;
                case PixelFormat.Format32bppArgb:
                    tpImage.iChannels = 4;
                    break;
                default:
                    throw new Exception("Image formats are not supported");
            }
            //仅支持8位
            tpImage.iDepth = 0;
            //图像尺寸
            tpImage.iWidth = bitmap.Width; tpImage.iHeight = bitmap.Height;
            //分配内存(释放不是用eyemImageFree,用Marshal.FreeHGlobal(tpImage.vpImage))
            tpImage.vpImage = Marshal.AllocHGlobal(bd.Stride * bd.Height);
            try
            {
                int pd = ((tpImage.iWidth * tpImage.iChannels) + 3) / 4 * 4;

                long bytesToCopy = tpImage.iWidth * tpImage.iChannels;

                for (int y = 0; y < tpImage.iHeight; y++)
                {
                    long offsetSrc = y * pd;
                    long offsetDst = y * tpImage.iWidth * tpImage.iChannels;

                    Buffer.MemoryCopy((byte*)(bd.Scan0.ToPointer()) + offsetSrc, (byte*)(tpImage.vpImage.ToPointer()) + offsetDst, bytesToCopy, bytesToCopy);
                }
            }
            finally
            {
                bitmap.UnlockBits(bd);
            }
            return tpImage;
        }

        //public static void eyemCvtToEyemImage(Bitmap bitmap, out EyemImage tpImage)
        //{
        //    int channels = 0;
        //    switch (bitmap.PixelFormat)
        //    {
        //        case PixelFormat.Format8bppIndexed:
        //            channels = 1;
        //            break;
        //        case PixelFormat.Format24bppRgb:
        //            channels = 3;
        //            break;
        //        case PixelFormat.Format32bppArgb:
        //            channels = 4;
        //            break;
        //        default:
        //            break;
        //    }
        //    //锁定数据区
        //    BitmapData bd = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
        //        ImageLockMode.ReadOnly, bitmap.PixelFormat);
        //    try
        //    {
        //        eyemImageFromBitmap(bd.Scan0, bd.Width, bd.Height, 0, channels, out tpImage);
        //    }
        //    finally
        //    {
        //        bitmap.UnlockBits(bd);
        //    }
        //}

        public static IntPtr eyemStructArray2IntPtr<T>(T[] tpArray)
        {
            if (tpArray == null)
                throw new ArgumentNullException(typeof(T).Name.ToString());
            //分配结构体需要的内存,需要释放
            IntPtr hGlobal = Marshal.AllocHGlobal(checked(Marshal.SizeOf(typeof(T)) * tpArray.Length));
            for (int index = 0; index < tpArray.Length; index++)
            {
                Marshal.StructureToPtr(tpArray[index], (IntPtr)(checked((long)hGlobal + index * Marshal.SizeOf(typeof(T)))), false);
            }
            return hGlobal;
        }
        public static Bitmap eyemCvtToBitmap(EyemImage tpImage)
        {
            if (tpImage.vpImage == IntPtr.Zero || tpImage.iDepth != 0)
                return null;
            PixelFormat format;
            switch (tpImage.iChannels)
            {
                case 1:
                    format = PixelFormat.Format8bppIndexed;
                    break;
                case 3:
                    format = PixelFormat.Format24bppRgb;
                    break;
                case 4:
                    format = PixelFormat.Format32bppArgb;
                    break;
                default:
                    return null;
            }

            Bitmap bitmap = new Bitmap(tpImage.iWidth, tpImage.iHeight, format);
            //对于输出灰度图像
            if (format == PixelFormat.Format8bppIndexed)
            {
                ColorPalette palette = bitmap.Palette;
                for (int i = 0; i < 256; i++)
                {
                    palette.Entries[i] = Color.FromArgb(i, i, i);
                }
                bitmap.Palette = palette;
            }
            //锁定数据区
            BitmapData bd = bitmap.LockBits(new Rectangle(0, 0, tpImage.iWidth, tpImage.iHeight),
                ImageLockMode.WriteOnly, format);
            try
            {
                int pd = ((tpImage.iWidth * tpImage.iChannels) + 3) / 4 * 4;
                long bytesToCopy = tpImage.iWidth * tpImage.iChannels;
                for (int y = 0; y < tpImage.iHeight; y++)
                {
                    long offsetSrc = (y * tpImage.iWidth * tpImage.iChannels);
                    long offsetDst = (y * pd);
                    Buffer.MemoryCopy((byte*)(tpImage.vpImage.ToPointer()) + offsetSrc, (byte*)(bd.Scan0.ToPointer()) + offsetDst, bytesToCopy, bytesToCopy);
                }
            }
            finally
            {
                bitmap.UnlockBits(bd);
            }
            return bitmap;
        }

    }
}