其他分享
首页 > 其他分享> > emgucv中获取摄像头,并获取一个亮点,同时进行梯形校正

emgucv中获取摄像头,并获取一个亮点,同时进行梯形校正

作者:互联网

emguv的版本为3.4.3

using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.CV.Util;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;

namespace SimulateShootCheck
{
    class CameraBase
    {
        //二值化阈值
        public int binarizationThreshold;

        //四个真实的点
        private PointF p1;
        private PointF p2;
        private PointF p3;
        private PointF p4;
        //射击的击中点
        private PointF nt1 = new PointF(80, 1000);
        private PointF[] needTransPointF1 = new PointF[1];//将击中的坐标传入这个数组才能进行梯形校正

        private RotatedRect rotatedRect;     //计算外接椭圆
        private Point rcenter;//外接椭圆的中心点
        private Point rcenter_First;//第一个外界椭圆的中心点
        protected PointF result;//返回的击中点

        private bool isActive;//这个摄像头是否被激活
        private float waitTime;//协程等待的时间
        protected Timer timer  ;//计时器
        protected bool canCkeck = false;//可以检测击中点

        string msg; //发送的消息

        /// <summary>
        /// 获取击中点
        /// </summary>
        /// <param name="img">用于获取摄像头画面的mat</param>
        /// <param name="windowName">弹出的窗口的名字</param>
        /// <param name="cap">被捕获的摄像机</param>
        protected void HitCheck(Mat img, string windowName, VideoCapture cap)
        {

            if (cap == null)
            {
                return;
            }
            cap.Read(img);
            if (img.IsEmpty)
            {
                Console.WriteLine("未检测到图像");
            }

            //获取灰度图
            CvInvoke.CvtColor(img, img, ColorConversion.Bgr2Gray);
            //二值化
            CvInvoke.Threshold(img, img, binarizationThreshold, 255, ThresholdType.Binary);
            //高亮膨胀,高亮膨胀最好传入一个二值化的图片
            Mat element = CvInvoke.GetStructuringElement(ElementShape.Ellipse, new Size(9, 9), new Point(-1, -1)); //定义膨胀的核,如果element为null,使用以中心为锚点的3*3的矩形为核
            CvInvoke.Dilate(img, img, element, new Point(-1, -1), 1, BorderType.Default, new MCvScalar());
            //通过寻找轮廓的方式,寻找高亮点
            VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
            CvInvoke.FindContours(img, contours, null, RetrType.List, ChainApproxMethod.ChainApproxNone); //只支持灰度图
            //绘制外接椭圆
            for (int i = 0; i < contours.Size; i++)
            {
                if (contours[i].Size > 5)
                {
                    rotatedRect = CvInvoke.FitEllipse(contours[i]);     //计算外接椭圆
                    rcenter = new Point((int)rotatedRect.Center.X, (int)rotatedRect.Center.Y);
                    //记录第一个椭圆的中心
                    if (i == 0)
                    {
                        rcenter_First = new Point((int)rotatedRect.Center.X, (int)rotatedRect.Center.Y);
                    }
                    CvInvoke.Ellipse(img, rcenter, new Size((int)(rotatedRect.Size.Width / 2),
                        (int)(rotatedRect.Size.Height / 2)), rotatedRect.Angle, 0, 360,
                        new MCvScalar(255, 165, 0, 255));
                }
            }
            CvInvoke.Imshow(windowName, img);
            CvInvoke.WaitKey(30);
            //梯形校正
            if (canCkeck)
            {
               needTransPointF1[0] = rcenter_First;
               result = Trans(p1, p2, p3, p4, needTransPointF1);
               Console.WriteLine("转换后的坐标为"+ result);
            }
        }

        /// <summary>
        /// 获取梯形校正后的点
        /// </summary>
        /// <param name="transpoint1">左上角的实际点坐标</param>
        /// <param name="transpoint2">右上角的实际点坐标</param>
        /// <param name="transpoint3">左下角的实际点坐标</param>
        /// <param name="transpoint4">右下角的实际点坐标</param>
        /// <param name="needTransPointF">要转换的坐标点的集合,如果只有一个点,传一个只有一个元素的集合</param>
        /// <returns></returns>
        public PointF Trans(PointF transpoint1, PointF transpoint2, PointF transpoint3, PointF transpoint4, PointF[] needTransPointF)
        {
            //coretP  是已经知道的最终显示画面的四个角点的坐标 数组  顺序为 左上  右上  左下 右下  由

            PointF leftUp = new PointF(0, 0);
            PointF RightUp = new PointF(1920, 0);
            PointF leftnDown = new PointF(0, 1080);
            PointF RightDown = new PointF(1920, 1080);

            PointF[] end = new PointF[] { };
            PointF[] coretP = new PointF[] { leftUp, RightUp, leftnDown, RightDown };

            //是手动点击矫正后的四个角点的坐标 数组  顺序为 左上  右上  左下 右下  由函数外传入
            PointF trap1 = transpoint1;
            PointF trap2 = transpoint2;
            PointF trap3 = transpoint3;
            PointF trap4 = transpoint4;

            PointF[] rec2 = new PointF[4] { transpoint1, transpoint2, transpoint3, transpoint4 };

            Mat Mat = CvInvoke.GetPerspectiveTransform(rec2, coretP);

            end = CvInvoke.PerspectiveTransform(needTransPointF, Mat);
            return end[0];
        }
    }
}

 

1

1

标签:PointF,img,private,获取,emgucv,using,new,摄像头,CvInvoke
来源: https://www.cnblogs.com/wrc-blog/p/14741622.html