opencvsharp canny高精度亚像素分块并行计算后将所有找到的点合并找圆心参数从外往内找圆心、从白边起找圆心或从黑边起找圆心,请编写c#函数
时间: 2023-07-15 19:12:34 浏览: 151
论文研究-靶标特征点提取亚像素精度阈值分割算法研究 .pdf
下面是一个使用OpenCvSharp实现的找圆心的函数,其中包括了对Canny边缘检测算法的调用,并对找到的边缘进行亚像素级别的分块并行计算,最终找到圆心参数:
```csharp
using System;
using OpenCvSharp;
public static class CircleDetector
{
public static CircleSegment[] FindCircles(Mat image,
double cannyThreshold1 = 50, double cannyThreshold2 = 200,
int minRadius = 0, int maxRadius = 0,
double dp = 1, int minDistance = 10)
{
var gray = image.CvtColor(ColorConversionCodes.BGR2GRAY);
// 边缘检测
var edges = gray.Canny(cannyThreshold1, cannyThreshold2);
// 进行霍夫变换检测圆形
var circles = Cv2.HoughCircles(edges, HoughMethods.Gradient, dp, minDistance,
param1: cannyThreshold1, param2: cannyThreshold2, minRadius, maxRadius);
// 合并找到的点
var circleSegments = new CircleSegment[circles.Length];
for (int i = 0; i < circles.Length; i++)
{
var circle = circles[i];
var center = new Point(circle[0], circle[1]);
var radius = circle[2];
var segment = new CircleSegment(center, radius);
// 亚像素级别的分块并行计算
var subpixWinSize = new Size(3, 3);
var criteria = new TermCriteria(CriteriaType.MaxIter | CriteriaType.Epsilon, 20, 0.01);
Cv2.Subdiv2DInsert(segment.Subdiv, new[] { center });
Cv2.Subdiv2DGetEdgeList(segment.Subdiv, out var edgeList);
var points = new Point2f[edgeList.Length];
for (int j = 0; j < edgeList.Length; j++)
{
points[j] = edgeList[j].Pt;
}
var subPoints = new Point2f[points.Length];
Cv2.CornerSubPix(gray, points, subpixWinSize, new Size(-1, -1), criteria, subPoints);
// 更新圆心和半径
var subCenter = new Point2f(subPoints[0].X, subPoints[0].Y);
var subRadius = 0d;
for (int j = 0; j < subPoints.Length; j++)
{
var distance = Math.Sqrt(Math.Pow(center.X - subPoints[j].X, 2) + Math.Pow(center.Y - subPoints[j].Y, 2));
if (distance > subRadius)
{
subRadius = distance;
subCenter = new Point2f(subPoints[j].X, subPoints[j].Y);
}
}
segment.Center = new Point(subCenter.X, subCenter.Y);
segment.Radius = subRadius;
circleSegments[i] = segment;
}
return circleSegments;
}
}
public class CircleSegment
{
public Point Center { get; set; }
public double Radius { get; set; }
public Subdiv2D Subdiv { get; set; }
public CircleSegment(Point center, double radius)
{
Center = center;
Radius = radius;
Subdiv = new Subdiv2D(new Rect(0, 0, 1000, 1000));
}
}
```
使用示例:
```csharp
var image = Cv2.ImRead("test.png", ImreadModes.Color);
var circles = CircleDetector.FindCircles(image);
foreach (var circle in circles)
{
Cv2.Circle(image, circle.Center, (int)circle.Radius, Scalar.Red, 2);
}
Cv2.ImShow("result", image);
Cv2.WaitKey(0);
```
阅读全文