public double GetCellLengthWithBoundingBoxPoint(VectorOfPoint contour) { var tempRect = CvInvoke.MinAreaRect(contour); var boxPoints = CvInvoke.BoxPoints(tempRect); return(GetCellLengthFromBoxPoints(boxPoints)); }
/// <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) {
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); }
/// <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); }
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); } } }
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); }
/// <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); }
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); }
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); }
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); }
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); }
/// <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); }
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; }
/// <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); }
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)); }
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); } }
/// <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); } }