LabelMachine.claclabel.cs 13.0 KB
using CodeLibrary;
using Newtonsoft.Json;
using OnlineStore.Common;
using OnlineStore.LoadCSVLibrary;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DeviceLibrary
{
    public partial class LabelMachine
    {
        SolidBrush blue = new SolidBrush(Color.BlueViolet);
        SolidBrush red = new SolidBrush(Color.Red);
        SolidBrush yellow = new SolidBrush(Color.Yellow);
        SolidBrush AliceBlue = new SolidBrush(Color.AliceBlue);
        Font font = new Font(FontFamily.GenericSansSerif, 60);
        Pen Greenpen = new Pen(Color.Green, 10);
        //Size pointsize = new Size(15, 15);
        int pointsize = 16;
        /// <summary>
        /// 计算贴标位置
        /// </summary>
        /// <param name="Label_Pix_Point">二维码坐标</param>
        /// <returns>XY轴贴标点,R轴角度,是否反转标签</returns>
        public (Point, double, bool) ClacLabel(Point Label_Pix_Point)
        {
            bool ReverseLabel = false;
            int Right_Batch_X = Config.Right_Batch_X;
            if (MoveInfo.ReelParam.PlateW == 13)
            {
                Right_Batch_X = Right_Batch_X + Config.Label_Offset_Pixel_13;
            }
            else if (MoveInfo.ReelParam.PlateW == 15)
            {
                Right_Batch_X = Right_Batch_X + Config.Label_Offset_Pixel_15;
            }
            //照片中料盘中心点像素位置
            Point Center_Pix_Point = new Point(Right_Batch_X, Config.Right_Batch_Y);
            //二维码坐标
            //Point Label_Pix_Point = new Point(X, Y);
            //中心点到二维码角度,右侧为0度,+180转换到左侧为0度
            var angle = Common.getAngle(Center_Pix_Point, Label_Pix_Point) + 180;
            //中心点到二维码距离
            var distance = Common.distance(Center_Pix_Point, Label_Pix_Point);
            //中心点到标签中心的角度
            double rr = 20;
            var lr = Math.Cos(rr * Math.PI / 180);
            //中心点到标签中心的距离
            var ll = lr * distance;
            //标签中心到盘心的坐标
            var labelCenterAngle = rr + angle;
            if (labelCenterAngle < 0)
                labelCenterAngle = 360 + labelCenterAngle;
            //标签中心的坐标
            var labelCenter = Common.PointWithAngle(Center_Pix_Point, labelCenterAngle - 180, ll);
            /*
            //从二维码坐标开始, 往中心点坐标推移一定的距离,获得推移后的坐标
            Point AxisPixPoint = Common.PointWithAngle(Label_Pix_Point, angle, Config.Label_R_Offset_Pixel);

            //匹配角度与贴标旋转轴的角度差
            var labelAngle = angle - Config.Label_R_Angle_Diff+360;
            if (labelAngle > 360)
                labelAngle -= 360;            
            */
            //因为标签不统一暂时改为以二维码为中心贴标
            labelCenter = Label_Pix_Point;
            labelCenterAngle = angle;

            //贴标位置轴的像素坐标
            Point AxisPixPoint = Common.PointWithAngle(labelCenter, labelCenterAngle, Config.Label_R_Offset_Pixel);
            //计算贴标角度的脉冲值
            //if (labelCenterAngle > Config.Label_R_MaxAngle)
            //{
            //    ReverseLabel = true;
            //    labelCenterAngle -= 180;
            //}
            int labelAxisPos = (int)((double)Config.Label_R_360 / 335 * (double)labelCenterAngle);
            MoveInfo.log($"计算结果,Label_R_360:{Config.Label_R_360},贴标角度:{labelCenterAngle},R轴:{labelAxisPos}");
            //计算贴标像素点位与图像中心点的差
            Point p1 = new Point(AxisPixPoint.X - Config.Right_Batch_X, AxisPixPoint.Y - Center_Pix_Point.Y);

            //计算像素*脉冲像素比得到脉冲值+中心点基准脉冲
            var x = (int)(p1.X * Config.Cam_Pixel_X_Ratio) + Config.Label_X_Base;
            var y = (int)(p1.Y * Config.Cam_Pixel_Y_Ratio) + Config.Label_Y_Base;
            p1.X = x;
            p1.Y = y;
            MoveInfo.log($"计算结果,图像像素中心{Center_Pix_Point},二维码像素坐标{Label_Pix_Point},角度{angle},贴标角度{labelCenterAngle},贴标像素点位为{AxisPixPoint},轴点位为{p1},R轴{labelAxisPos},盘宽{MoveInfo.ReelParam.PlateW}");
            if (saveLabelDebugBmp)
            {
                //IOMove(IO_Label_Type.Camera_Led, IO_VALUE.HIGH);
                //Task.Delay(10).Wait();
                Bitmap bitmap = Camera._cam.GrabOneImage(Config.CameraName);
                //IOMove(IO_Label_Type.Camera_Led, IO_VALUE.LOW);
                bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone);
                //Bitmap bitmap = new Bitmap("d:\\出料模块-20210424-043753-0162.bmp");
                printLabelDebugBitmap(bitmap, Label_Pix_Point, Center_Pix_Point, AxisPixPoint, angle, p1, labelCenterAngle, labelAxisPos, labelCenter);
                bitmap.Dispose();
            }
            return (p1, labelAxisPos, ReverseLabel);
        }
        void printLabelDebugBitmap(Bitmap srcbitmap, Point Label_Pix_Point, Point Center_Pix_Point, Point AxisPixPoint, double angle, Point AxisP1, double labelAngle, double labelAxisPos, Point labelCenter)
        {


            Bitmap bitmap = new Bitmap(srcbitmap.Width, srcbitmap.Height, PixelFormat.Format32bppArgb);
            Graphics g = Graphics.FromImage(bitmap);
            

            g.DrawImage(srcbitmap, 0, 0);
            srcbitmap.Dispose();
            g.FillEllipse(blue, Common.EllipseCenter(Label_Pix_Point, pointsize));
            g.FillEllipse(yellow, Common.EllipseCenter(Center_Pix_Point, pointsize));
            g.FillEllipse(red, Common.EllipseCenter(AxisPixPoint, pointsize));
            g.FillEllipse(AliceBlue, Common.EllipseCenter(labelCenter, pointsize));

            g.DrawLine(Greenpen, AxisPixPoint, Label_Pix_Point);
            g.DrawString($"angle:{angle}", font, blue, 0, 0);
            g.DrawString($"AxisP1:{AxisP1}", font, red, 0, 80);
            g.DrawString($"labelAngle:{labelAngle}/{labelAxisPos}", font, red, 0, 160);

            g.Save();
            Directory.CreateDirectory("/image/LabelDebug/");
            bitmap.Save("/image/LabelDebug/" + DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss") + ".jpg", ImageFormat.Jpeg);
            g.Dispose();

        }

        NamedPipeClient namedPipeClient = new NamedPipeClient("OcrService", ".");
        /// <summary>
        /// 计算贴标位置
        /// </summary>
        /// <param name="Label_Pix_Point">二维码坐标</param>
        /// <returns>XY轴贴标点,R轴角度,是否反转标签</returns>
        public (Point, double, bool) ClacLabel2(Point Label_Pix_Point, Bitmap bitmap, ReelParam reelParam)
        {
            OcrProcess.Run();
            Point qrcenter = Label_Pix_Point;
            //string file = @"D:\853string\Image_20210604173619489.bmp";
            //图像剪切范围矩形
            var orgCrop = Rectangle.Inflate(new Rectangle(qrcenter, new Size(1, 1)), ConfigHelper.Config.Get("LabelCutSize",560), ConfigHelper.Config.Get("LabelCutSize", 560));
            //计算剪切后的二维码中心坐标点
            qrcenter.X = qrcenter.X - orgCrop.X;
            qrcenter.Y = qrcenter.Y - orgCrop.Y;
            ///var bitmap = new Bitmap(file);
            var b1 = Common.ImageCrop(bitmap, orgCrop);
            //pictureBox1.Image = b1;// crop(bitmap, new Rectangle(0,0,bitmap.Width,bitmap.Height));
            bitmap.Dispose();
            Directory.CreateDirectory("/image/LabelDebug/");
            string filename = "/image/LabelDebug/" + reelParam.ReeID + "-" + DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss") + ".temp.bmp";
            b1.Save(filename);
            //调用算法服务
            var resp = namedPipeClient.Request(filename);
            MoveInfo.log($"贴标OCR file:{filename}, 计算结果:" + resp);
            //File.Delete(file + ".temp.bmp");
            var l = JsonConvert.DeserializeObject<List<TextBlock>>(resp);
            List<TextBlock> newlist = new List<TextBlock>();
            //过滤合规数据
            foreach (var t in l.ToArray())
            {
                //Console.WriteLine(Sim(t.Text, "PN+VC63.33034.L0L-018139"));
                var s1 = Common.Sim(t.Text.Length >= 27 ? t.Text.Substring(0, 27) : t.Text, "PN+VC:"+ reelParam.PN);
                var s2 = Common.Sim(t.Text.Length >= 6 ? t.Text.Substring(0, 6) : t.Text, "PN+VC:");
                var s3 = Common.Sim(t.Text.Length >= 7 ? t.Text.Substring(0, 7) : "", "VPN:RTL");
                MoveInfo.log($"text:{t.Text}");
                MoveInfo.log($"s1:{s1}, s2:{s2}, s3:{s3}");
                if ((s1 > 0.7 || s2 > 0.9) && s3 < 0.7 && t.Text.Length < 33)
                {
                    newlist.Add(t);
                    MoveInfo.log($"s1:{s1}, s2:{s2} , {t.Text}");
                }
                if (s1 > 0.9)
                {
                    newlist.Clear();
                    newlist.Add(t);
                    MoveInfo.log($"s1:{s1}>0.93 , {t.Text}");
                    break;
                }
            }
            //List<Point> RightPoint
            Point labelPoint = Point.Empty;
            double labelAngle = 0;
            double lastDistance = 0;
            TextBlock lasttextBlock = new TextBlock();
            if (newlist.Count == 0)
            {
                MoveInfo.log($"贴标OCR 筛选结果失败");
                return ClacLabel(Label_Pix_Point);
            }
            MoveInfo.log($"贴标OCR 筛选结果:" + JsonConvert.SerializeObject(newlist));
            Graphics graphics = Graphics.FromImage(b1);
            graphics.FillEllipse(AliceBlue, Common.EllipseCenter(qrcenter,pointsize));

            foreach (var lp in newlist)
            {
                //textBox1.Text += JsonConvert.SerializeObject(lp) + "\r\n";
                //字符起始位置左下角定位点
                var sp = lp.BoxPoints;

                var (dc, topindex) = Common.DistanceWithBoxAndPoint(sp, qrcenter);

                if (dc > lastDistance)
                {
                    lastDistance = dc;
                    lasttextBlock = lp;
                    var lf = (topindex == 0) ? 3 : topindex - 1;//左下角点位
                    var ld = (lf == 0) ? 3 : lf - 1;//横向点位

                    labelPoint = sp[lf];
                    labelAngle = Common.getAngle(sp[lf], sp[ld]) + 90;
                }


                for (int i = 0; i < lp.BoxPoints.Count; i++)
                {
                    if (i == 0)
                        graphics.FillEllipse(blue, Common.EllipseCenter(lp.BoxPoints[i], pointsize));
                    else
                        graphics.FillEllipse(red, Common.EllipseCenter(lp.BoxPoints[i], pointsize));
                }                
            }
            graphics.FillEllipse(yellow, Common.EllipseCenter(labelPoint, pointsize) );
            MoveInfo.log($"贴标OCR lasttextBlock:" + JsonConvert.SerializeObject(lasttextBlock));
            //graphics.FillEllipse(red, new Rectangle(lc.X, lc.Y, pointsize.Width, pointsize.Height));
            //纵向偏移
            labelPoint = Common.PointWithAngle(labelPoint, labelAngle, Config.Label_Offset_Y);
            //横向偏移
            labelPoint = Common.PointWithAngle(labelPoint, labelAngle - 90, Config.Label_Offset_X);
            graphics.FillEllipse(yellow, Common.EllipseCenter(labelPoint, pointsize));
            graphics.Save();
            graphics.Dispose();
            b1.Save(filename+".result.jpg",ImageFormat.Jpeg);
            b1.Dispose();

            if (labelAngle < 0)
                labelAngle = 360 + labelAngle;

            //计算贴标角度的脉冲值
            if (labelAngle > Config.Label_R_MaxAngle)
            {
                if (labelAngle > Config.Label_R_MaxAngle + (360 - labelAngle) / 2)
                    labelAngle = 0;
                else
                    labelAngle = Config.Label_R_MaxAngle;
            }

            int labelAxisPos = (int)((double)Config.Label_R_360 / Config.Label_R_MaxAngle * (double)labelAngle);
            //换算为剪切前的像素位置
            labelPoint.Offset(orgCrop.X, orgCrop.Y);

           
            //计算贴标像素点位与图像中心点的差
            Point p2 = new Point(labelPoint.X - Config.Right_Batch_X, labelPoint.Y - Config.Right_Batch_Y);
            //MoveInfo.log($"计算结果,Label_R_360:{Config.Label_R_360},贴标角度:{labelAngle},R轴:{labelAxisPos},贴标计算像素位置:{labelPoint},换算全图像素位置:{p1}");

            //计算像素*脉冲像素比得到脉冲值+中心点基准脉冲
            var x = (int)(p2.X * Config.Cam_Pixel_X_Ratio) + Config.Label_X_Base;
            var y = (int)(p2.Y * Config.Cam_Pixel_Y_Ratio) + Config.Label_Y_Base;
            Point p1 = new Point(x, y);
            MoveInfo.log($"计算结果,Label_R_360:{Config.Label_R_360},贴标角度:{labelAngle},R轴:{labelAxisPos},贴标计算像素位置:{p2},换算伺服脉冲位置:{p1}");

            return (p1, labelAxisPos, false);
        }
    }
}