包安装opencvsharp,mathnet,numpy可不用,有些可以自己手敲

三个函数:最终调用函数 cirCenter()

                //cleanline清除重复线函数                  //getPoint计算交点函数

这里使用了mask,也可以不用mask.我纯是第一次做这个,借鉴一个python的代码(找不到是哪位大佬的了,属实是找了好久才找到的)

他这里直线去重是非常不好用的,我觉得使用角度判断非常好用,一般直接就得出了四条线(我觉得应该是大佬的藏拙,),但是我不懂,还是在做九点标定板上定位九个十字中心的时候发现的。我也不懂,但是就稀里糊涂的定位出来了

 public void cirCenter()
 {
     OpenCvSharp.Mat oriPic = Cv2.ImRead("C:\\Users\\LEIPENG\\source\\repos\\OnTimeCapture\\OnTimeCapture\\bin\\Debug\\Camera\\A.jpg");
     OpenCvSharp.Mat src1 = Cv2.ImRead("C:\\Users\\LEIPENG\\source\\repos\\OnTimeCapture\\OnTimeCapture\\bin\\Debug\\Camera\\A.jpg", 0);
     //OpenCvSharp.Mat src1 = Cv2.ImRead("C:\\Users\\LEIPENG\\Desktop\\nineTen.png",0);
     //Cv2.CvtColor(src, src, ColorConversionCodes.GRAY2BGR);
     OpenCvSharp.Mat gray = new OpenCvSharp.Mat(), binary = new OpenCvSharp.Mat(), vline = new OpenCvSharp.Mat();
     gray = src1;
     //二值化
     Cv2.Threshold(gray, binary, 150, 255, ThresholdTypes.BinaryInv);                                                         //形态学处理
     OpenCvSharp.Mat kernel2 = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(10, 10), new OpenCvSharp.Point(-1, -1));
     Cv2.MorphologyEx(binary, vline, MorphTypes.Open, kernel2, new OpenCvSharp.Point(-1, -1));
     Cv2.MedianBlur(vline, vline, 5);


     //Cv2.ImShow("提取边缘线前二值化图", vline);

     OpenCvSharp.Mat mat = new OpenCvSharp.Mat();
     vline.ConvertTo(vline, MatType.CV_8UC1);
     Cv2.Canny(vline, vline, 0, 150);
     //Cv2.ImShow("二值化去噪提取边缘线", vline);
     var cir = Cv2.HoughCircles(vline, HoughModes.Gradient, 1, 20, 50, 30, 0, 0);

     OpenCvSharp.Mat mask = OpenCvSharp.Mat.Zeros(vline.Size(), MatType.CV_8U); // 创建遮罩
                                                                                //Cv2.BitwiseNot(mask, mask);
                                                                                //OpenCvSharp.Point[][] contours=null;
     float x1 = cir[1].Center.X - cir[1].Radius;
     float x2 = cir[1].Center.X + cir[1].Radius;
     float y1 = cir[1].Center.Y - cir[1].Radius;
     float y2 = cir[1].Center.Y + cir[1].Radius;
     OpenCvSharp.Point point1 = new OpenCvSharp.Point(x1, cir[1].Center.Y);//左上
     OpenCvSharp.Point point2 = new OpenCvSharp.Point(cir[1].Center.X, y2);//右上
     OpenCvSharp.Point point3 = new OpenCvSharp.Point(cir[1].Center.X, y1);//左下
     OpenCvSharp.Point point4 = new OpenCvSharp.Point(x2, cir[1].Center.Y);//右下

     OpenCvSharp.Point[] poi = { point1, point2, point4, point3 };
     Cv2.ImShow("操作之前", vline);
     Cv2.DrawContours(mask, new[] { poi }, -1, new Scalar(255), -1);
     Cv2.ImShow("mask画矩形", mask);


     OpenCvSharp.Mat invertedMask = new OpenCvSharp.Mat();
     Cv2.BitwiseAnd(vline, vline, invertedMask, mask: mask);//实现遮罩///已经用不到
     //invertedMask = vline;
     Mat edges = new Mat();
     //Cv2.Canny(invertedMask, edges, 45, 135);
     edges = vline;
     Cv2.ImShow("HoughLines操作之前", invertedMask);
     var lines = Cv2.HoughLines(edges, 1, Cv2.PI / 180, 120);

     List<LineSegmentPolar> list = cleanline(lines);

     Point[] point = getPoint(list).ToArray();

     foreach (var line in list)
     {
         var rho = line.Rho;
         var theta = line.Theta;
         var a = Math.Cos(theta);
         var b = Math.Sin(theta);
         var x0 = a * rho;
         var y0 = b * rho;
         var x11 = Convert.ToInt32(x0 + 2000 * (-b));
         var y11 = Convert.ToInt32(y0 + 2000 * (a));
         var x22 = Convert.ToInt32(x0 - 2000 * (-b));
         var y22 = Convert.ToInt32(y0 - 2000 * (a));
         Cv2.Line(oriPic, new Point(x11, y11), new Point(x22, y22), Scalar.Lime, 1);
         Cv2.Line(invertedMask, new Point(x11, y11), new Point(x22, y22), Scalar.White, 1);
     }
     var sumx = 0;
     var sumy = 0;
     foreach (var item in point)
     {
         Cv2.Circle(src1, Convert.ToInt32(item.X), Convert.ToInt32(item.Y), 3, Scalar.Lime);
         sumx += item.X;
         sumy += item.Y;
     }
     var midx = sumx / point.Length;
     var midy = sumy / point.Length;
     Cv2.Circle(oriPic, Convert.ToInt32(midx), Convert.ToInt32(midy), 3, Scalar.Lime);
     Cv2.Circle(invertedMask, Convert.ToInt32(midx), Convert.ToInt32(midy), 2, Scalar.White);
     Cv2.ImShow("res", oriPic);
     Cv2.ImShow("vline使用bitand +mask", invertedMask);
 }

 List<LineSegmentPolar> cleanline(LineSegmentPolar[] lines)
 {
     for (int i = 0; i < lines.Length; i++)
     {
         if (lines[i].Rho < 0)
         {
             lines[i].Rho = -lines[i].Rho;
             lines[i].Theta = (float)(lines[i].Theta - Cv2.PI);
         }
     }
     List<LineSegmentPolar> listcopy = new List<LineSegmentPolar>();
     //listcopy = lines.ToList();

     List<LineSegmentPolar> list = new List<LineSegmentPolar>();
     list.Add(lines[0]);
     for (int i = 1; i < lines.Length; i++)
     {
         listcopy.Add(lines[i]);
     }

     foreach (var line in listcopy)
     {
         string flag = "0";
         foreach (var star in list)
         {
             if (Math.Abs(line.Rho - star.Rho) < 10 && Math.Abs(line.Theta - star.Theta) < 0.1)
             {
                 flag = "1";
             }

         }

         if (flag == "0")
         {
             list.Add(line);
         }
     }
     return list;
 }
 List<OpenCvSharp.Point> getPoint(List<LineSegmentPolar> lines)
 {
     //OpenCvSharp.Point[] points=new Point[] { };
     List<Point> points = new List<Point>();
     if (lines.Count == 4)
     {
         List<LineSegmentPolar> horline = new List<LineSegmentPolar>();
         List<LineSegmentPolar> verline = new List<LineSegmentPolar>();
         foreach (var line in lines)
         {
             if ((line.Theta > (0 - 0.1)) && line.Theta < (0 + 0.1))
             {
                 horline.Add(line);
             }
             else
             {
                 verline.Add(line);
             }
         }
         int i = 0;
         foreach (var l1 in horline)
         {
             foreach (var l2 in verline)
             {
                 double[,] a = new double[,] { { Math.Cos(l1.Theta), Math.Sin(l1.Theta) },
                     { Math.Cos(l2.Theta), Math.Sin(l2.Theta) } };
                 double[] b = new double[] { l1.Rho, l2.Rho };

                 var d = Numpy.np.linalg.solve(a, b);
                 var d1 = Convert.ToDouble(d.data[0].ToString());
                 var d2 = Convert.ToDouble(d.data[1].ToString());
                 Point point = new Point(d1, d2);
                 points.Add(point);
                 i++;
             }
         }
     }
     return points;
 }

更多推荐