FrmOpenCamera.cs 14.1 KB
using CameraVisionLib.Model;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Asa.Camera
{
    public partial class FrmOpenCamera : Form
    {
        private int id;
        private string cameraName;
        private List<RegionPlan> cameraPlan;
        private int planIndex;
        private int regionIndex;
        private float zoom = 0.5f;
        private Bitmap bmp;
        private Point oldPoint;
        private FieldMargin fieldMargin = FieldMargin.Outside;

        private const int FIELD_MARGIN = 5;
        private readonly Font TEXT_FONT = new("宋体", 12f);

        internal FrmOpenCamera()
        {
            InitializeComponent();
        }

        internal FrmOpenCamera(string name) : this()
        {
            id = 0;
            cameraName = name;
            planIndex = -1;
            regionIndex = -1;

            if (Common.visionLib.regionLists.TryGetValue(name, out cameraPlan))
            {
                for (int i = 0; i < cameraPlan.Count; i++)
                    LstPlan.Items.Add(cameraPlan[i].Name);
            }

            Common.visionLib.Open(name);
            bmp = Common.visionLib.GetImage(name);
            NudZoom.Value = (decimal)zoom;
        }




        private void ChangeNameRatio()
        {
            if (regionIndex == -1)
            {
                TxtName.Text = "";
                NudRatio.Value = 0;
            }
            else
            {
                TxtName.Text = cameraPlan[planIndex].Info[regionIndex].Name;
                NudRatio.Value = Convert.ToDecimal(cameraPlan[planIndex].Info[regionIndex].Region.Ratio);
            }
        }

        private void FindFieldMargin(Point pt)
        {
            fieldMargin = FieldMargin.Outside;
            
            RectangleF rect = new(cameraPlan[planIndex].Info[regionIndex].Region.X * zoom, cameraPlan[planIndex].Info[regionIndex].Region.Y * zoom, cameraPlan[planIndex].Info[regionIndex].Region.Width * zoom, cameraPlan[planIndex].Info[regionIndex].Region.Height * zoom);

            if (Math.Abs(rect.X - pt.X) < FIELD_MARGIN)
            {
                if (Math.Abs(rect.Y - pt.Y) < FIELD_MARGIN)
                    fieldMargin = FieldMargin.LeftTop;
                else if (Math.Abs(pt.Y - rect.Y - rect.Height) < FIELD_MARGIN)
                    fieldMargin = FieldMargin.LeftBottom;
                else if (pt.Y > rect.Y && pt.Y < rect.Y + rect.Height)
                    fieldMargin = FieldMargin.Left;
            }
            else if (Math.Abs(rect.X + rect.Width - pt.X) < FIELD_MARGIN)
            {
                if (Math.Abs(rect.Y - pt.Y) < FIELD_MARGIN)
                    fieldMargin = FieldMargin.RightTop;
                else if (Math.Abs(pt.Y - rect.Y - rect.Height) < FIELD_MARGIN)
                    fieldMargin = FieldMargin.RightBottom;
                else if (pt.Y > rect.Y && pt.Y < rect.Y + rect.Height)
                    fieldMargin = FieldMargin.Right;
            }
            else if (pt.X > rect.X && pt.X < rect.X + rect.Width)
            {
                if (Math.Abs(rect.Y - pt.Y) < FIELD_MARGIN)
                    fieldMargin = FieldMargin.Top;
                else if (Math.Abs(pt.Y - rect.Y - rect.Height) < FIELD_MARGIN)
                    fieldMargin = FieldMargin.Bottom;
                else if (pt.Y > rect.Y && pt.Y < rect.Y + rect.Height)
                    fieldMargin = FieldMargin.Inside;
            }

            switch (fieldMargin)
            {
                case FieldMargin.Left: PicShow.Cursor = Cursors.SizeWE; break;
                case FieldMargin.LeftTop: PicShow.Cursor = Cursors.SizeNWSE; break;
                case FieldMargin.LeftBottom: PicShow.Cursor = Cursors.SizeNESW; break;
                case FieldMargin.Right: PicShow.Cursor = Cursors.SizeWE; break;
                case FieldMargin.RightBottom: PicShow.Cursor = Cursors.SizeNWSE; break;
                case FieldMargin.RightTop: PicShow.Cursor = Cursors.SizeNESW; break;
                case FieldMargin.Top: PicShow.Cursor = Cursors.SizeNS; break;
                case FieldMargin.Bottom: PicShow.Cursor = Cursors.SizeNS; break;
                case FieldMargin.Inside: PicShow.Cursor = Cursors.SizeAll; break;
                case FieldMargin.Outside: PicShow.Cursor = Cursors.Default; break;
            }
        }

        private void ChangeFieldMargin(int x, int y)
        {
            switch (fieldMargin)
            {
                case FieldMargin.Left:
                    cameraPlan[planIndex].Info[regionIndex].Region.X += x;
                    cameraPlan[planIndex].Info[regionIndex].Region.Width -= x;
                    break;
                case FieldMargin.Top:
                    cameraPlan[planIndex].Info[regionIndex].Region.Y += y;
                    cameraPlan[planIndex].Info[regionIndex].Region.Height -= y;
                    break;
                case FieldMargin.Right:
                    cameraPlan[planIndex].Info[regionIndex].Region.Width += x;
                    break;
                case FieldMargin.Bottom:
                    cameraPlan[planIndex].Info[regionIndex].Region.Height += y;
                    break;
                case FieldMargin.LeftTop:
                    cameraPlan[planIndex].Info[regionIndex].Region.X += x;
                    cameraPlan[planIndex].Info[regionIndex].Region.Width -= x;
                    cameraPlan[planIndex].Info[regionIndex].Region.Y += y;
                    cameraPlan[planIndex].Info[regionIndex].Region.Height -= y;
                    break;
                case FieldMargin.RightTop:
                    cameraPlan[planIndex].Info[regionIndex].Region.Y += y;
                    cameraPlan[planIndex].Info[regionIndex].Region.Height -= y;
                    cameraPlan[planIndex].Info[regionIndex].Region.Width += x;
                    break;
                case FieldMargin.LeftBottom:
                    cameraPlan[planIndex].Info[regionIndex].Region.X += x;
                    cameraPlan[planIndex].Info[regionIndex].Region.Width -= x;
                    cameraPlan[planIndex].Info[regionIndex].Region.Height += y;
                    break;
                case FieldMargin.RightBottom:
                    cameraPlan[planIndex].Info[regionIndex].Region.Width += x;
                    cameraPlan[planIndex].Info[regionIndex].Region.Height += y;
                    break;
                case FieldMargin.Inside:
                    cameraPlan[planIndex].Info[regionIndex].Region.X += x;
                    cameraPlan[planIndex].Info[regionIndex].Region.Y += y;
                    break;
            }
        }

        private void FrmOpenCamera_FormClosing(object sender, FormClosingEventArgs e)
        {
            Common.visionLib.Close();
        }

        private void BtnGrabOne_Click(object sender, EventArgs e)
        {
            bmp = Common.visionLib.GetImage(cameraName);

            //bmp = new Bitmap(@"C:\Neotel\测试图.jpg");
            PicShow.Refresh();
        }

        private void BtnAdd_Click(object sender, EventArgs e)
        {
            if (planIndex == -1) return;

            string name = "name" + ++id;
            RegionInfo info = new(name, 0, 0, 100, 100, 0.3f);
            cameraPlan[planIndex].Info.Add(info);
            regionIndex = cameraPlan[planIndex].Info.Count - 1;
            ChangeNameRatio();
            PicShow.Refresh();
        }

        private void BtnDel_Click(object sender, EventArgs e)
        {
            if (regionIndex == -1) return;
            if (planIndex == -1) return;

            cameraPlan[planIndex].Info.RemoveAt(regionIndex);
            regionIndex = cameraPlan[planIndex].Info.Count == 0 ? -1 : 0;
            ChangeNameRatio();
            PicShow.Refresh();
        }

        private void TxtName_TextChanged(object sender, EventArgs e)
        {
            if (regionIndex == -1) return;
            cameraPlan[planIndex].Info[regionIndex].Name = TxtName.Text;
            PicShow.Refresh();
        }

        private void NudRatio_ValueChanged(object sender, EventArgs e)
        {
            if (regionIndex == -1) return;
            cameraPlan[planIndex].Info[regionIndex].Region.Ratio = (float)NudRatio.Value;
            //PicShow.Refresh();
        }

        private void NudZoom_ValueChanged(object sender, EventArgs e)
        {
            zoom = (float)NudZoom.Value;
            PicShow.Refresh();
        }

        private void BtnOK_Click(object sender, EventArgs e)
        {
            DialogResult = DialogResult.OK;
        }

        private void PicShow_MouseDown(object sender, MouseEventArgs e)
        {
            if (planIndex == -1) return;
            if (e.Button != MouseButtons.Left) return;
            oldPoint = e.Location;
            if (fieldMargin != FieldMargin.Outside) return;

            float x = e.X / zoom;  //放大到正常大小
            float y = e.Y / zoom;  //放大到正常大小
            regionIndex = cameraPlan[planIndex].Info.FindIndex(match => match.Region.X < x && match.Region.Y < y && match.Region.X + match.Region.Width > x && match.Region.Y + match.Region.Height > y);
            ChangeNameRatio();
            if (regionIndex > -1)
                FindFieldMargin(e.Location);
            PicShow.Refresh();
        }

        private void PicShow_MouseMove(object sender, MouseEventArgs e)
        {
            if (regionIndex == -1) return;

            if (e.Button == MouseButtons.Left)
            {
                int x = Convert.ToInt32((e.X - oldPoint.X) / zoom);
                int y = Convert.ToInt32((e.Y - oldPoint.Y) / zoom);
                ChangeFieldMargin(x, y);
                oldPoint = e.Location;
                PicShow.Refresh();
            }
            else if (e.Button == MouseButtons.None)
            {
                FindFieldMargin(e.Location);
            }
        }

        private void PicShow_MouseUp(object sender, MouseEventArgs e)
        {

        }

        private void PicShow_Paint(object sender, PaintEventArgs e)
        {
            if (bmp == null) return;
            RectangleF destRect = new(0, 0, bmp.Width * zoom, bmp.Height * zoom);
            RectangleF srcRect = new(0, 0, bmp.Width, bmp.Height);
            e.Graphics.DrawImage(bmp, destRect, srcRect, GraphicsUnit.Pixel);

            if (planIndex < 0) return;
            List<RegionInfo> info = cameraPlan[planIndex].Info;
            float x, y, width, height;
            for (int i = 0; i < info.Count; i++)
            {
                x = info[i].Region.X * zoom;
                y = info[i].Region.Y * zoom;
                width = info[i].Region.Width * zoom;
                height = info[i].Region.Height * zoom;
                string s = info[i].Name;
                SizeF sf = e.Graphics.MeasureString(s, TEXT_FONT);
                e.Graphics.FillRectangle(Brushes.White, x, y - sf.Height, sf.Width, sf.Height);
                e.Graphics.DrawString(s, TEXT_FONT, Brushes.Black, x, y - sf.Height);

                if (i == regionIndex)
                {
                    e.Graphics.DrawRectangle(Pens.Red, x, y, width, height);
                    //4个角的矩形
                    e.Graphics.FillRectangle(Brushes.White, x - FIELD_MARGIN, y - FIELD_MARGIN, FIELD_MARGIN, FIELD_MARGIN);
                    e.Graphics.FillRectangle(Brushes.White, x + width, y - FIELD_MARGIN, FIELD_MARGIN, FIELD_MARGIN);
                    e.Graphics.FillRectangle(Brushes.White, x - FIELD_MARGIN, y + height, FIELD_MARGIN, FIELD_MARGIN);
                    e.Graphics.FillRectangle(Brushes.White, x + width, y + height, FIELD_MARGIN, FIELD_MARGIN);
                    e.Graphics.DrawRectangle(Pens.Black, x - FIELD_MARGIN, y - FIELD_MARGIN, FIELD_MARGIN, FIELD_MARGIN);
                    e.Graphics.DrawRectangle(Pens.Black, x + width, y - FIELD_MARGIN, FIELD_MARGIN, FIELD_MARGIN);
                    e.Graphics.DrawRectangle(Pens.Black, x - FIELD_MARGIN, y + height, FIELD_MARGIN, FIELD_MARGIN);
                    e.Graphics.DrawRectangle(Pens.Black, x + width, y + height, FIELD_MARGIN, FIELD_MARGIN);
                }
                else
                {
                    e.Graphics.DrawRectangle(Pens.LimeGreen, x, y, width, height);
                }

            }

        }


        private enum FieldMargin
        {
            Outside,
            Inside,
            Left,
            Top,
            Right,
            Bottom,
            LeftTop,
            RightTop,
            LeftBottom,
            RightBottom
        }

        private void FrmOpenCamera_Load(object sender, EventArgs e)
        {

        }

        private void LstPlan_SelectedIndexChanged(object sender, EventArgs e)
        {
            planIndex = LstPlan.SelectedIndex;
            regionIndex = -1;
            PicShow.Refresh();
        }

        private void BtnAddPlan_Click(object sender, EventArgs e)
        {
            string name = Microsoft.VisualBasic.Interaction.InputBox("输入名称");
            if (string.IsNullOrWhiteSpace(name)) return;
            RegionPlan plan = new RegionPlan(name);
            cameraPlan.Add(plan);
            LstPlan.Items.Add(name);
            LstPlan.SelectedIndex = cameraPlan.Count - 1;
        }

        private void BtnDelPlan_Click(object sender, EventArgs e)
        {
            if (planIndex == -1) return;
            DialogResult dr = MessageBox.Show("删除" + LstPlan.Text, "", MessageBoxButtons.YesNo);
            if (dr == DialogResult.No) return;
            cameraPlan.RemoveAt(planIndex);
            LstPlan.Items.RemoveAt(planIndex);
            planIndex = -1;
            if (LstPlan.Items.Count > 0)
                LstPlan.SelectedIndex = 0;
        }

        private void BtnRenamePlan_Click(object sender, EventArgs e)
        {
            if (planIndex == -1) return;
            string name = Microsoft.VisualBasic.Interaction.InputBox(LstPlan.Text + " 重命名为");
            if (string.IsNullOrWhiteSpace(name)) return;
            cameraPlan[planIndex].Name = name;

            int temp = planIndex;
            LstPlan.Items.RemoveAt(planIndex);
            LstPlan.Items.Insert(temp, name);
            LstPlan.SelectedIndex = temp;
        }
    }
}