CameraPointTest.cs 13.6 KB
using CodeLibrary;
using Newtonsoft.Json;
using OnlineStore.Common;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace DeviceLibrary
{
    [Serializable]
    public enum TestStorePointPort {
       入口, 出口, 上层左侧, 上层右侧, 下层左侧, 下层右侧,贴标
    }
    [Serializable]
    public class tstoredata {
        public string name="";
        public List<int> value = new List<int>();
    }
    public class CameraPointTest
    {
        static CameraData CameraData;
        public static Dictionary<TestStorePointPort, List<string>> StoreState = new Dictionary<TestStorePointPort, List<string>>();
        public static void Init()
        {
            var fd = File.ReadAllText("Config\\CameraPointTest.json");
            CameraData = JsonConvert.DeserializeObject<CameraData>(fd);
            for (int i = 0; i < 5; i++)
            {
                inArea.Add(new tstoredata());
                inArea[i].name = "L" + ((char)(0x41 + i)).ToString();
                for (int j = 0; j < 4; j++)
                {
                    inArea[i].value.Add(-1);
                }
            }
            for (int i = 0; i < 5; i++)
            {
                outArea.Add(new tstoredata());
                outArea[i].name = "U" + ((char)(0x41 + i)).ToString();
                outArea[i].value.Add(-1);                
            }
        }
        public static event EventHandler<Bitmap> TestStorePointEvent;

        public static List<tstoredata> inArea = new List<tstoredata>();
        public static List<tstoredata> outArea = new List<tstoredata>();
        public static List<string> GetThingStoreName(TestStorePointPort tp,bool TestHas=true) {
            //var tl = Test(tp);
            try
            {
                int startindex = 0;
                List<string> haslistStoreName = new List<string>();
                List<int> haslistindex;
                switch (tp)
                {
                    case TestStorePointPort.入口:
                        startindex = RobotManage.AllPositionMapNumList.IndexOf("LA1");
                        haslistindex = TestStorePoint(RobotManage.CameraA.GetImage(0), TestStorePointPort.入口);
                        int index = 0;
                        for (int i = 0; i < 5; i++) {
                            for (int j = 0; j < 4; j++)
                            {
                                inArea[i].value[j]=haslistindex[index];
                                index++;
                            }
                        }
                        break;
                    case TestStorePointPort.出口:
                        startindex = RobotManage.AllPositionMapNumList.IndexOf("UA1");
                        haslistindex = TestStorePoint(RobotManage.CameraA.GetImage(1), TestStorePointPort.出口);
                        index = 0;
                        for (int i = 0; i < 5; i++)
                        {
                            outArea[i].value[0]=haslistindex[index];
                            index++;
                        }
                        break;
                    case TestStorePointPort.上层左侧:
                        startindex = RobotManage.AllPositionMapNumList.IndexOf("SA1");
                        haslistindex = TestStorePoint(RobotManage.CameraA.GetImage(2), TestStorePointPort.上层左侧);
                        break;
                    case TestStorePointPort.上层右侧:
                        startindex = RobotManage.AllPositionMapNumList.IndexOf("SA1");
                        haslistindex = TestStorePoint(RobotManage.CameraA.GetImage(3), TestStorePointPort.上层右侧);
                        break;
                    case TestStorePointPort.下层左侧:
                        startindex = RobotManage.AllPositionMapNumList.IndexOf("SH1");
                        haslistindex = TestStorePoint(RobotManage.CameraA.GetImage(2), TestStorePointPort.下层左侧);
                        break;
                    case TestStorePointPort.下层右侧:
                        startindex = RobotManage.AllPositionMapNumList.IndexOf("SH7");
                        haslistindex = TestStorePoint(RobotManage.CameraA.GetImage(3), TestStorePointPort.下层右侧);
                        break;
                    default:
                        haslistindex = new List<int>();
                        break;
                }
                if (startindex == -1)
                    return new List<string>();

                for (int i = 0; i < haslistindex.Count; i++)
                {
                    if (haslistindex[i] == 1)
                    {
                        haslistStoreName.Add(RobotManage.AllPositionMapNumList[startindex + i]);
                    }
                }
                //StoreState[TestStorePointPort.入口] = haslistStoreName;
                //LogUtil.info("haslistStoreName:" + string.Join(",", haslistStoreName));
                return haslistStoreName;
            }
            catch (AccessViolationException) { return new List<string>(); }
            catch (Exception ex)
            {
                LogUtil.error("haslistStoreName:" + ex.ToString());
                return new List<string>();
            }
        }
        [HandleProcessCorruptedStateExceptions]
        public static List<int> TestStorePoint(Bitmap bmp, TestStorePointPort tp)
        {

            //TestStorePointEvent?.Invoke(tp, bmp);

            string Name = tp.ToString();
            if (CameraData[Name].ObjectPoint.Count == 0)
            {
                CameraData[Name].ObjectPoint = CalcStoreBMP(CameraData[Name].WCols, CameraData[Name].HLines, CameraData[Name].PointList);
            }

            List<Point> points = CameraData[Name].ObjectPoint;
            if (bmp == null)
                return new List<int>(points.Count);
            
            List<int> haslist = new List<int>();
            BitmapData bd=null;
            try
            {
                bd = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat);
                for (int i = 0; i < points.Count; i++)
                {
                    var p = points[i];
                    p.X = p.X - 8;
                    p.Y = p.Y - 8;
                    var cl = new List<ColorHSV>();
                    for (int j = 0; j < 32; j++)
                    {
                        for (int k = 0; k < 32; k++)
                        {
                            var x = p.X + j;
                            var y = p.Y + k;
                            var addr = y * bd.Stride + x * 4;
                            var cr = Marshal.ReadByte(bd.Scan0, addr + 2);
                            var cg = Marshal.ReadByte(bd.Scan0, addr + 1);
                            var cb = Marshal.ReadByte(bd.Scan0, addr);
                            var hh = ColorHelper.RgbToHsv(new ColorRGB(cr, cg, cb));
                            cl.Add(hh);
                        }
                    }
                    var h = cl.Average(cc => cc.H);
                    var s = cl.Average(cc => cc.S);
                    var v = cl.Average(cc => cc.V);

                    var has = s > CameraData[Name].S && h > 60 && h < 200;
                    haslist.Add(has ? 1 : 0);
                }
            }
            catch (AccessViolationException ex)
            {
                LogUtil.error("TestStorePoint AccessViolationException:" + ex.ToString());
            }catch (Exception ex)
            {
                LogUtil.error("TestStorePoint:" + ex.ToString());
            }
            finally
            {
                if (bd!=null)
                    bmp.UnlockBits(bd);
            }
            //Size pointsize = new Size(30, 30);
            SolidBrush red = new SolidBrush(Color.Red);
            SolidBrush gray = new SolidBrush(Color.Gray);
            try
            {
                var g = Graphics.FromImage(bmp);
                for (int i = 0; i < CameraData[Name].ObjectPoint.Count; i++)
                {
                    g.FillEllipse(haslist[i] == 1 ? red : gray, GetCR(CameraData[Name].ObjectPoint[i], 30));
                }
                g.Save();
                bmp.Save(tp.ToString() + ".bmp");
            }
            catch (Exception ex)
            {
                LogUtil.error("TestStorePoint:" + ex.ToString());
            }
            TestStorePointEvent?.Invoke(tp, bmp);
            return haslist;
        }
        /// <summary>
        /// 按中心点扩展一个矩形区域
        /// </summary>
        /// <param name="point"></param>
        /// <param name="size"></param>
        /// <returns></returns>
        static Rectangle GetCR(Point point,int size) {

            return new Rectangle(point.X - size / 2, point.Y - size / 2, size, size);
        }
        /// <summary>
        /// 获取库位像素点位
        /// </summary>
        /// <param name="w"></param>
        /// <param name="h"></param>
        /// <param name="points"></param>
        /// <returns></returns>
        static List<Point> CalcStoreBMP(int w, int h, List<Point> points)
        {

            List<Point> StorePoint = new List<Point>();
            

            //var g = Graphics.FromImage(bmp);

            var la = Common.getAngle(points[0], points[3]);
            var ld = Common.distance(points[0], points[3]);
            var ra = Common.getAngle(points[1], points[2]);
            var rd = Common.distance(points[1], points[2]);
            for (int j = 0; j < h; j++)
            {
                var pa = Common.PointWithAngle(points[0], la, ld / (h - 1) * j);
                var pb = Common.PointWithAngle(points[1], ra, rd / (h - 1) * j);
                var ag = Common.getAngle(pa, pb);
                var ad = Common.distance(pa, pb);
                for (int i = 0; i < w; i++)
                {
                    if (ad == 0)
                        StorePoint.Add(pa);
                    else
                    {
                        var p = Common.PointWithAngle(pa, ag, ad / (w - 1) * i);
                        StorePoint.Add(p);
                    }
                    //g.FillEllipse(red, new Rectangle(p, pointsize));
                }
            }

            //g.Save();
            //bmp.Save(@"D:\rick\vs\SO20031_TinStorage\料架照片\1.bmp");
            return StorePoint;
        }

        public static bool ScanRectangle() {
            var r = CameraData[TestStorePointPort.贴标.ToString()].PointList;
            Point Start = r[0];
            Point End = r[1];
            int width = End.X - Start.X;
            int height = End.Y - Start.Y;
            LogUtil.info($"开始扫描绿色区域:{Start},{width}x{height}");
            var bmp = Camera._cam.GrabOneImage(CodeManager.hikNameList[0], PixelType.RGB8);
            //var bmp = new Bitmap("Image_20221208134139341.bmp");
            var bd = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, bmp.PixelFormat);
            int HeightCount = 0;
            int errlinecount = 0;
            try {
                
                for (int i = 0; i < height; i=i+2)
                {
                    int linecount = 0;
                    
                    for (int j = 0; j < width; j=j+3)
                    {
                        var x = Start.X+ j;
                        var y = Start.Y + height - i;
                        var addr = y * bd.Stride + x * 3;
                        var cr = Marshal.ReadByte(bd.Scan0, addr + 2);
                        var cg = Marshal.ReadByte(bd.Scan0, addr + 1);
                        var cb = Marshal.ReadByte(bd.Scan0, addr);
                        var hh = ColorHelper.RgbToHsv(new ColorRGB(cr, cg, cb));
                        var s = hh.S;
                        var h = hh.H;
                        var has = s > 15 && h > 90 && h < 150;
                        if (has)
                        {
                            linecount++;//本行绿色计数
                            Marshal.WriteByte(bd.Scan0, addr + 2, 0xFF);
                            Marshal.WriteByte(bd.Scan0, addr + 1, 0);
                            Marshal.WriteByte(bd.Scan0, addr, 0);
                        }
                    }
                    if (linecount*3 < width * 0.6)
                    {
                        errlinecount++;
                        HeightCount = 0;
                        if (errlinecount > 60)
                        {
                            return false;
                        }
                        //return HeightCount;
                    }
                    else {
                        HeightCount++;
                        if (HeightCount*2 > 50) {
                            return true;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LogUtil.error("ScanRectangle:" + ex.ToString());
            }
            finally
            {
                bmp.UnlockBits(bd);
                bmp.Save("\\Image\\LabelDebug\\" + DateTime.Now.ToString("yyyyMMddHHmmss") + "-"+ errlinecount +"-"+ HeightCount + ".bmp");
            }            
            return false;
        }
    }
    public class CameraData : Dictionary<string, CameraPointData> { }

    public class CameraPointData
    {
        public int S = 20;
        public int WCols;
        public int HLines;
        public List<Point> PointList = new List<Point>();
        [JsonIgnore]
        public List<Point> ObjectPoint = new List<Point>();
    }
}