Beispiel #1
0
        public double GetCellLengthWithBoundingBoxPoint(VectorOfPoint contour)
        {
            var tempRect  = CvInvoke.MinAreaRect(contour);
            var boxPoints = CvInvoke.BoxPoints(tempRect);

            return(GetCellLengthFromBoxPoints(boxPoints));
        }
Beispiel #2
0
        /// <summary>
        /// 获取机器人法兰中心移动坐标和旋转角度,camera=0代表右侧相机,camera=1代表前方向机
        /// </summary>
        /// <param name="bitmap">产品图像</param>
        /// <param name="cameraID">相机编号</param>
        public ImageInfo GetProductParamters(Bitmap bitmap, int cameraID, int spongeH)
        {
            ImageInfo            imageInfo      = new ImageInfo();
            List <VectorOfPoint> imageContours  = GetContours(bitmap, cameraID, spongeH);
            VectorOfPoint        productContour = imageContours.Max();
            MCvMoments           cvMoments      = CvInvoke.Moments(productContour, false);
            int gravityX = Convert.ToInt32(cvMoments.M10 / cvMoments.M00);
            int gravityY = Convert.ToInt32(cvMoments.M01 / cvMoments.M00);

            Trace.WriteLine("用矩计算质心:X = " + gravityX.ToString() + "\tY = " + gravityY.ToString());
            if (productContour != null)
            {
                var      minRect = CvInvoke.MinAreaRect(productContour); //最小外接矩形
                PointF[] pt      = CvInvoke.BoxPoints(minRect);          //最小外接矩形四个角点

                PointF po = minRect.Center;                              //最小外接矩形中心
                Trace.WriteLine("当前外接矩形中心:" + po.ToString());
                imageInfo.CenterOfImg = po;

                //长轴,短轴,倾角计算:
                //AxisLong =  Math.Sqrt(Math.Pow(pt[1].X - pt[0].X, 2) + Math.Pow(pt[1].Y - pt[0].Y, 2));
                imageInfo.AxisLong = minRect.Size.Width > minRect.Size.Height ? minRect.Size.Width : minRect.Size.Height;
                //AxisShort =  Math.Sqrt(Math.Pow(pt[2].X - pt[1].X, 2) + Math.Pow(pt[2].Y - pt[1].Y, 2));
                imageInfo.AxisShort    = minRect.Size.Height <= minRect.Size.Width ? minRect.Size.Height : minRect.Size.Width;;
                imageInfo.ImageCorner  = pt;
                imageInfo.RotatedAngle = Math.Abs(minRect.Angle) > 45?minRect.Angle + 90:minRect.Angle;

                Matrix <double> imgCenter = new Matrix <double>(3, 1)
                {
Beispiel #3
0
        public void SaveImgWithContours(Point point)
        {
            var imgToSave = Image;

            foreach (var contour in Contours.ToArrayOfArray())
            {
                var tempVector = new VectorOfPoint(contour);
                CvInvoke.DrawContours(imgToSave, tempVector, 0, new MCvScalar(0, 255, 0), 2);
                var tempRect = CvInvoke.MinAreaRect(tempVector);
                var box      = CvInvoke.BoxPoints(tempRect);
                var boxVec   = new VectorOfPointF(box);
                CvInvoke.DrawContours(imgToSave, boxVec, 0, new MCvScalar(0, 0, 255), 2);
                if (CvInvoke.PointPolygonTest(tempVector, point, true) >= 0)
                {
                    CvInvoke.PutText(ContourImage, tempRect.Size.Height.ToString(CultureInfo.InvariantCulture),
                                     new Point((int)(10 + boxVec[0].X), (int)(10 + boxVec[0].Y)),
                                     FontFace.HersheySimplex, 0.65, new MCvScalar(255, 100, 100, 255), 2);
                }
            }

            var processedDir = FolderName + Path.DirectorySeparatorChar + "processed";

            if (!Directory.Exists(processedDir))
            {
                Directory.CreateDirectory(processedDir);
            }

            CvInvoke.Imwrite(processedDir + Path.DirectorySeparatorChar + OpenedImgNumber + ".jpg", imgToSave);
        }
Beispiel #4
0
 /// <summary>
 /// Get the minimum enclosing rectangle for this Box
 /// </summary>
 /// <returns>The minimum enclosing rectangle for this Box</returns>
 public System.Drawing.Rectangle MinAreaRect()
 {
     PointF[] data = CvInvoke.BoxPoints(this);
     int minX = (int)Math.Round(Math.Min(Math.Min(data[0].X, data[1].X), Math.Min(data[2].X, data[3].X)));
     int maxX = (int)Math.Round(Math.Max(Math.Max(data[0].X, data[1].X), Math.Max(data[2].X, data[3].X)));
     int minY = (int)Math.Round(Math.Min(Math.Min(data[0].Y, data[1].Y), Math.Min(data[2].Y, data[3].Y)));
     int maxY = (int)Math.Round(Math.Max(Math.Max(data[0].Y, data[1].Y), Math.Max(data[2].Y, data[3].Y)));
     return new Rectangle(minX, minY, maxX - minX, maxY - minY);
 }
Beispiel #5
0
 public void DrawAllCellContourSizes()
 {
     foreach (var contour in Contours.ToArrayOfArray())
     {
         var tempVector = new VectorOfPoint(contour);
         var tempRect   = CvInvoke.MinAreaRect(tempVector);
         var box        = CvInvoke.BoxPoints(tempRect);
         var boxVec     = new VectorOfPointF(box);
         CvInvoke.PutText(ContourImage, tempRect.Size.Height.ToString(CultureInfo.InvariantCulture),
                          new Point((int)(10 + boxVec[0].X), (int)(10 + boxVec[0].Y)),
                          FontFace.HersheySimplex, 0.65, new MCvScalar(255, 100, 100, 255), 2);
     }
 }
        public string FindContourOnRoiFrame(CamService cam)
        {
            var allContours = new VectorOfVectorOfPoint();

            CvInvoke.FindContours(cam.RoiFrame,
                                  allContours,
                                  new Mat(),
                                  RetrType.External,
                                  ChainApproxMethod.ChainApproxNone);

            var contour      = new VectorOfPoint();
            var contourArс   = 0.0;
            var contourArea  = 0.0;
            var contourWidth = 0.0;

            for (var i = 0; i < allContours.Size; i++)
            {
                var tempContour    = allContours[i];
                var tempContourArс = CvInvoke.ArcLength(tempContour, true);
                if (tempContourArс > contourArс)
                {
                    contour    = tempContour;
                    contourArс = tempContourArс;
                }
            }

            if (contourArс > 0)
            {
                contourArea = CvInvoke.ContourArea(contour);
                var rect             = CvInvoke.MinAreaRect(contour);
                var box              = CvInvoke.BoxPoints(rect);
                var contourBoxPoint1 = new PointF(box[0].X, (float)cam.roiPosYSlider + box[0].Y);
                var contourBoxPoint2 = new PointF(box[1].X, (float)cam.roiPosYSlider + box[1].Y);
                var contourBoxPoint4 = new PointF(box[3].X, (float)cam.roiPosYSlider + box[3].Y);
                var side1            = MeasureService.FindDistance(contourBoxPoint1, contourBoxPoint2);
                var side2            = MeasureService.FindDistance(contourBoxPoint4, contourBoxPoint1);

                contourWidth = side1 < side2
                                   ? side1
                                   : side2;
            }

            return(Converter.ToString($"Contour\n" +
                                      $"Arc:\n" +
                                      $"{(int) contourArс}\n" +
                                      $"Area:\n" +
                                      $"{(int) contourArea}\n" +
                                      $"Width:\n" +
                                      $"{(int) contourWidth}\n"
                                      ));
        }
        //void DrawBoxSequance( Image<Bgr , byte> dst, List<RotatedRect> rects , int iterNum)
        //{
        //    if ( rects == null ) return;
        //    dst = dst?.DrawRotatedRect( rects [ iterNum - 1 ] , new Bgr(50,240,10));
        //    if ( iterNum == 0 ) return;
        //    DrawBoxSequance( dst , rects , iterNum - 1 );
        //}

        void DrawBoxSequance(Image <Bgr, byte> dst, List <RotatedRect> rects, int iterNum)
        {
            for (int i = 0; i < rects.Count; i++)
            {
                var points = CvInvoke.BoxPoints(rects [i]);
                var lines  = Enumerable.Range(0, points.GetLength(0))
                             .Select(j =>
                                     new LineSegment2DF(points[j], points [(j + 1) % 4]))
                             .ToArray();
                foreach (var line in lines)
                {
                    dst.Draw(line, new Bgr(50, 240, 10), 2);
                }
            }
        }
Beispiel #8
0
 public double GetCellLengthWithBoundingBoxPoint(Point point)
 {
     foreach (var contour in Boxes.ToArrayOfArray())
     {
         var tempVector = new VectorOfPoint(contour);
         if (!(CvInvoke.PointPolygonTest(tempVector, point, true) >= 0))
         {
             continue;
         }
         var tempRect  = CvInvoke.MinAreaRect(tempVector);
         var boxPoints = CvInvoke.BoxPoints(tempRect);
         return(GetCellLengthFromBoxPoints(boxPoints));
     }
     return(-1.0);
 }
        public static Image <Bgr, TDepth> DrawRotatedRect <TDepth>(
            this Image <Bgr, TDepth> src
            , RotatedRect rect
            , Bgr color)
            where TDepth : new()
        {
            var output = src.Clone();
            var points = CvInvoke.BoxPoints(rect);
            var lines  = Enumerable.Range(0, points.GetLength(0))
                         .Select(i =>
                                 new LineSegment2DF(points[i], points [(i + 1) % 4]))
                         .ToArray()
                         .ActLoop(x => output.Draw(x, color, 2));

            return(output);
        }
Beispiel #10
0
        /// <summary>
        /// 画最小外接矩
        /// </summary>
        private void DrawContourMinRectangle(ContoursArgs e)
        {
            VectorOfPoint cnt         = e.Contours[e.ContourIndex];
            RotatedRect   rotatedRect = CvInvoke.MinAreaRect(cnt);

            PointF[] pointF = CvInvoke.BoxPoints(rotatedRect);
            //取整
            Point[] pointInt = new Point[pointF.Length];
            for (int i = 0; i < pointF.Length; i++)
            {
                pointInt[i] = Point.Round(pointF[i]);
            }

            VectorOfPoint         vector  = new VectorOfPoint(pointInt);
            VectorOfVectorOfPoint vector2 = new VectorOfVectorOfPoint(vector);

            CvInvoke.DrawContours(mTempImage, vector2, -1, e.Color, e.Thickness);
        }
Beispiel #11
0
        private static List <PointF> GetMiniBox(VectorOfPoint contours, out float minEdgeSize)
        {
            List <PointF> box   = new List <PointF>();
            RotatedRect   rrect = CvInvoke.MinAreaRect(contours);

            PointF[] points = CvInvoke.BoxPoints(rrect);
            minEdgeSize = Math.Min(rrect.Size.Width, rrect.Size.Height);

            List <PointF> thePoints = new List <PointF>(points);

            thePoints.Sort(CompareByX);

            int index_1 = 0, index_2 = 1, index_3 = 2, index_4 = 3;

            if (thePoints[1].Y > thePoints[0].Y)
            {
                index_1 = 0;
                index_4 = 1;
            }
            else
            {
                index_1 = 1;
                index_4 = 0;
            }

            if (thePoints[3].Y > thePoints[2].Y)
            {
                index_2 = 2;
                index_3 = 3;
            }
            else
            {
                index_2 = 3;
                index_3 = 2;
            }

            box.Add(thePoints[index_1]);
            box.Add(thePoints[index_2]);
            box.Add(thePoints[index_3]);
            box.Add(thePoints[index_4]);

            return(box);
        }
Beispiel #12
0
        public Mat DrawAllCellContourBoundingBoxes()
        {
            var matToReturn         = ContourImage.CreateNewMatLikeThis();
            var boxVecOfVectorPoint = new VectorOfVectorOfPointF();

            foreach (var contour in Contours.ToArrayOfArray())
            {
                var tempVector = new VectorOfPoint(contour);
                var tempRect   = CvInvoke.MinAreaRect(tempVector);
                var box        = CvInvoke.BoxPoints(tempRect);
                var boxVec     = new VectorOfPointF(box);
                boxVecOfVectorPoint.Push(boxVec);
            }

            var convertedVectorOfVectorPoint = boxVecOfVectorPoint.ConvertToVectorOfPoint();

            CvInvoke.DrawContours(matToReturn, convertedVectorOfVectorPoint, -1, new MCvScalar(0, 255, 0, 255), 2);
            return(matToReturn);
        }
Beispiel #13
0
        private void DrawSelectedCellContourBoxToMat(Mat imgToMod, VectorOfPoint tempVector)
        {
            var matToReturn = imgToMod.CreateNewHardCopyFromMat();

            if (matToReturn.NumberOfChannels < 3)
            {
                CvInvoke.CvtColor(matToReturn, matToReturn, ColorConversion.Gray2Bgr);
            }


            var boxVecOfVectorPoint = new VectorOfVectorOfPointF();
            var tempRect            = CvInvoke.MinAreaRect(tempVector);
            var box    = CvInvoke.BoxPoints(tempRect);
            var boxVec = new VectorOfPointF(box);

            boxVecOfVectorPoint.Push(boxVec);
            var convertedVectorOfVectorPoint = boxVecOfVectorPoint.ConvertToVectorOfPoint();

            CvInvoke.DrawContours(matToReturn, convertedVectorOfVectorPoint, -1, new MCvScalar(0, 114, 251, 0), 3);
        }
Beispiel #14
0
        public Mat DrawAllCellContourBoundingBoxes(Mat imgToMod)
        {
            var matToReturn = imgToMod.CreateNewHardCopyFromMat();

            CvInvoke.CvtColor(matToReturn, matToReturn, ColorConversion.Gray2Bgr);
            var boxVecOfVectorPoint = new VectorOfVectorOfPointF();

            foreach (var contour in Contours.ToArrayOfArray())
            {
                var tempVector = new VectorOfPoint(contour);
                var tempRect   = CvInvoke.MinAreaRect(tempVector);
                var box        = CvInvoke.BoxPoints(tempRect);
                var boxVec     = new VectorOfPointF(box);
                boxVecOfVectorPoint.Push(boxVec);
            }

            var convertedVectorOfVectorPoint = boxVecOfVectorPoint.ConvertToVectorOfPoint();

            CvInvoke.DrawContours(matToReturn, convertedVectorOfVectorPoint, -1, new MCvScalar(0, 255, 0, 255), 2);
            return(matToReturn);
        }
Beispiel #15
0
        /// <summary>
        /// Here, bounding rectangle is drawn with minimum area
        /// </summary>
        /// <param name="scr"></param>
        /// <returns></returns>
        private Point[] Find_Rectangle(Image <Bgr, byte> scr)
        {
            // Declare variable
            Point[] rect           = new Point[4];
            double  area           = 0;
            int     index_contours = 0;


            VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
            Mat hierarchy = new Mat();
            Image <Gray, byte> GrayImages      = scr.Convert <Gray, byte>();
            Image <Gray, byte> ThresholdImages = new Image <Gray, byte>(GrayImages.Size);

            // Find contours
            CvInvoke.Threshold(GrayImages, ThresholdImages, threshold_value, 255, ThresholdType.Binary);
            CvInvoke.FindContours(ThresholdImages, contours, hierarchy, RetrType.External, ChainApproxMethod.ChainApproxSimple);
            for (int i = 0; i < contours.Size; i++)
            {
                double s = CvInvoke.ContourArea(contours[i]);
                if (area < s)
                {
                    area           = s;
                    index_contours = i;
                }
            }
            // Find Rectangle Box With 4 Points
            RotatedRect RectangleMin = CvInvoke.MinAreaRect(contours[index_contours]);

            PointF[] RectangleMin_Tip = CvInvoke.BoxPoints(RectangleMin);
            for (int i = 0; i < 4; i++)
            {
                rect[i] = Point.Round(RectangleMin_Tip[i]);
            }
            // Clear memory
            GrayImages.Dispose();
            ThresholdImages.Dispose();
            contours.Dispose();
            hierarchy.Dispose();
            return(rect);
        }
Beispiel #16
0
        private void PrepareContour()
        {
            var contour = workingCam.workingContours.Pop();

            contourMoments     = CvInvoke.Moments(contour);
            contourCenterPoint = new Point((int)(contourMoments.M10 / contourMoments.M00), (int)workingCam.roiPosYSlider + (int)(contourMoments.M01 / contourMoments.M00));
            drawman.DrawCircle(workingCam.linedFrame, contourCenterPoint, 4, new Bgr(Color.Blue).MCvScalar, 3);

            // Find contour rectangle
            var rect = CvInvoke.MinAreaRect(contour);
            var box  = CvInvoke.BoxPoints(rect);

            contourBoxPoint1 = new Point((int)box[0].X, (int)workingCam.roiPosYSlider + (int)box[0].Y);
            contourBoxPoint2 = new Point((int)box[1].X, (int)workingCam.roiPosYSlider + (int)box[1].Y);
            contourBoxPoint3 = new Point((int)box[2].X, (int)workingCam.roiPosYSlider + (int)box[2].Y);
            contourBoxPoint4 = new Point((int)box[3].X, (int)workingCam.roiPosYSlider + (int)box[3].Y);
            drawman.DrawLine(workingCam.linedFrame, contourBoxPoint1, contourBoxPoint2, view.CamContourRectColor, view.CamContourRectThickness);
            drawman.DrawLine(workingCam.linedFrame, contourBoxPoint2, contourBoxPoint3, view.CamContourRectColor, view.CamContourRectThickness);
            drawman.DrawLine(workingCam.linedFrame, contourBoxPoint3, contourBoxPoint4, view.CamContourRectColor, view.CamContourRectThickness);
            drawman.DrawLine(workingCam.linedFrame, contourBoxPoint4, contourBoxPoint1, view.CamContourRectColor, view.CamContourRectThickness);

            // Setup vertical contour middlepoints
            var contourWidth  = FindDistance(contourBoxPoint1, contourBoxPoint2);
            var contourHeight = FindDistance(contourBoxPoint4, contourBoxPoint1);

            if (contourWidth < contourHeight)
            {
                contourBoxMiddlePoint1 = FindMiddle(contourBoxPoint1, contourBoxPoint2);
                contourBoxMiddlePoint2 = FindMiddle(contourBoxPoint4, contourBoxPoint3);
            }
            else
            {
                contourBoxMiddlePoint1 = FindMiddle(contourBoxPoint4, contourBoxPoint1);
                contourBoxMiddlePoint2 = FindMiddle(contourBoxPoint3, contourBoxPoint2);
            }
        }
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            // decode();
            // buttonClick();

            //以锐化效果显示图像
            try
            {
                Bitmap oldBitmap = new Bitmap(@"D:\Desktop\DIYcode\微孔-识别\RT5911A9OMZ3000973.jpg");
                oldBitmap.RotateFlip(RotateFlipType.Rotate270FlipNone);
                int    Height    = oldBitmap.Height;
                int    Width     = oldBitmap.Width;
                Bitmap newBitmap = new Bitmap(Width, Height);

                Color pixel;
                //拉普拉斯模板
                //int[] Laplacian = { -1, -1, -1, -1, 9, -1, -1, -1, -1 };
                //for (int x = 1; x < Width - 1; x++)
                //    for (int y = 1; y < Height - 1; y++)
                //    {
                //        int r = 0, g = 0, b = 0;
                //        int Index = 0;
                //        for (int col = -1; col <= 1; col++)
                //            for (int row = -1; row <= 1; row++)
                //            {
                //                pixel = oldBitmap.GetPixel(x + row, y + col); r += pixel.R * Laplacian[Index];
                //                g += pixel.G * Laplacian[Index];
                //                b += pixel.B * Laplacian[Index];
                //                Index++;
                //            }
                //        //处理颜色值溢出
                //        r = r > 255 ? 255 : r;
                //        r = r < 0 ? 0 : r;
                //        g = g > 255 ? 255 : g;
                //        g = g < 0 ? 0 : g;
                //        b = b > 255 ? 255 : b;
                //        b = b < 0 ? 0 : b;
                //        newBitmap.SetPixel(x - 1, y - 1, Color.FromArgb(r, g, b));
                //    }

                // new GrayBitmapData(newBitmap).NewFilter(9);
                // newBitmap.Save(@"D:\Desktop\DIYcode\newBitmap.jpg");


                Image <Gray, Byte> matimg = OtsuThreshold(oldBitmap);

                matimg.Save(@"D:\Desktop\DIYcode\matimg.jpg");
                matimg = matimg.SmoothMedian(11);
                matimg.Save(@"D:\Desktop\DIYcode\SmoothMedian.jpg");
                Image <Gray, Byte> edges = new Image <Gray, byte>(newBitmap.Width, newBitmap.Height);

                Image <Bgr, Byte> contoursimg = new Image <Bgr, byte>(oldBitmap);

                Mat hierarchy = new Mat();
                // Image<Gray, Byte> hierarchy = new Image<Gray, byte>(matimg.Width, matimg.Height);

                VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();

                VectorOfVectorOfPointF VectorOfPointF = new VectorOfVectorOfPointF();

                CvInvoke.Canny(matimg, edges, 0, 200);

                CvInvoke.FindContours(edges,
                                      contours,
                                      hierarchy,
                                      RetrType.Tree,
                                      ChainApproxMethod.ChainApproxSimple);
                List <int> fater_contours = new List <int>();

                int[,,] arraylist = ((int[, , ])(hierarchy.GetData()));

                for (int k = 0; k < contours.Size; k++)
                {
                    int i = k;
                    int c = 0;
                    while (arraylist[0, i, 2] != -1)
                    {
                        i = arraylist[0, i, 2];
                        c = c + 1;
                        if (c >= 5)
                        {
                            fater_contours.Add(k);
                        }
                    }
                }
                for (int j = 0; j < fater_contours.Count; j++)
                {
                    RotatedRect rect = CvInvoke.MinAreaRect(contours[fater_contours[j]]); //minAreaRect
                    PointF[]    pf   = CvInvoke.BoxPoints(rect);                          //BoxPoints();
                    // VectorOfPointF.Push(new VectorOfPointF(pf));
                    contoursimg.Draw(rect, new Bgr(255, 0, 0), 2);
                    // CvInvoke.DrawContours(new Image<Bgr, Byte>(newBitmap), VectorOfPointF, -1, new MCvScalar(0, 255, 0), 1, LineType.AntiAlias);
                }

                var str = decode(matimg.ToBitmap());
                ImgContorl.Source = ToBitmapsource(contoursimg.ToBitmap());
                //CvInvoke.DrawContours(new Image<Bgr, Byte>(newBitmap), VectorOfPointF, -1 , new MCvScalar(0, 255, 0), 1, LineType.AntiAlias);
                //double area = CvInvoke.ContourArea(contours[k]);
                //if (area > 20000 && area < 30000)
                //{
                //    CvInvoke.DrawContours(contoursimg, contours, k, new MCvScalar(0, 255, 0), 1, Emgu.CV.CvEnum.LineType.AntiAlias);
                //    contoursimg.Save(@"D:\Desktop\DIYcode\contoursimg" + k.ToString() + ".jpg");
                //    vector.Push(ofPoint);
                //}

                //if (area > 3300 && area < 3800)
                //{
                //    CvInvoke.DrawContours(contoursimg, contours, k, new MCvScalar(255, 0, 0), 1, Emgu.CV.CvEnum.LineType.AntiAlias);
                //    contoursimg.Save(@"D:\Desktop\DIYcode\werwer" + k.ToString() + ".jpg");
                //    vector.Push(ofPoint);
                //}

                //if (area>500)
                //{
                //    CvInvoke.DrawContours(contoursimg, contours, k, new MCvScalar(255, 0, 0), 1, Emgu.CV.CvEnum.LineType.AntiAlias);
                //}
                //  CvInvoke.DrawContours(disp, contours, k, new MCvScalar(0, 255, 0), 1, Emgu.CV.CvEnum.LineType.AntiAlias, null, 1);
                //    }
                //}
            }
            catch (Exception ex)
            {
                //  return null;
                //  MessageBox.Show(ex.Message, "信息提示");
            }
        }
        private void SetImg(string path)
        {
            try
            {
                Bitmap oldBitmap = new Bitmap(path);
                oldBitmap.RotateFlip(RotateFlipType.Rotate270FlipNone);

                Image <Gray, Byte> matimg = OtsuThreshold(oldBitmap);
                matimg = matimg.SmoothMedian(11);
                Image <Gray, Byte> edges = new Image <Gray, byte>(oldBitmap.Width, oldBitmap.Height);

                Image <Bgr, Byte> contoursimg = new Image <Bgr, byte>(oldBitmap);

                Mat hierarchy = new Mat();

                VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
                //VectorOfVectorOfPointF VectorOfPointF = new VectorOfVectorOfPointF();

                CvInvoke.Canny(matimg, edges, 0, 200);

                CvInvoke.FindContours(edges,
                                      contours,
                                      hierarchy,
                                      RetrType.Tree,
                                      ChainApproxMethod.ChainApproxSimple);
                List <int> fater_contours = new List <int>();

                int[,,] arraylist = ((int[, , ])(hierarchy.GetData()));

                for (int k = 0; k < contours.Size; k++)
                {
                    int i = k;
                    int c = 0;
                    while (arraylist[0, i, 2] != -1)
                    {
                        i = arraylist[0, i, 2];
                        c = c + 1;
                        if (c > 4)
                        {
                            fater_contours.Add(k);
                        }
                    }
                }
                for (int j = 0; j < fater_contours.Count; j++)
                {
                    RotatedRect rect = CvInvoke.MinAreaRect(contours[fater_contours[j]]); //minAreaRect
                    MudelSize = rect.Size.Width > rect.Size.Height ?  (int)rect.Size.Height :  (int)rect.Size.Width;

                    PointF[] pf = CvInvoke.BoxPoints(rect);//BoxPoints();

                    Point[] point = new Point[pf.Length];

                    int[] pointx = new int[4];
                    int[] pointy = new int[4];
                    for (int i = 0; i < pf.Length; i++)
                    {
                        pointx[i] = (int)pf[i].X;
                        pointy[i] = (int)pf[i].Y;
                    }
                    Rectangles.Add(new Rectangle()
                    {
                        X = pointx.Min(), Y = pointy.Min(), Width = MudelSize, Height = MudelSize
                    });

                    contoursimg.Draw(rect, new Bgr(255, 0, 0), 2);
                    // CvInvoke.DrawContours(new Image<Bgr, Byte>(newBitmap), VectorOfPointF, -1, new MCvScalar(0, 255, 0), 1, LineType.AntiAlias);
                }
            }
            catch (Exception ex)
            {
                //  return null;
                //  MessageBox.Show(ex.Message, "信息提示");
            }
        }
        public void ProcessDartContour()
        {
            logger.Debug($"Process dartContour for cam_{camService.camNumber} start");
            // Moments and centerpoint
            // var contourMoments = CvInvoke.Moments(processedContour);
            // var contourCenterPoint = new PointF((float) (contourMoments.M10 / contourMoments.M00),
            //                                     (float) camService.roiPosYSlider + (float) (contourMoments.M01 / contourMoments.M00));

            // Find contour rectangle
            var rect = CvInvoke.MinAreaRect(dartContour.ContourPoints);
            var box  = CvInvoke.BoxPoints(rect);

            var contourBoxPoint1 = new PointF(box[0].X, (float)camService.roiPosYSlider + box[0].Y);
            var contourBoxPoint2 = new PointF(box[1].X, (float)camService.roiPosYSlider + box[1].Y);
            var contourBoxPoint3 = new PointF(box[2].X, (float)camService.roiPosYSlider + box[2].Y);
            var contourBoxPoint4 = new PointF(box[3].X, (float)camService.roiPosYSlider + box[3].Y);

            // Setup vertical contour middlepoints
            var    contourHeight = FindDistance(contourBoxPoint1, contourBoxPoint2);
            var    contourWidth  = FindDistance(contourBoxPoint4, contourBoxPoint1);
            PointF contourBoxMiddlePoint1;
            PointF contourBoxMiddlePoint2;

            if (contourWidth > contourHeight)
            {
                contourBoxMiddlePoint1 = FindMiddle(contourBoxPoint1, contourBoxPoint2);
                contourBoxMiddlePoint2 = FindMiddle(contourBoxPoint4, contourBoxPoint3);
            }
            else
            {
                contourBoxMiddlePoint1 = FindMiddle(contourBoxPoint4, contourBoxPoint1);
                contourBoxMiddlePoint2 = FindMiddle(contourBoxPoint3, contourBoxPoint2);
            }

            // Find spikeLine to surface
            var spikeLinePoint1 = contourBoxMiddlePoint1;
            var spikeLinePoint2 = contourBoxMiddlePoint2;
            var spikeLineLength = camService.surfacePoint2.Y - contourBoxMiddlePoint2.Y;
            var spikeAngle      = FindAngle(contourBoxMiddlePoint2, contourBoxMiddlePoint1);

            spikeLinePoint1.X = (float)(contourBoxMiddlePoint2.X + Math.Cos(spikeAngle) * spikeLineLength);
            spikeLinePoint1.Y = (float)(contourBoxMiddlePoint2.Y + Math.Sin(spikeAngle) * spikeLineLength);

            // Find point of impact with surface
            PointF?camPoi = FindLinesIntersection(spikeLinePoint1, spikeLinePoint2, camService.surfacePoint1, camService.surfacePoint2);

            // Translate cam surface POI to dartboard projection
            var frameWidth                    = camService.RoiLastThrowFrame.Cols;
            var frameSemiWidth                = frameWidth / 2;
            var camFovSemiAngle               = camFovAngle / 2;
            var projectionToCenter            = new PointF();
            var surfacePoiToCenterDistance    = FindDistance(camService.surfaceCenterPoint1, camPoi.GetValueOrDefault());
            var surfaceLeftToPoiDistance      = FindDistance(camService.surfaceLeftPoint1, camPoi.GetValueOrDefault());
            var surfaceRightToPoiDistance     = FindDistance(camService.surfaceRightPoint1, camPoi.GetValueOrDefault());
            var projectionCamToCenterDistance = frameSemiWidth / Math.Sin(Math.PI * camFovSemiAngle / 180.0) * Math.Cos(Math.PI * camFovSemiAngle / 180.0);
            var projectionCamToPoiDistance    = Math.Sqrt(Math.Pow(projectionCamToCenterDistance, 2) + Math.Pow(surfacePoiToCenterDistance, 2));
            var projectionPoiToCenterDistance = Math.Sqrt(Math.Pow(projectionCamToPoiDistance, 2) - Math.Pow(projectionCamToCenterDistance, 2));
            var poiCamCenterAngle             = Math.Asin(projectionPoiToCenterDistance / projectionCamToPoiDistance);

            projectionToCenter.X = (float)(camService.setupPoint.X - Math.Cos(camService.toBullAngle) * projectionCamToCenterDistance);
            projectionToCenter.Y = (float)(camService.setupPoint.Y - Math.Sin(camService.toBullAngle) * projectionCamToCenterDistance);

            if (surfaceLeftToPoiDistance < surfaceRightToPoiDistance)
            {
                poiCamCenterAngle *= -1;
            }

            var projectionPoi = new PointF
            {
                X = (float)(camService.setupPoint.X + Math.Cos(camService.toBullAngle + poiCamCenterAngle) * 2000),
                Y = (float)(camService.setupPoint.Y + Math.Sin(camService.toBullAngle + poiCamCenterAngle) * 2000)
            };

            // Draw line from cam through projection POI
            var rayPoint = projectionPoi;
            var angle    = FindAngle(camService.setupPoint, rayPoint);

            rayPoint.X = (float)(camService.setupPoint.X + Math.Cos(angle) * 2000);
            rayPoint.Y = (float)(camService.setupPoint.Y + Math.Sin(angle) * 2000);

            drawService.ProjectionDrawLine(camService.setupPoint, rayPoint, new Bgr(Color.DodgerBlue).MCvScalar);

            var ray = new Ray(camService.camNumber, camService.setupPoint, rayPoint, dartContour.Arc);

            throwService.SaveRay(ray);

            logger.Debug($"Process dartContour for cam_{camService.camNumber} end. Ray saved:{ray}");
        }
        /// <summary>
        /// 获取机器人法兰中心移动坐标和旋转角度,camera=0代表右侧相机,camera=1代表前方向机
        /// </summary>
        /// <param name="bitmap">产品图像</param>
        /// <param name="cameraID">相机编号</param>
        public ImageInfo GetProductParamters(Bitmap bitmap, int cameraID, int spongeH)
        {
            ImageInfo imageInfo = new ImageInfo();
            Dictionary <Point, int> dividedCoutour;//记录四条边的点集
            List <double>           motorShif      = new List <double>();
            List <VectorOfPoint>    imageContours  = GetContours(bitmap, cameraID, spongeH);
            VectorOfPoint           productContour = imageContours.Max();

            Point[] pst = productContour.ToArray();//获取轮廓上所有的点集
            //用矩计算质心
            MCvMoments cvMoments     = CvInvoke.Moments(productContour, false);
            float      gravityX      = (float)(cvMoments.M10 / cvMoments.M00);
            float      gravityY      = (float)(cvMoments.M01 / cvMoments.M00);
            PointF     gravityCenter = new PointF(gravityX, gravityY);

            imageInfo.GravityCenterOfImg = gravityCenter;
            //用X均值和Y均值计算质心
            float vx = 0;
            float vy = 0;

            foreach (var item in pst)
            {
                vx += item.X;
                vy += item.Y;
            }
            PointF centriod = new PointF((float)vx / (float)pst.Length, (float)vy / (float)pst.Length);

            if (productContour != null)
            {
                RotatedRect minRect          = CvInvoke.MinAreaRect(productContour); //最小外接矩形
                PointF[]    pt               = CvInvoke.BoxPoints(minRect);          //最小外接矩形四个角点
                PointF      po               = minRect.Center;                       //最小外接矩形中心
                double      rectRotatedAngle = Math.Abs(minRect.Angle) > 45 ? minRect.Angle + 90 : minRect.Angle;
                //长轴,短轴,倾角计算:
                //AxisLong =  Math.Sqrt(Math.Pow(pt[1].X - pt[0].X, 2) + Math.Pow(pt[1].Y - pt[0].Y, 2));
                double AxisLong = minRect.Size.Width > minRect.Size.Height ? minRect.Size.Width : minRect.Size.Height;
                //AxisShort =  Math.Sqrt(Math.Pow(pt[2].X - pt[1].X, 2) + Math.Pow(pt[2].Y - pt[1].Y, 2));
                double AxisShort = minRect.Size.Height <= minRect.Size.Width ? minRect.Size.Height : minRect.Size.Width;
                imageInfo.ImageCorner      = pt;
                imageInfo.RectCenterOfImg  = po;
                imageInfo.CenterOfImg      = centriod;
                imageInfo.RectRotatedAngle = rectRotatedAngle;
                imageInfo.AxisLong         = AxisLong;
                imageInfo.AxisShort        = AxisShort;
                Trace.WriteLine("当前轮廓质心:" + centriod.ToString());
                Trace.WriteLine("当前外界矩形中心:" + po.ToString());
                Trace.WriteLine("X差值" + Math.Abs(centriod.X - po.X).ToString(), "Y差值" + Math.Abs(centriod.Y - po.Y).ToString());
                #region 计算电气抓位移
                dividedCoutour = new Dictionary <Point, int>();//储存四条分组的边的点集

                for (int i = 0; i < pt.Length; i++)
                {
                    Point p1 = new Point((int)pt[i].X, (int)pt[i].Y);
                    Point p2 = new Point((int)pt[(i + 1) % 4].X, (int)pt[(i + 1) % 4].Y);
                    if (p1.X < width / 2 && p1.Y > height / 2)//左
                    {
                        foreach (var item in pst)
                        {
                            if (item.X <= (p1.X >= p2.X ? p1.X : p2.X) + 20 && item.X >= (p1.X > p2.X ? p2.X : p1.X) - 20 && item.Y <= (p1.Y >= p2.Y ? p1.Y : p2.Y) - 20 && item.Y >= (p1.Y > p2.Y ? p2.Y : p1.Y) + 20)
                            {
                                dividedCoutour[item] = 0;
                            }
                        }
                    }
                    else if (p1.X < width / 2 && p1.Y < height / 2)//上
                    {
                        foreach (var item in pst)
                        {
                            if (item.X <= (p1.X >= p2.X ? p1.X : p2.X) - 20 && item.X >= (p1.X > p2.X ? p2.X : p1.X) + 20 && item.Y <= (p1.Y >= p2.Y ? p1.Y : p2.Y) + 20 && item.Y >= (p1.Y > p2.Y ? p2.Y : p1.Y) - 20)
                            {
                                dividedCoutour[item] = 1;
                            }
                        }
                    }
                    else if (p1.X > width / 2 && p1.Y < height / 2)//右
                    {
                        foreach (var item in pst)
                        {
                            if (item.X <= (p1.X >= p2.X ? p1.X : p2.X) + 20 && item.X >= (p1.X > p2.X ? p2.X : p1.X) - 20 && item.Y <= (p1.Y >= p2.Y ? p1.Y : p2.Y) - 20 && item.Y >= (p1.Y > p2.Y ? p2.Y : p1.Y) + 20)
                            {
                                dividedCoutour[item] = 2;
                            }
                        }
                    }
                    else if (p1.X > width / 2 && p1.Y > height / 2)//下
                    {
                        foreach (var item in pst)
                        {
                            if (item.X <= (p1.X >= p2.X ? p1.X : p2.X) - 20 && item.X >= (p1.X > p2.X ? p2.X : p1.X) + 20 && item.Y <= (p1.Y >= p2.Y ? p1.Y : p2.Y) + 20 && item.Y >= (p1.Y > p2.Y ? p2.Y : p1.Y) - 20)
                            {
                                dividedCoutour[item] = 3;
                            }
                        }
                    }
                }
                /*计算拟合直线斜率*/
                LineParamters leftLineParamter              = LinearRegression(dividedCoutour.Where(a => a.Value == 0).Select(a => a.Key).ToArray());
                LineParamters upLineParamter                = LinearRegression(dividedCoutour.Where(a => a.Value == 1).Select(a => a.Key).ToArray());
                LineParamters rightLineParamter             = LinearRegression(dividedCoutour.Where(a => a.Value == 2).Select(a => a.Key).ToArray());
                LineParamters bottomLineParamter            = LinearRegression(dividedCoutour.Where(a => a.Value == 3).Select(a => a.Key).ToArray());
                Dictionary <double, double> fourLineParmter = new Dictionary <double, double>();
                //fourLineParmter.Add(leftLineParamter.K, leftLineParamter.B);
                //fourLineParmter.Add(upLineParamter.K, upLineParamter.B);
                //fourLineParmter.Add(rightLineParamter.K, rightLineParamter.B);
                //fourLineParmter.Add(bottomLineParamter.K, bottomLineParamter.B);
                imageInfo.fourLineParam = fourLineParmter;

                double leftAngle   = Math.Atan(leftLineParamter.K) * 180f / Math.PI;
                double upAngle     = Math.Atan(upLineParamter.K) * 180f / Math.PI;
                double rightAngle  = Math.Atan(rightLineParamter.K) * 180f / Math.PI;
                double bottomAngle = Math.Atan(bottomLineParamter.K) * 180f / Math.PI;
                double RotatedAngle;
                if (Math.Abs(Math.Abs(leftAngle - upAngle) - 90f) <= Math.Abs(Math.Abs(upAngle - rightAngle) - 90f))
                {
                    RotatedAngle = Math.Abs(leftAngle) < Math.Abs(upAngle) ? leftAngle : upAngle;
                }
                else
                {
                    RotatedAngle = Math.Abs(rightAngle) < Math.Abs(upAngle) ? rightAngle : upAngle;
                }
                imageInfo.RotatedAngle = RotatedAngle;
                /*计算拟合直线斜率*/
                DividedContours = dividedCoutour;

                //验证一段分5组:
                List <double> up     = new List <double>();
                List <double> bottom = new List <double>();
                List <double> left   = new List <double>();
                List <double> right  = new List <double>();
                left = GetFiveDistanceOnLine(rectRotatedAngle, new Point((int)gravityCenter.X, (int)gravityCenter.Y), AxisLong, AxisShort, dividedCoutour.Where(a => a.Value == 0).ToDictionary(a => a.Key, a => a.Value));
                //if (cameraID == 0)//R
                //{
                //    for (int i = 0; i < left.Count; i++)
                //    {
                //        if (left[i] > AxisLong * 3 / 5f)
                //        {
                //            left[i] = 0;
                //        }
                //    }
                //}

                for (int i = 0; i < left.Count; i++)
                {
                    if (left[i] > AxisLong * 3 / 5f)
                    {
                        left[i] = 0;
                    }
                }

                up = GetFiveDistanceOnLine(rectRotatedAngle, new Point((int)gravityCenter.X, (int)gravityCenter.Y), AxisLong, AxisShort, dividedCoutour.Where(a => a.Value == 1).ToDictionary(a => a.Key, a => a.Value));
                //if (cameraID == 1)//F
                //{
                //    for (int i = 0; i < up.Count; i++)
                //    {
                //        if (up[i] > AxisLong * 3 / 5f)
                //        {
                //            up[i] = 0;
                //        }
                //    }
                //}

                for (int i = 0; i < up.Count; i++)
                {
                    if (up[i] > AxisShort * 3 / 5f)
                    {
                        up[i] = 0;
                    }
                }

                right = GetFiveDistanceOnLine(rectRotatedAngle, new Point((int)gravityCenter.X, (int)gravityCenter.Y), AxisLong, AxisShort, dividedCoutour.Where(a => a.Value == 2).ToDictionary(a => a.Key, a => a.Value));
                //if (cameraID == 0)//R
                //{
                //    for (int i = 0; i < right.Count; i++)
                //    {
                //        if (right[i] > AxisLong * 3 / 5f)
                //        {
                //            right[i] = 0;
                //        }
                //    }
                //}

                for (int i = 0; i < right.Count; i++)
                {
                    if (right[i] > AxisLong * 3 / 5f)
                    {
                        right[i] = 0;
                    }
                }

                bottom = GetFiveDistanceOnLine(rectRotatedAngle, new Point((int)gravityCenter.X, (int)gravityCenter.Y), AxisLong, AxisShort, dividedCoutour.Where(a => a.Value == 3).ToDictionary(a => a.Key, a => a.Value));
                //if (cameraID == 1)//F
                //{
                //    for (int i = 0; i < bottom.Count; i++)
                //    {
                //        if (bottom[i] > AxisLong * 3 / 5f)
                //        {
                //            bottom[i] = 0;
                //        }
                //    }
                //}

                for (int i = 0; i < bottom.Count; i++)
                {
                    if (bottom[i] > AxisShort * 3 / 5f)
                    {
                        bottom[i] = 0;
                    }
                }


                //if (cameraID == 1)//F
                //{
                motorShif = left.Concat(up).Concat(right).Concat(bottom).ToList <double>();//左-上-右-下

                //}
                //else
                //{
                //    motorShif = bottom.Concat(left).Concat(up).Concat(right).ToList<double>();//下-左-上-右
                //}
                double _20 = motorShif[19];
                double _21 = motorShif[9];
                double _22 = motorShif[8];
                double _23 = motorShif[18];
                motorShif.Add(_20);
                motorShif.Add(_21);
                motorShif.Add(_22);
                motorShif.Add(_23);
                imageInfo.MotorShift = motorShif.ToArray();
                #endregion

                //foreach (var item in dividedCoutour)
                //{
                //    File.AppendAllText("ContourPoints.txt", "X=" + item.Key.X.ToString() +"\t\t"+ "Y=" + item.Key.Y.ToString() +"\t\t"+"Key="+item.Value.ToString()+ "\n\r");
                //}



                Matrix <double> imgCenter = new Matrix <double>(3, 1)
                {
        // Maximum Value, Minimum Value and their locations
        // Mean Color or Mean Intensity

        public void calcularRegionProps(Image <Gray, byte> inputRegionIMG, double AreaMin)
        {
            // Declaração do vetor de vetores de pontos
            Emgu.CV.Util.VectorOfVectorOfPoint vetordeVetdePontos = new Emgu.CV.Util.VectorOfVectorOfPoint();
            // Declaração de uma matriz
            Mat hierarquia = new Mat();

            // Aplicação da função FindContour
            CvInvoke.FindContours(
                inputRegionIMG                                       // Recebe a imagem de entrada
                , vetordeVetdePontos                                 // Recebe um vetor de pontos de contorno
                , hierarquia                                         // Recebe a hierarquia dos pontos
                , Emgu.CV.CvEnum.RetrType.Tree                       // Recebe o tipo de arvore e contornos
                , Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxNone   // Tip de aproximação aos contornos
                , new Point(0, 0)                                    // Offset do ponto, posso omitir ou declarar um ponto a 0 0
                );

            Image <Bgr, Byte> input = inputRegionIMG.Convert <Bgr, byte>();

            //Até aqui encontro o contorno. Deve ser só 1!!!, portanto deve ser o contorno 0,
            //mas mesmo assim vamos fazer um teste para ver qual o contorno a usar

            // Pontos buffer
            PointF buffer_Minx = new PointF(inputRegionIMG.Width, inputRegionIMG.Height);
            PointF buffer_MaxX = new PointF(0, 0);
            PointF buffer_MinY = new PointF(inputRegionIMG.Width, inputRegionIMG.Height);
            PointF buffer_MaxY = new PointF(0, 0);


            for (int i = 0; i < vetordeVetdePontos.Size; i++)
            {
                Area = Math.Abs(CvInvoke.ContourArea(vetordeVetdePontos[i], true));      // calcula a area do contorno

                if (Area >= AreaMin)
                {
                    for (int iter = 0; iter < vetordeVetdePontos[i].Size; iter++)
                    {
                        //----------------- Calculo do extreme -----------------
                        // Calcula o valor do ponto mais à esquerda
                        if (vetordeVetdePontos[i][iter].X < buffer_Minx.X)
                        {
                            buffer_Minx = vetordeVetdePontos[i][iter];
                        }

                        // Calcula o valor do ponto mais à direita
                        if (vetordeVetdePontos[i][iter].X > buffer_MaxX.X)
                        {
                            buffer_MaxX = vetordeVetdePontos[i][iter];
                        }

                        // Calcula o valor do ponto Y mais em cima
                        if (vetordeVetdePontos[i][iter].Y < buffer_MinY.Y)
                        {
                            buffer_MinY = vetordeVetdePontos[i][iter];
                        }

                        // Calcula o valor do ponto Y mais em baixo
                        if (vetordeVetdePontos[i][iter].Y > buffer_MaxY.Y)
                        {
                            buffer_MaxY = vetordeVetdePontos[i][iter];
                        }
                        //----------------- Fim do calculo do extreme -----------------
                    }

                    // ------------- Calculo do Centroid ---------------------
                    Moments momento = CvInvoke.Moments(vetordeVetdePontos[i]);
                    int     X       = (int)(momento.M10 / momento.M00);
                    int     Y       = (int)(momento.M01 / momento.M00);
                    Centroid = new PointF(X, Y);
                    // ------------------------------------------------------

                    // ------------ Calculo do AspectRatio ------------------
                    AspectRatio = inputRegionIMG.Width / inputRegionIMG.Height;
                    //-------------------------------------------------------

                    //------------- Calculo da BoundingBox ------------------
                    BoundingBox = CvInvoke.BoundingRectangle(vetordeVetdePontos[i]);
                    //-------------------------------------------------------

                    // ------------   Calculo do Extent   -------------------
                    float rect_area = BoundingBox.Width * BoundingBox.Height;
                    Extent = (float)Area / rect_area;
                    // ------------------------------------------------------

                    // --------------- ConvectHULL --------------------------
                    CvInvoke.ConvexHull(vetordeVetdePontos[i], ConvexHull, false);
                    //-------------------------------------------------------

                    // --------------- ConvectHULL_area ---------------------
                    ConvexHull_area = CvInvoke.ContourArea(ConvexHull);
                    //-------------------------------------------------------

                    //-----------------  Solidity ---------------------------
                    Solidity = Area / ConvexHull_area;
                    // ------------------------------------------------------

                    //-------------- Diametro Equivalente -------------------
                    EquivalentDiameter = Math.Sqrt(4 * Area / Math.PI);
                    // ------------------------------------------------------

                    //--------------- Circulo Envolvente --------------------
                    CirculoEnvolvente = CvInvoke.MinEnclosingCircle(vetordeVetdePontos[i]);
                    //-------------------------------------------------------

                    //--------------- Circulo Perimetro --------------------
                    perimetro = CvInvoke.ArcLength(vetordeVetdePontos[i], true);
                    // -----------------------------------------------------

                    // -------------- Circularity (Fator de forma)----------
                    Circularity = (4 * Math.PI * Area) / (perimetro * perimetro);
                    //------------------------------------------------------

                    // --------------- Verifica se é convexo ---------------
                    isConvex = CvInvoke.IsContourConvex(vetordeVetdePontos[i]);
                    //------------------------------------------------------

                    // ------------- Apriximação do contorno ---------------
                    CvInvoke.ApproxPolyDP(
                        vetordeVetdePontos[i],              // Cada vetor de um contorno iterado
                        ContourApproximation,               // Vetor que vai conter a aproximação
                        0.1 * perimetro,                    // Expande o perimetro
                        true                                // Calcula um aproximação ao contorno externo
                        );
                    // -----------------------------------------------------

                    // ------------- Devolve o contorno --------------------
                    Contorno = vetordeVetdePontos[i];
                    // ------------------------------------------------------

                    // ------------  Retangulo rodado  ---------------------
                    RotatedRect retanguloRodado = CvInvoke.MinAreaRect(vetordeVetdePontos[i]);
                    PointF[]    vetorPontos     = CvInvoke.BoxPoints(retanguloRodado);
                    BoundingBoxRectRodado = new Point[vetorPontos.Length];
                    for (int iterador = 0; iterador < vetorPontos.Length; iterador++)
                    {
                        BoundingBoxRectRodado[iterador].X = (int)vetorPontos[iterador].X;
                        BoundingBoxRectRodado[iterador].Y = (int)vetorPontos[iterador].Y;
                    }
                    // ------------ AnguloRecExterior ----------------------
                    AnguloRectExterior = retanguloRodado.Angle;
                    // -----------------------------------------------------

                    // ------------ EllipseImagem --------------------------
                    EllipseValores = CvInvoke.FitEllipseAMS(vetordeVetdePontos[i]);
                    // -----------------------------------------------------

                    // Fitting a Line ---------------
                    //---------------------------

                    // salta do ciclo for
                    i = vetordeVetdePontos.Size;
                }
            }

            Extreme.Mais_a_esquerda = buffer_Minx;
            Extreme.Mais_a_Direita  = buffer_MaxX;
            Extreme.Mais_em_baixo   = buffer_MaxY;
            Extreme.Mais_em_cima    = buffer_MinY;
        }
Beispiel #22
0
 /// <summary>
 /// Get the 4 verticies of this Box.
 /// </summary>
 /// <returns>The vertives of this RotatedRect</returns>
 public System.Drawing.PointF[] GetVertices()
 {
     return(CvInvoke.BoxPoints(this));
 }
        /// <summary>
        /// 图漾获取产品特征及位置
        /// </summary>
        /// <param name="myblob"></param>
        /// <param name="point_3d"></param>
        /// <returns></returns>
        public static bool getProduceInfo(Emgu.CV.Cvb.CvBlob myblob, float[] point_3d)
        {
            //#########################################【1】,获取最小外接矩形中心点下标#################################################
            Point[]     ctr  = myblob.GetContour();                          //获取轮廓
            RotatedRect rect = CvInvoke.MinAreaRect(new VectorOfPoint(ctr)); //最小矩形

            PointF[] pt = CvInvoke.BoxPoints(rect);                          //最小外接矩形四个角点
            PointF   po = rect.Center;                                       //最小外接矩形中心
            int      xc = (int)po.X;                                         //最小外接矩形中心X坐标
            int      yc = (int)po.Y;                                         //最小外接矩形中心Y坐标

            //#########################################【2】,绘制外接最小矩形(紧贴连通域):#################################################
            for (int i = 0; i < 4; ++i)
            {
                Point p1 = new Point((int)pt[i].X, (int)pt[i].Y);
                //GLB.obj.jd.Add(p1);//角点存下备画轨迹用
                Point p2 = new Point((int)pt[(i + 1) % 4].X, (int)pt[(i + 1) % 4].Y);
                CvInvoke.Line(GLB.MyFrame, p1, p2, new MCvScalar(0, 0, 255), 2);
            }

            //#########################################【3】真实角点):#################################################
            List <Point3> pointReal = new List <Point3>();

            for (int i = 0; i < 4; ++i)
            {
                Point3 Ang_temp = new Point3(0, 0, 0);//0.8视场角点坐标
                Ang_temp.X = xc + 0.8 * (pt[i].X - xc);
                Ang_temp.Y = yc + 0.8 * (pt[i].Y - yc);

                if (Ang_temp.Y < 0 || Ang_temp.Y > 960 - 2 || Ang_temp.X < 0 || Ang_temp.X > 1280 - 2)
                {
                    return(false);                      ///////无效角点
                }
                Point3 Ang_point = new Point3(0, 0, 0); //0.8角点坐标
                Ang_point.X = point_3d[((int)Ang_temp.Y * GLB.BUFW + (int)Ang_temp.X) * 3 + 0];
                Ang_point.Y = point_3d[((int)Ang_temp.Y * GLB.BUFW + (int)Ang_temp.X) * 3 + 1];
                Ang_point.Z = point_3d[((int)Ang_temp.Y * GLB.BUFW + (int)Ang_temp.X) * 3 + 2];
                if (double.IsNaN(Ang_point.Z))
                {
                    return(false);                          ///////////////////////////////////////////////////////////无效角点
                }
                pointReal.Add(Ang_point);
                RotatedRect myrect = new RotatedRect(new PointF((float)Ang_temp.X, (float)Ang_temp.Y), new Size(8, 8), 0);
                CvInvoke.Ellipse(GLB.MyFrame, myrect, new MCvScalar(255, 0, 0), 2);//在角上一个小圆
            }
            //GLB.obj.Depth = (int)pointReal.Average(o => o.Z);//中心点的深度//Z
            //GLB.obj.yCenter = (int)pointReal.Average(o => o.Y);//Y
            //GLB.obj.xCenter = (int)pointReal.Average(o => o.X); ;//X
            ////#########################################队列求均值--获取中心坐标#################################################
            GLB.avgCameraPoint3.Enqueue(new Point3(pointReal.Average(o => o.X), pointReal.Average(o => o.Y), (int)pointReal.Average(o => o.Z)));
            if (GLB.avgCameraPoint3.Count > 5)
            {
                GLB.avgCameraPoint3.Dequeue();
            }
            else
            {
                return(false);
            }
            GLB.obj.Depth   = (int)GLB.avgCameraPoint3.Average(o => o.Z); //中心点的深度//Z
            GLB.obj.yCenter = (int)GLB.avgCameraPoint3.Average(o => o.Y); //Y
            GLB.obj.xCenter = (int)GLB.avgCameraPoint3.Average(o => o.X); //X
            //#########################################获取质心#################################################
            //PointF gravity = myblob.Centroid;
            //int gravity_x = (int)gravity.X;
            //int gravity_y = (int)gravity.Y;
            //if (double.IsNaN(point_3d[(gravity_y * GLB.BUFW + gravity_x) * 3 + 2])) return false;/////////////////////空值不执行
            //GLB.obj.Depth = (int)point_3d[(gravity_y * GLB.BUFW + gravity_x) * 3 + 2];//Z
            //GLB.obj.yCenter = (int)point_3d[(gravity_y * GLB.BUFW + gravity_x) * 3 + 1];//Y
            //GLB.obj.xCenter = (int)point_3d[(gravity_y * GLB.BUFW + gravity_x) * 3 + 0];//X

            //######################################### 显示本区块中心[画圆]:#################################################
            RotatedRect boxCenter = new RotatedRect(new PointF(xc, yc), new Size(8, 8), 0);

            CvInvoke.Ellipse(GLB.MyFrame, boxCenter, new MCvScalar(255, 0, 0), 4);                                                                                                                                                                                         //在中心画一个小圆
            CvInvoke.PutText(GLB.MyFrame, "x:" + xc + "y:" + yc + "XC=" + GLB.obj.xCenter + "YC=" + GLB.obj.yCenter + "Depth=" + GLB.obj.Depth, new System.Drawing.Point(xc - 176, yc + 25), Emgu.CV.CvEnum.FontFace.HersheyDuplex, .75, new MCvScalar(255, 255, 255), 2); //深度显示

            //#########################################【4】真实的长轴,短轴,倾角计算:#################################################
            double axisLong  = 1.25 * Math.Sqrt(Math.Pow(pointReal[1].X - pointReal[0].X, 2) + Math.Pow(pointReal[1].Y - pointReal[0].Y, 2) + Math.Pow(pointReal[1].Z - pointReal[0].Z, 2));
            double axisShort = 1.25 * Math.Sqrt(Math.Pow(pointReal[2].X - pointReal[1].X, 2) + Math.Pow(pointReal[2].Y - pointReal[1].Y, 2) + Math.Pow(pointReal[2].Z - pointReal[1].Z, 2));

            if (axisShort > axisLong)
            {
                double temp = axisLong;
                axisLong  = axisShort;
                axisShort = temp;
            }
            double Angl = rect.Angle;//矩形框角度

            // Angl *= 180d / Math.PI; //换算成角度制
            if (Math.Abs(Angl) > 45)
            {
                Angl = Angl + 90;
            }


            if (Angl >= 90)//控制旋转范围
            {
                Angl -= 180;
            }
            if (Angl <= -90)
            {
                Angl += 180;
            }
            //GLB.obj.Angle = Angl;//旋转角
            ////队列求均值
            GLB.avgAngle.Enqueue((float)Angl);
            if (GLB.avgAngle.Count > 5)
            {
                GLB.avgAngle.Dequeue();
            }
            else
            {
                return(false);
            }
            GLB.obj.Angle = GLB.avgAngle.Average();//旋转角


            GLB.obj.axisLong  = axisLong;             //长轴
            GLB.obj.axisShort = axisShort;            //短轴
            GLB.obj.L2S       = axisLong / axisShort; //长短轴之比;
            GLB.obj.realArea  = axisLong * axisShort; //估算的物件尺寸

            //像尺寸显示:
            CvInvoke.PutText(GLB.MyFrame, "Lr=" + (int)axisLong + ",Sr=" + (int)axisShort, new System.Drawing.Point((int)pt[2].X, (int)pt[2].Y), Emgu.CV.CvEnum.FontFace.HersheyDuplex, .75, new MCvScalar(0, 0, 255), 2);
            CvInvoke.PutText(GLB.MyFrame, "Angl=" + Angl, new System.Drawing.Point((int)pt[3].X, (int)pt[3].Y), Emgu.CV.CvEnum.FontFace.HersheyDuplex, .75, new MCvScalar(0, 0, 255), 2);
            return(true);
        }
Beispiel #24
0
 public RotatedBox(RotatedRect pixel)
 {
     _pixel    = pixel;
     _vertices = CvInvoke.BoxPoints(_pixel);
 }
        /// <summary>
        /// 映美金获取产品特征及位置
        /// </summary>
        /// <param name="productContour"></param>
        public static void getProduceInfoForYMJ(VectorOfPoint productContour)
        {
            //#########################################【1】,获取最小外接矩形中心点下标#################################################
            RotatedRect rect = CvInvoke.MinAreaRect(productContour); //最小矩形

            PointF[] pt = CvInvoke.BoxPoints(rect);                  //最小外接矩形四个角点
            PointF   po = rect.Center;                               //最小外接矩形中心
            int      xc = (int)po.X;                                 //最小外接矩形中心X坐标
            int      yc = (int)po.Y;                                 //最小外接矩形中心Y坐标

            //#########################################【2】,绘制外接最小矩形(紧贴连通域):#################################################
            for (int i = 0; i < 4; ++i)
            {
                Point p1 = new Point((int)pt[i].X, (int)pt[i].Y);
                Point p2 = new Point((int)pt[(i + 1) % 4].X, (int)pt[(i + 1) % 4].Y);
                CvInvoke.Line(TisCamera.YMJImage, p1, p2, new MCvScalar(0, 0, 255), 8);
            }

            //#########################################【3】长轴,短轴,旋转角:#################################################
            float width  = rect.Size.Width;  //像素宽
            float height = rect.Size.Height; //像素长

            if (height > width)
            {
                float temp = height;
                height = width;
                width  = temp;
            }

            double Angl = rect.Angle;//矩形框角度

            // Angl *= 180d / Math.PI; //换算成角度制
            if (Math.Abs(Angl) > 45)
            {
                Angl = Angl + 90;
            }


            if (Angl >= 90)//控制旋转范围
            {
                Angl -= 180;
            }
            if (Angl <= -90)
            {
                Angl += 180;
            }
            GLB.obj.Angle     = Angl;                                 //旋转角
            GLB.obj.axisLong  = width * 0.466;                        //长轴  一个像素0.466mm
            GLB.obj.axisShort = height * 0.466;                       //短轴
            GLB.obj.L2S       = width / height;                       //长短轴之比;
            GLB.obj.realArea  = GLB.obj.axisLong * GLB.obj.axisShort; //估算的物件尺寸

            //像尺寸显示:
            CvInvoke.PutText(TisCamera.YMJImage, "Lr=" + (int)GLB.obj.axisLong + ",Sr=" + (int)GLB.obj.axisShort, new System.Drawing.Point((int)pt[2].X, (int)pt[2].Y), Emgu.CV.CvEnum.FontFace.HersheyDuplex, 1.75, new MCvScalar(0, 0, 255), 8);
            CvInvoke.PutText(TisCamera.YMJImage, "Angl=" + Angl, new System.Drawing.Point((int)pt[3].X, (int)pt[3].Y), Emgu.CV.CvEnum.FontFace.HersheyDuplex, 1.75, new MCvScalar(0, 0, 255), 8);

            //#########################################【4】获取质心#################################################
            MCvMoments moments = CvInvoke.Moments(productContour, false); //计算当前轮廓的矩

            int gravity_x = Convert.ToInt32(moments.M10 / moments.M00);   //计算当前轮廓中心点坐标
            int gravity_y = Convert.ToInt32(moments.M01 / moments.M00);

            GLB.obj.Depth   = 990;       //平台高度//Z
            GLB.obj.xCenter = gravity_x; //X
            GLB.obj.yCenter = gravity_y; //Y
            //#########################################【5】显示本区块中心[画圆]:#################################################
            RotatedRect boxCenter = new RotatedRect(new PointF(xc, yc), new Size(18, 18), 0);

            CvInvoke.Ellipse(TisCamera.YMJImage, boxCenter, new MCvScalar(255, 0, 0), 8);                                                                                                                                                                                      //在中心画一个小圆
            CvInvoke.PutText(TisCamera.YMJImage, "x:" + xc + "y:" + yc + "XC=" + GLB.obj.xCenter + "YC=" + GLB.obj.yCenter + "Depth=" + GLB.obj.Depth, new System.Drawing.Point(xc - 176, yc + 25), Emgu.CV.CvEnum.FontFace.HersheyDuplex, 1.75, new MCvScalar(0, 0, 255), 8); //深度显示
        }
        private MovesDetectionResult DetectMoves(CamService cam)
        {
            var maxDartContourArc   = configService.MaxContourArcValue * 1.5;
            var maxDartContourArea  = configService.MaxContourAreaValue * 1.5;
            var maxDartContourWidth = configService.MaxContourWidthValue * 1.5;

            var minDartContourArc   = configService.MinContourArcValue;
            var minDartContourArea  = configService.MinContourAreaValue;
            var minDartContourWidth = configService.MinContourWidthValue;

            var allContours = new VectorOfVectorOfPoint();

            CvInvoke.FindContours(cam.ThrowExtractedRoiFrame,
                                  allContours,
                                  new Mat(),
                                  RetrType.External,
                                  ChainApproxMethod.ChainApproxNone);

            if (!detectionEnabled || allContours.Size == 0)
            {
                return(MovesDetectionResult.Nothing);
            }

            var contourWithMaxArc   = new VectorOfPoint();
            var contourWithMaxArea  = new VectorOfPoint();
            var contourWithMaxWidth = new VectorOfPoint();

            var maxArс   = 0.0;
            var maxArea  = 0.0;
            var maxWidth = 0.0;

            for (var i = 0; i < allContours.Size; i++)
            {
                var tempContour = allContours[i];

                var tempContourArс = CvInvoke.ArcLength(tempContour, true);
                if (tempContourArс > maxArс)
                {
                    maxArс            = tempContourArс;
                    contourWithMaxArc = tempContour;
                }

                var tempContourArea = CvInvoke.ContourArea(tempContour);
                if (tempContourArea > maxArea)
                {
                    maxArea            = tempContourArea;
                    contourWithMaxArea = tempContour;
                }

                var rect             = CvInvoke.MinAreaRect(tempContour);
                var box              = CvInvoke.BoxPoints(rect);
                var contourBoxPoint1 = new PointF(box[0].X, (float)cam.roiPosYSlider + box[0].Y);
                var contourBoxPoint2 = new PointF(box[1].X, (float)cam.roiPosYSlider + box[1].Y);
                var contourBoxPoint4 = new PointF(box[3].X, (float)cam.roiPosYSlider + box[3].Y);
                var side1            = MeasureService.FindDistance(contourBoxPoint1, contourBoxPoint2);
                var side2            = MeasureService.FindDistance(contourBoxPoint4, contourBoxPoint1);
                var tempContourWidth = side1 < side2
                                           ? side1
                                           : side2;
                if (tempContourWidth > maxWidth)
                {
                    maxWidth            = tempContourWidth;
                    contourWithMaxWidth = tempContour;
                }
            }

            if (workingMode == DetectionServiceWorkingMode.Crossing ||
                maxArс >= minDartContourArc &&
                maxArс <= maxDartContourArc &&
                maxArea >= minDartContourArea &&
                maxArea <= maxDartContourArea &&
                maxWidth >= minDartContourWidth &&
                maxWidth <= maxDartContourWidth &&
                contourWithMaxArc.Equals(contourWithMaxArea) &&
                contourWithMaxArea.Equals(contourWithMaxWidth) &&
                contourWithMaxWidth.Equals(contourWithMaxArc)
                )
            {
                return(MovesDetectionResult.Throw);
            }

            if (maxArс > maxDartContourArc ||
                maxArea > maxDartContourArea ||
                maxWidth > maxDartContourWidth)
            {
                return(MovesDetectionResult.Extraction);
            }

            return(MovesDetectionResult.Nothing);
        }
        /// <summary>
        /// check whether the plate is tilted or not, if yes, rotate it.
        /// </summary>
        /// <param name="plate"></param>
        /// <param name="plate_feature"></param>
        /// <returns>rotated image</returns>
        private static Image <Gray, byte> crop_and_rotated_plate(Image <Gray, byte> plate, RotatedRect plate_feature)
        {
            PointF[] boxes = CvInvoke.BoxPoints(plate_feature);

            List <double> Xs = new List <double>();
            List <double> Ys = new List <double>();

            foreach (PointF box in boxes)
            {
                Xs.Add(box.X);
                Ys.Add(box.Y);
            }

            double Xmax = Xs.Max();
            double Ymax = Ys.Max();

            double Xmin = Xs.Min();
            double Ymin = Ys.Min();


            Rectangle r     = plate_feature.MinAreaRect();
            double    X     = r.X;
            double    Y     = r.Y;
            double    W     = r.Width;
            double    H     = r.Height;
            double    angle = plate_feature.Angle;

            float X_center = (float)(Xmax + Xmin) / 2;
            float Y_center = (float)(Ymax + Ymin) / 2;

            Size patch_size = new Size((int)(Xmax - Xmin), (int)(Ymax - Ymin));


            if (angle < (-45))
            {
                angle = angle + 90;
            }

            if (angle == 0)
            {
                return(plate);
            }


            Mat    map_matrix = new Mat(new Size(2, 3), DepthType.Cv64F, 1);
            PointF center     = new PointF(X_center, Y_center);

            CvInvoke.GetRotationMatrix2D(center, angle, 1.0, map_matrix);

            Image <Gray, byte> cropped = new Image <Gray, byte>(patch_size);

            CvInvoke.GetRectSubPix(plate, patch_size, center, cropped);

            Image <Gray, byte> warp_affine = cropped.WarpAffine(map_matrix, Inter.Linear, Warp.Default, BorderType.Default, new Gray(0));


            int warp_H = 0;
            int warp_W = 0;

            if (warp_affine.Width > warp_affine.Height)
            {
                warp_H = warp_affine.Height;
                warp_W = warp_affine.Width;
            }
            else
            {
                warp_H = warp_affine.Width;
                warp_W = warp_affine.Height;
            }

            Image <Gray, byte> output = new Image <Gray, byte>(warp_W, warp_H);

            CvInvoke.GetRectSubPix(warp_affine, new Size(warp_W, warp_H), center, output);
            //CvInvoke.Imshow("warpaffine", warp_affine);
            //CvInvoke.Imshow("GetRectSubPix", output);
            //CvInvoke.WaitKey();


            //CvInvoke.Imshow("plate", output);
            //CvInvoke.WaitKey();
            return(warp_affine);

            //return plate;
        }
        private Ray ProcessDartContour(CamService cam, DartContour dartContour)
        {
            // Moments and centerpoint
            // var contourMoments = CvInvoke.Moments(processedContour);
            // var contourCenterPoint = new PointF((float) (contourMoments.M10 / contourMoments.M00),
            //                                     (float) camService.roiPosYSlider + (float) (contourMoments.M01 / contourMoments.M00));

            // Find contour rectangle
            var rect = CvInvoke.MinAreaRect(dartContour.ContourPoints);
            var box  = CvInvoke.BoxPoints(rect);

            var contourBoxPoint1 = new PointF(box[0].X, (float)cam.roiPosYSlider + box[0].Y);
            var contourBoxPoint2 = new PointF(box[1].X, (float)cam.roiPosYSlider + box[1].Y);
            var contourBoxPoint3 = new PointF(box[2].X, (float)cam.roiPosYSlider + box[2].Y);
            var contourBoxPoint4 = new PointF(box[3].X, (float)cam.roiPosYSlider + box[3].Y);

            // Setup vertical contour middlepoints
            var    contourHeight = MeasureService.FindDistance(contourBoxPoint1, contourBoxPoint2);
            var    contourWidth  = MeasureService.FindDistance(contourBoxPoint4, contourBoxPoint1);
            PointF contourBoxMiddlePoint1;
            PointF contourBoxMiddlePoint2;

            if (contourWidth > contourHeight)
            {
                contourBoxMiddlePoint1 = MeasureService.FindMiddle(contourBoxPoint1, contourBoxPoint2);
                contourBoxMiddlePoint2 = MeasureService.FindMiddle(contourBoxPoint4, contourBoxPoint3);
            }
            else
            {
                contourBoxMiddlePoint1 = MeasureService.FindMiddle(contourBoxPoint4, contourBoxPoint1);
                contourBoxMiddlePoint2 = MeasureService.FindMiddle(contourBoxPoint3, contourBoxPoint2);
            }

            // Find spikeLine to surface
            var spikeLinePoint1 = contourBoxMiddlePoint1;
            var spikeLinePoint2 = contourBoxMiddlePoint2;
            var spikeLineLength = cam.surfaceSlider - contourBoxMiddlePoint2.Y;
            var spikeAngle      = MeasureService.FindAngle(contourBoxMiddlePoint2, contourBoxMiddlePoint1);

            spikeLinePoint1.X = (float)(contourBoxMiddlePoint2.X + Math.Cos(spikeAngle) * spikeLineLength);
            spikeLinePoint1.Y = (float)(contourBoxMiddlePoint2.Y + Math.Sin(spikeAngle) * spikeLineLength);

            // Find point of impact with surface
            PointF?camPoi = MeasureService.FindLinesIntersection(spikeLinePoint1,
                                                                 spikeLinePoint2,
                                                                 new PointF(0,
                                                                            (float)cam.surfaceSlider),
                                                                 new PointF(cam.resolutionWidth,
                                                                            (float)cam.surfaceSlider));

            // Translate cam surface POI to dartboard projection
            var frameSemiWidth             = cam.resolutionWidth / 2;
            var camFovSemiAngle            = cam.camFovAngle / 2;
            var projectionToCenter         = new PointF();
            var surfacePoiToCenterDistance = MeasureService.FindDistance(new PointF((float)cam.surfaceCenterSlider,
                                                                                    (float)cam.surfaceSlider),
                                                                         camPoi.GetValueOrDefault());
            var surfaceLeftToPoiDistance = MeasureService.FindDistance(new PointF((float)cam.surfaceCenterSlider - cam.resolutionWidth / 3,
                                                                                  (float)cam.surfaceSlider),
                                                                       camPoi.GetValueOrDefault());
            var surfaceRightToPoiDistance = MeasureService.FindDistance(new PointF((float)cam.surfaceCenterSlider + cam.resolutionWidth / 3,
                                                                                   (float)cam.surfaceSlider),
                                                                        camPoi.GetValueOrDefault());
            var projectionCamToCenterDistance = frameSemiWidth / Math.Sin(Math.PI * camFovSemiAngle / 180.0) * Math.Cos(Math.PI * camFovSemiAngle / 180.0);
            var projectionCamToPoiDistance    = Math.Sqrt(Math.Pow(projectionCamToCenterDistance, 2) + Math.Pow(surfacePoiToCenterDistance, 2));
            var projectionPoiToCenterDistance = Math.Sqrt(Math.Pow(projectionCamToPoiDistance, 2) - Math.Pow(projectionCamToCenterDistance, 2));
            var poiCamCenterAngle             = Math.Asin(projectionPoiToCenterDistance / projectionCamToPoiDistance);

            projectionToCenter.X = (float)(cam.camSetupPoint.X - Math.Cos(cam.toBullAngle) * projectionCamToCenterDistance);
            projectionToCenter.Y = (float)(cam.camSetupPoint.Y - Math.Sin(cam.toBullAngle) * projectionCamToCenterDistance);

            if (surfaceLeftToPoiDistance < surfaceRightToPoiDistance)
            {
                poiCamCenterAngle *= -1;
            }

            var projectionPoi = new PointF((float)(cam.camSetupPoint.X + Math.Cos(cam.toBullAngle + poiCamCenterAngle) * 2000),
                                           (float)(cam.camSetupPoint.Y + Math.Sin(cam.toBullAngle + poiCamCenterAngle) * 2000));

            // Draw line from cam through projection POI
            var rayPoint = projectionPoi;
            var angle    = MeasureService.FindAngle(cam.camSetupPoint, rayPoint);

            rayPoint.X = (float)(cam.camSetupPoint.X + Math.Cos(angle) * 2000);
            rayPoint.Y = (float)(cam.camSetupPoint.Y + Math.Sin(angle) * 2000);

            return(new Ray(cam.camNumber, cam.camSetupPoint, rayPoint, dartContour.Area));
        }
Beispiel #29
0
        public void Process()
        {
            if (null == this.ImageMat)
            {
                return;
            }

            try
            {
                this.OgImageMat = this.ImageMat.CreateNewHardCopyFromMat();

                //Itt megkellene nézni, hogy mik vannak minden enum mögött, hogy van-e jobb alternatíva
                //Blurring image
                var tempSize = new Size(5, 5);
                //Using input | output arrays instead of temp objects
                CvInvoke.GaussianBlur(this.ImageMat, this.ImageMat, tempSize, 0);

                MainWindow.ImageProcessorExaminer.AddImage(ImageMat.CreateNewHardCopyFromMat(), "ImageProcessor_GaussianBlur");
                //Adaptive threshold
                var tempAdaptiveThreshold = this.AdaptiveThresholdConstant;
                //Azt az 59-et majd meg kell lesni, hogy miért az van


                CvInvoke.AdaptiveThreshold(this.ImageMat, this.ImageMat, 255, Emgu.CV.CvEnum.AdaptiveThresholdType.MeanC, Emgu.CV.CvEnum.ThresholdType.BinaryInv, 59, this.AdaptiveThresholdConstant);
                MainWindow.ImageProcessorExaminer.AddImage(ImageMat.CreateNewHardCopyFromMat(), "ImageProcessor_AdaptiveThreshold");
                //Get contours and remove small patches
                Contours = new VectorOfVectorOfPoint();
                Mat hierarchy = new Mat();
                // meg kellene nézni miez ez a mat, vactorofvectorpoint és input, output és inoutputarrayek
                CvInvoke.FindContours(this.ImageMat, Contours, hierarchy, Emgu.CV.CvEnum.RetrType.List, Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxSimple);

                var dims = Contours.Size;
                for (var idx = 0; idx < dims; idx++)
                {
                    var con = Contours[idx];
                    if (!(CvInvoke.ContourArea(con) < 800))
                    {
                        continue;
                    }
                    var color = new MCvScalar(0, 0, 0);
                    //CvInvoke.FillPoly(this.ImageMat, con, color);
                    //TODO ezt lehet meg kellene még vizsgálni
                    CvInvoke.FillConvexPoly(this.ImageMat, con, color);
                }

                MainWindow.ImageProcessorExaminer.AddImage(ImageMat.CreateNewHardCopyFromMat(), "ImageProcessor_FillConvexPoly");
                //Open then close to close gaps
                var kernelMat1 = CvInvoke.GetStructuringElement(Emgu.CV.CvEnum.ElementShape.Rectangle, new Size(3, 3), new Point(-1, -1));
                CvInvoke.MorphologyEx(
                    this.ImageMat,
                    this.ImageMat,
                    Emgu.CV.CvEnum.MorphOp.Open,
                    kernelMat1,
                    new Point(-1, -1),
                    1, Emgu.CV.CvEnum.BorderType.Default,
                    new MCvScalar());
                MainWindow.ImageProcessorExaminer.AddImage(ImageMat.CreateNewHardCopyFromMat(), "ImageProcessor_MorphologyEx_Open");
                var kernelMat2 = CvInvoke.GetStructuringElement(Emgu.CV.CvEnum.ElementShape.Rectangle, new Size(7, 7), new Point(-1, -1));
                CvInvoke.MorphologyEx(
                    this.ImageMat,
                    this.ImageMat,
                    Emgu.CV.CvEnum.MorphOp.Close,
                    kernelMat2,
                    new Point(-1, -1),
                    2,
                    Emgu.CV.CvEnum.BorderType.Default,
                    new MCvScalar());
                MainWindow.ImageProcessorExaminer.AddImage(ImageMat.CreateNewHardCopyFromMat(), "ImageProcessor_MorphologyEx_Close");
                //Get new contours find the correct ones by size and hierarchy draw them onto the img, draw bounding box, and length
                CvInvoke.FindContours(this.ImageMat, Contours, hierarchy, Emgu.CV.CvEnum.RetrType.Tree, Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxSimple);
                //Empty out objects contours
                ContoursToReturn = new VectorOfVectorOfPoint();
                //Image to be overlayed, with alpha values
                //ContourImageMat = new Mat(this.ImageMat.Rows, this.ImageMat.Cols, Emgu.CV.CvEnum.DepthType.Cv8U, 4);
                ContourImageMat = OgImageMat.CreateNewHardCopyFromMat();
                CvInvoke.CvtColor(ContourImageMat, ContourImageMat, ColorConversion.Gray2Bgr);
                //ContourImageMat = new Mat(this.ImageMat.Rows, this.ImageMat.Cols, Emgu.CV.CvEnum.DepthType.Cv8U, 1);
                //MainWindow.ImageProcessorExaminer.AddImage(ContourImageMat.CreateNewHardCopyFromMat(), "ImageProcessor_ContourImageMat");
                dims = Contours.Size;

                var tempVoVoPointF = new VectorOfVectorOfPointF();

                for (var idx = 0; idx < dims; idx++)
                {
                    var con = Contours[idx];
                    //Skip small patches
                    if (CvInvoke.ContourArea(con) < 300)
                    {
                        continue;
                    }
                    //Only use ones that have parents, so the inner ones
                    //https://stackoverflow.com/questions/41560048/c-sharp-emgu-cv-findcontours-hierarchy-data-always-null
                    //https://stackoverflow.com/questions/37408481/navigate-through-hierarchy-of-contours-found-by-findcontours-method/37470968#37470968
                    //http://www.emgu.com/forum/viewtopic.php?t=6333
                    //http://www.emgu.com/forum/viewtopic.php?f=7&t=5263
                    //https://stackoverrun.com/fr/q/11437249
                    if ((int)hierarchy.GetData().GetValue(0, idx, 3) < 0)
                    {
                        continue;
                    }
                    ContoursToReturn.Push(con);
                    //UprightBoundingRectangles.Add(CvInvoke.BoundingRectangle(con));
                    //CvInvoke.DrawContours(ContourImageMat, Contours, 0, new MCvScalar(0, 255, 0, 255), 2);
                    CvInvoke.DrawContours(ContourImageMat, Contours, -1, new MCvScalar(0, 255, 0, 255), 1);

                    var rect   = CvInvoke.MinAreaRect(con);
                    var box    = CvInvoke.BoxPoints(rect);
                    var boxVec = new VectorOfPointF(box);
                    tempVoVoPointF.Push(boxVec);

                    /*
                     * var rect = CvInvoke.MinAreaRect(con);
                     * //var box = CvInvoke.BoxPoints(rect);
                     * //VectorOfPointF boxVec = new VectorOfPointF(box);
                     * VectorOfVectorOfPoint boxVec = new VectorOfVectorOfPoint(con);
                     * //az jókérdés, hogy ez most a megfelelő alak-e vagy sem
                     * CvInvoke.DrawContours(ContourImageMat, boxVec, 0, new MCvScalar(0, 255, 0, 255), 2);
                     */
                }
                MainWindow.ImageProcessorExaminer.AddImage(ContourImageMat.CreateNewHardCopyFromMat(), "ImageProcessor_ContourImageMat");
                this.AngledBoundingBoxesToReturn = tempVoVoPointF.ConvertToVectorOfPoint();

                MainWindow.ImageProcessorExaminer.AddImage(ContourImageMat.CreateNewHardCopyFromMat(), "ImageProcessor_ContourImageMat_2");
                //CvInvoke.PutText(this.ImageMat, "{" + ContoursToReturn.Size + "}", new Point(100, 300), Emgu.CV.CvEnum.FontFace.HersheySimplex, 8.0, new MCvScalar(255), 5);
                //this.DetectedCellCount = ContoursToReturn.Size;
                //MainWindow.ImageProcessorExaminer.AddImage(ImageMat.CreateNewHardCopyFromMat(), "ImageProcessor_PutText");
                //CvInvoke.EqualizeHist(this.ImageMat,this.ImageMat);

                //new PopupImage(ImageMat, "ImgProcessor_ImageMat").Show();
                //new PopupImage(ContourImageMat, "ImgProcessor_ContourImageMat").Show();
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
        }
Beispiel #30
0
        /// <summary>
        /// 获取最小外接矩形并处理相关参数
        /// </summary>
        /// <param name="contour">对应轮廓</param>
        /// <param name="block_num">编号</param>
        public bool getMinAreaRect11(VectorOfPoint contour, int block_num)
        {
            //本区块颜色定义:
            MCvScalar color = new MCvScalar(53 * block_num % 255, 255 - 73 * block_num % 255, 93 * block_num % 255);//B,G,R

            //1,获取最小外接矩形中心点的深度:
            try
            {
                RotatedRect box = CvInvoke.MinAreaRect(contour); //最小外接矩形
                PointF[]    pt  = CvInvoke.BoxPoints(box);       //最小外接矩形四个角点

                PointF po = box.Center;                          //最小外接矩形中心
                int    xc = (int)po.X;                           //最小外接矩形中心X坐标
                int    yc = (int)po.Y;                           //最小外接矩形中心Y坐标

                if (double.IsNaN(GLB.myp3d[(yc * GLB.BUFW + xc) * 3 + 2]))
                {
                    return(false);                                                  //空值不执行
                }
                GLB.obj[block_num].Depth   = (int)GLB.myp3d[(yc * GLB.BUFW + xc) * 3 + 2];
                GLB.obj[block_num].yCenter = (int)GLB.myp3d[(yc * GLB.BUFW + xc) * 3 + 1];
                GLB.obj[block_num].xCenter = (int)GLB.myp3d[(yc * GLB.BUFW + xc) * 3 + 0];

                //1b,绘制外接最小矩形(紧贴连通域):
                for (int i = 0; i < 4; ++i)
                {
                    Point p1 = new Point((int)pt[i].X, (int)pt[i].Y);
                    GLB.obj[block_num].jd.Add(p1);//角点存下备画轨迹用
                    Point p2 = new Point((int)pt[(i + 1) % 4].X, (int)pt[(i + 1) % 4].Y);
                    CvInvoke.Line(GLB.frame, p1, p2, color, 2);
                }

                List <Point3> pr = new List <Point3>();//真实角点
                for (int i = 0; i < 4; ++i)
                {
                    Point3 Ang_temp = new Point3(0, 0, 0);//0.8视场角点坐标
                    Ang_temp.X = xc + 0.8 * (pt[i].X - xc);
                    Ang_temp.Y = yc + 0.8 * (pt[i].Y - yc);

                    if (Ang_temp.Y < 0 || Ang_temp.Y > 960 - 2 || Ang_temp.X < 0 || Ang_temp.X > 1280 - 2)
                    {
                        return(false);                      //无效角点
                    }
                    Point3 Ang_point = new Point3(0, 0, 0); //0.8角点坐标
                    Ang_point.X = GLB.myp3d[((int)Ang_temp.Y * GLB.BUFW + (int)Ang_temp.X) * 3 + 0];
                    Ang_point.Y = GLB.myp3d[((int)Ang_temp.Y * GLB.BUFW + (int)Ang_temp.X) * 3 + 1];
                    Ang_point.Z = GLB.myp3d[((int)Ang_temp.Y * GLB.BUFW + (int)Ang_temp.X) * 3 + 2];
                    if (double.IsNaN(Ang_point.Z))
                    {
                        return(false);//无效角点
                    }
                    pr.Add(Ang_point);
                    RotatedRect myrect = new RotatedRect(new PointF((float)Ang_temp.X, (float)Ang_temp.Y), new Size(8, 8), 0);
                    CvInvoke.Ellipse(GLB.frame, myrect, new MCvScalar(255, 0, 0), 2);//在角上一个小圆
                }

                //GLB.obj[block_num].xCenter = (int)pr.Average(o => o.X);
                //GLB.obj[block_num].yCenter = (int)pr.Average(o => o.Y);
                //GLB.obj[block_num].Depth = (int)pr.Average(o => o.Z);//中心点的深度
                //1a,显示本区块中心[画圆]:
                RotatedRect boxCenter = new RotatedRect(new PointF(xc, yc), new Size(8, 8), 0);
                CvInvoke.Ellipse(GLB.frame, boxCenter, new MCvScalar(0, 255, 255), 4);                                                                                                                                                                                           //在中心画一个小圆
                CvInvoke.PutText(GLB.frame, "Depth=" + GLB.obj[block_num].Depth + "XC=" + GLB.obj[block_num].xCenter + "YC=" + GLB.obj[block_num].yCenter, new System.Drawing.Point(xc - 76, yc + 25), Emgu.CV.CvEnum.FontFace.HersheyDuplex, .75, new MCvScalar(0, 0, 255), 2); //深度显示
                //CvInvoke.PutText(frame, "Depth=" + GLB.obj[block_num].Depth , new System.Drawing.Point(xc - 76, yc + 25), Emgu.CV.CvEnum.FontFace.HersheyDuplex, .75, new MCvScalar(0, 0, 255), 2);//深度显示


                //真实的长轴,短轴,倾角计算:
                double axisLong  = 1.25 * Math.Sqrt(Math.Pow(pr[1].X - pr[0].X, 2) + Math.Pow(pr[1].Y - pr[0].Y, 2) + Math.Pow(pr[1].Z - pr[0].Z, 2));
                double axisShort = 1.25 * Math.Sqrt(Math.Pow(pr[2].X - pr[1].X, 2) + Math.Pow(pr[2].Y - pr[1].Y, 2) + Math.Pow(pr[2].Z - pr[1].Z, 2));
                double Angl      = box.Angle;//矩形框角度


                if (axisShort > axisLong)
                {
                    double temp = axisLong;
                    axisLong  = axisShort;
                    axisShort = temp;
                }
                //img_Angle = Angl;//显示区夹角
                if (Math.Abs(Angl) > 45)
                {
                    Angl = Angl + 90;
                }

                if (GLB.img_mode == 0) //样品匹配时用//转换到机器人坐标
                {
                    if (Angl >= 90)    //控制旋转范围
                    {
                        Angl -= 180;
                    }
                    if (Angl <= -90)
                    {
                        Angl += 180;
                    }
                }
                GLB.obj[block_num].Angle     = Angl;                 //旋转角
                GLB.obj[block_num].axisLong  = axisLong;             //长轴
                GLB.obj[block_num].axisShort = axisShort;            //短轴
                GLB.obj[block_num].L2S       = axisLong / axisShort; //长短轴之比;
                GLB.obj[block_num].SZ        = axisLong * axisShort; //估算的物件尺寸

                //像尺寸显示:
                CvInvoke.PutText(GLB.frame, "Lr=" + (int)axisLong + ",Sr=" + (int)axisShort, new System.Drawing.Point((int)pt[2].X, (int)pt[2].Y), Emgu.CV.CvEnum.FontFace.HersheyDuplex, .75, color, 2);
                CvInvoke.PutText(GLB.frame, "Angl=" + Angl, new System.Drawing.Point((int)pt[3].X, (int)pt[3].Y), Emgu.CV.CvEnum.FontFace.HersheyDuplex, .75, color, 2);
                return(true);
            }
            catch
            {
                // MessageBox.Show("有异常");
                return(false);
            }
        }