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