OpenCvSharp4.6 编写多线程CircularCaliper找圆心函数 , 输入图像、找圆扇形区域的最小半径和最大半径、找圆扇形中心点、设定扇形区域起始角度、扇形区域结束角度 输入Caliper个数,宽度、长度、 输入从内到外找圆心、从黑到白找圆 输入canny参数 并行计Caliper区域,将Caliper区域所有canny点合并,拟合圆心 输出圆中心点、半径请编写函数
时间: 2023-07-10 08:07:27 浏览: 85
opencv 在图像中绘制点,直线,线段,矩形,圆形,椭圆的方法,并用函数实现,代码非常有用,简单易懂。
下面是一个基本的多线程CircularCaliper找圆心的函数实现:
```csharp
public static void FindCircleCenter(Mat input, int minRadius, int maxRadius, Point center,
double startAngle, double endAngle, int calipers, int caliperWidth, int caliperLength,
bool fromInsideToOutside, bool fromBlackToWhite, int cannyThreshold1, int cannyThreshold2,
out Point circleCenter, out int circleRadius)
{
// 初始化输出参数
circleCenter = new Point(-1, -1);
circleRadius = -1;
// 获得图像的边缘
Mat edges = new Mat();
Cv2.Canny(input, edges, cannyThreshold1, cannyThreshold2);
// 计算圆心和半径的搜索范围
int centerXMin = center.X - maxRadius;
int centerXMax = center.X + maxRadius;
int centerYMin = center.Y - maxRadius;
int centerYMax = center.Y + maxRadius;
int radiusMin = minRadius;
int radiusMax = maxRadius;
// 根据计算方向确定搜索范围
if (fromInsideToOutside)
{
centerXMin = center.X - minRadius;
centerXMax = center.X + minRadius;
centerYMin = center.Y - minRadius;
centerYMax = center.Y + minRadius;
radiusMin = minRadius;
radiusMax = maxRadius;
}
// 创建用于存储每个Caliper的结果的列表
List<Tuple<Point, Point>> caliperResults = new List<Tuple<Point, Point>>();
// 创建并行任务
Parallel.For(0, calipers, i =>
{
// 计算当前Caliper的角度
double angle = startAngle + (endAngle - startAngle) * ((double)i / (double)calipers);
// 计算当前Caliper的起点和终点
Point startPoint = new Point(center.X + (int)(Math.Cos(angle) * radiusMin),
center.Y + (int)(Math.Sin(angle) * radiusMin));
Point endPoint = new Point(center.X + (int)(Math.Cos(angle) * radiusMax),
center.Y + (int)(Math.Sin(angle) * radiusMax));
// 计算当前Caliper的方向
Point direction = new Point(endPoint.X - startPoint.X, endPoint.Y - startPoint.Y);
double length = Math.Sqrt(direction.X * direction.X + direction.Y * direction.Y);
direction.X /= length;
direction.Y /= length;
// 计算当前Caliper的法向量
Point normal = new Point(direction.Y, -direction.X);
// 在当前Caliper上搜索边缘点
List<Point> edgePoints = new List<Point>();
for (int j = 0; j < caliperLength; j++)
{
Point point = new Point(startPoint.X + (int)(direction.X * j) - (int)(normal.X * caliperWidth / 2),
startPoint.Y + (int)(direction.Y * j) - (int)(normal.Y * caliperWidth / 2));
Point edgePoint = FindEdgePoint(edges, point, normal, fromBlackToWhite);
if (edgePoint.X != -1 && edgePoint.Y != -1)
{
edgePoints.Add(edgePoint);
}
}
// 将当前Caliper的结果添加到列表中
if (edgePoints.Count > 0)
{
caliperResults.Add(new Tuple<Point, Point>(startPoint, edgePoints[edgePoints.Count / 2]));
}
});
// 合并所有Caliper的结果
List<Point> allEdgePoints = new List<Point>();
foreach (Tuple<Point, Point> result in caliperResults)
{
allEdgePoints.Add(result.Item2);
}
// 拟合圆心和半径
if (allEdgePoints.Count >= 3)
{
Point2f[] points = allEdgePoints.Select(p => new Point2f(p.X, p.Y)).ToArray();
Cv2.MinEnclosingCircle(points, out Point2f centerPoint, out float radius);
circleCenter = new Point((int)centerPoint.X, (int)centerPoint.Y);
circleRadius = (int)radius;
}
}
// 在给定的点和法向量方向上搜索边缘点
public static Point FindEdgePoint(Mat edges, Point point, Point normal, bool fromBlackToWhite)
{
int x = point.X;
int y = point.Y;
while (x >= 0 && x < edges.Width && y >= 0 && y < edges.Height)
{
if (edges.At<byte>(y, x) != 0)
{
return new Point(x, y);
}
x += normal.X;
y += normal.Y;
}
return new Point(-1, -1);
}
```
这个函数使用了并行计算来提高效率,并通过参数传递来支持不同的搜索方式和设置。请注意,这只是一个基本的实现,可能需要根据实际需求进行修改和改进。
阅读全文